mirror of
https://github.com/glest/glest-source.git
synced 2025-02-25 04:02:30 +01:00
- changed selection code to use color picking, can disable using new ini setting:
EnableColorPicking=false
This commit is contained in:
parent
3ed8b3a58a
commit
2dd2afb296
@ -1061,6 +1061,7 @@ static Vec2i _unprojectMap(const Vec2i& pt,const GLdouble* model,const GLdouble*
|
||||
// return ( translation * orientation );
|
||||
//}
|
||||
|
||||
|
||||
bool Renderer::ExtractFrustum(VisibleQuadContainerCache &quadCacheItem) {
|
||||
bool frustrumChanged = false;
|
||||
vector<float> proj(16,0);
|
||||
@ -1297,6 +1298,20 @@ bool Renderer::PointInFrustum(vector<vector<float> > &frustum, float x, float y,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Renderer::SphereInFrustum(vector<vector<float> > &frustum, float x, float y, float z, float radius) {
|
||||
// Go through all the sides of the frustum
|
||||
for(int i = 0; i < frustum.size(); i++ ) {
|
||||
// If the center of the sphere is farther away from the plane than the radius
|
||||
if(frustum[i][0] * x + frustum[i][1] * y + frustum[i][2] * z + frustum[i][3] <= -radius ) {
|
||||
// The distance was greater than the radius so the sphere is outside of the frustum
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The sphere was inside of the frustum!
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Renderer::CubeInFrustum(vector<vector<float> > &frustum, float x, float y, float z, float size ) {
|
||||
unsigned int p=0;
|
||||
|
||||
@ -5744,63 +5759,256 @@ Vec3f Renderer::computeScreenPosition(const Vec3f &worldPos) {
|
||||
return screenPos;
|
||||
}
|
||||
|
||||
void Renderer::computeSelected( Selection::UnitContainer &units, const Object *&obj, const bool withObjectSelection,
|
||||
void Renderer::computeSelected( Selection::UnitContainer &units, const Object *&obj,
|
||||
const bool withObjectSelection,
|
||||
const Vec2i &posDown, const Vec2i &posUp) {
|
||||
|
||||
//declarations
|
||||
GLuint selectBuffer[Gui::maxSelBuff];
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
|
||||
//compute center and dimensions of selection rectangle
|
||||
int x= (posDown.x+posUp.x) / 2;
|
||||
int y= (posDown.y+posUp.y) / 2;
|
||||
int w= abs(posDown.x-posUp.x);
|
||||
int h= abs(posDown.y-posUp.y);
|
||||
if(w<1) w=1;
|
||||
if(h<1) h=1;
|
||||
|
||||
//setup matrices
|
||||
glSelectBuffer(Gui::maxSelBuff, selectBuffer);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()};
|
||||
glRenderMode(GL_SELECT);
|
||||
glLoadIdentity();
|
||||
gluPickMatrix(x, y, w, h, view);
|
||||
gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane);
|
||||
loadGameCameraMatrix();
|
||||
|
||||
//render units to find which ones should be selected
|
||||
renderUnitsFast();
|
||||
if(withObjectSelection){
|
||||
renderObjectsFast(false,true);
|
||||
int x = (posDown.x+posUp.x) / 2;
|
||||
int y = (posDown.y+posUp.y) / 2;
|
||||
int w = abs(posDown.x-posUp.x);
|
||||
int h = abs(posDown.y-posUp.y);
|
||||
if(w < 1) {
|
||||
w = 1;
|
||||
}
|
||||
if(h < 1) {
|
||||
h = 1;
|
||||
}
|
||||
|
||||
//pop matrices
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
const bool newPickingSelection = Config::getInstance().getBool("EnableColorPicking","true");
|
||||
if(newPickingSelection == true) {
|
||||
int x1 = posDown.x;
|
||||
int y1 = posDown.y;
|
||||
int x2 = posUp.x;
|
||||
int y2 = posUp.y;
|
||||
|
||||
x = min(x1,x2);
|
||||
y = min(y1,y2);
|
||||
w = max(x1,x2) - min(x1,x2);
|
||||
h = max(y1,y2) - min(y1,y2);
|
||||
if(w < 1) {
|
||||
w = 1;
|
||||
}
|
||||
if(h < 1) {
|
||||
h = 1;
|
||||
}
|
||||
|
||||
x= (x * metrics.getScreenW() / metrics.getVirtualW());
|
||||
y= (y * metrics.getScreenH() / metrics.getVirtualH());
|
||||
|
||||
w= (w * metrics.getScreenW() / metrics.getVirtualW());
|
||||
h= (h * metrics.getScreenH() / metrics.getVirtualH());
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
//GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()};
|
||||
//gluPickMatrix(x, y, w, h, view);
|
||||
gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane);
|
||||
loadGameCameraMatrix();
|
||||
|
||||
//render units to find which ones should be selected
|
||||
//printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
vector<Unit *> rendererUnits = renderUnitsFast(false, newPickingSelection);
|
||||
|
||||
//printf("In [%s::%s] Line: %d rendererUnits = %d\n",__FILE__,__FUNCTION__,__LINE__,rendererUnits.size());
|
||||
|
||||
vector<Object *> rendererObjects;
|
||||
if(withObjectSelection == true) {
|
||||
rendererObjects = renderObjectsFast(false,true,newPickingSelection);
|
||||
}
|
||||
//printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
//pop matrices
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
||||
// Added this to ensure all the selection calls are done now
|
||||
// (see http://www.unknownroad.com/rtfm/graphics/glselection.html section: [0x4])
|
||||
glFlush();
|
||||
|
||||
//GraphicsInterface::getInstance().getCurrentContext()->swapBuffers();
|
||||
|
||||
//printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
vector<BaseColorPickEntity *> rendererModels;
|
||||
for(unsigned int i = 0; i < rendererObjects.size(); ++i) {
|
||||
Object *object = rendererObjects[i];
|
||||
rendererModels.push_back(object);
|
||||
//printf("In [%s::%s] Line: %d rendered object i = %d [%s] [%s]\n",__FILE__,__FUNCTION__,__LINE__,i,object->getUniquePickName().c_str(),object->getColorDescription().c_str());
|
||||
|
||||
//printf("In [%s::%s] Line: %d\ni = %d [%d - %s] ptr[%p] color[%s]\n",__FILE__,__FUNCTION__,__LINE__,i,unit->getId(),unit->getType()->getName().c_str(),unit->getCurrentModelPtr(),unit->getColorDescription().c_str());
|
||||
}
|
||||
|
||||
//printf("In [%s::%s] Line: %d\nLooking for picks inside [%d,%d,%d,%d] posdown [%s] posUp [%s]",__FILE__,__FUNCTION__,__LINE__,x,y,w,h,posDown.getString().c_str(),posUp.getString().c_str());
|
||||
//select units by checking the selected buffer
|
||||
//vector<BaseColorPickEntity *> rendererModels;
|
||||
for(unsigned int i = 0; i < rendererUnits.size(); ++i) {
|
||||
Unit *unit = rendererUnits[i];
|
||||
rendererModels.push_back(unit);
|
||||
//printf("In [%s::%s] Line: %d rendered unit i = %d [%s] [%s]\n",__FILE__,__FUNCTION__,__LINE__,i,unit->getUniquePickName().c_str(),unit->getColorDescription().c_str());
|
||||
|
||||
//printf("In [%s::%s] Line: %d\ni = %d [%d - %s] ptr[%p] color[%s]\n",__FILE__,__FUNCTION__,__LINE__,i,unit->getId(),unit->getType()->getName().c_str(),unit->getCurrentModelPtr(),unit->getColorDescription().c_str());
|
||||
}
|
||||
//printf("In [%s::%s] Line: %d\nLooking for picks inside [%d,%d,%d,%d] posdown [%s] posUp [%s]",__FILE__,__FUNCTION__,__LINE__,x,y,w,h,posDown.getString().c_str(),posUp.getString().c_str());
|
||||
|
||||
//vector<int> pickedList = BaseColorPickEntity::getPickedList(x,y,w,h, rendererModels);
|
||||
|
||||
vector<int> pickedList = BaseColorPickEntity::getPickedList(x,y,w,h, rendererModels);
|
||||
//printf("In [%s::%s] Line: %d pickedList = %d models rendered = %d\n",__FILE__,__FUNCTION__,__LINE__,pickedList.size(),rendererModels.size());
|
||||
|
||||
if(pickedList.empty() == false) {
|
||||
for(int i = 0; i < pickedList.size(); ++i) {
|
||||
int index = pickedList[i];
|
||||
|
||||
//printf("In [%s::%s] Line: %d searching for selected object i = %d index = %d units = %d objects = %d\n",__FILE__,__FUNCTION__,__LINE__,i,index,rendererUnits.size(),rendererObjects.size());
|
||||
|
||||
if(rendererObjects.size() > 0 && index < rendererObjects.size()) {
|
||||
Object *object = rendererObjects[index];
|
||||
//printf("In [%s::%s] Line: %d searching for selected object i = %d index = %d [%p]\n",__FILE__,__FUNCTION__,__LINE__,i,index,object);
|
||||
|
||||
if(object != NULL) {
|
||||
obj = object;
|
||||
if(withObjectSelection == true) {
|
||||
//printf("In [%s::%s] Line: %d found selected object [%p]\n",__FILE__,__FUNCTION__,__LINE__,obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
index -= rendererObjects.size();
|
||||
Unit *unit = rendererUnits[index];
|
||||
if(unit != NULL && unit->isAlive()) {
|
||||
units.push_back(unit);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// vector<int> pickedList = BaseColorPickEntity::getPickedList(x,y,w,h, rendererModels);
|
||||
// //printf("In [%s::%s] Line: %d pickedList = %d\n",__FILE__,__FUNCTION__,__LINE__,pickedList.size());
|
||||
//
|
||||
// if(pickedList.empty() == false) {
|
||||
// for(int i = 0; i < pickedList.size(); ++i) {
|
||||
// int index = pickedList[i];
|
||||
// Unit *unit = rendererUnits[index];
|
||||
// if(unit != NULL && unit->isAlive()) {
|
||||
// units.push_back(unit);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//printf("In [%s::%s] Line: %d units = %d\n",__FILE__,__FUNCTION__,__LINE__,units.size());
|
||||
|
||||
|
||||
/* Frustrum approach --> Currently not accurate enough
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()};
|
||||
gluPickMatrix(x, y, w, h, view);
|
||||
gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane);
|
||||
loadGameCameraMatrix();
|
||||
|
||||
VisibleQuadContainerCache quadSelectionCacheItem;
|
||||
ExtractFrustum(quadSelectionCacheItem);
|
||||
|
||||
//pop matrices
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
||||
//select units by checking the selected buffer
|
||||
int selCount= glRenderMode(GL_RENDER);
|
||||
if(selCount > 0) {
|
||||
VisibleQuadContainerCache &qCache = getQuadCache();
|
||||
for(int i=1; i <= selCount; ++i) {
|
||||
int index= selectBuffer[i*4-1];
|
||||
if(index>=OBJECT_SELECT_OFFSET)
|
||||
{
|
||||
Object *object = qCache.visibleObjectList[index-OBJECT_SELECT_OFFSET];
|
||||
if(object != NULL) {
|
||||
obj=object;
|
||||
if(withObjectSelection) {
|
||||
break;
|
||||
if(qCache.visibleQuadUnitList.empty() == false) {
|
||||
for(int visibleUnitIndex = 0;
|
||||
visibleUnitIndex < qCache.visibleQuadUnitList.size(); ++visibleUnitIndex) {
|
||||
Unit *unit = qCache.visibleQuadUnitList[visibleUnitIndex];
|
||||
if(unit != NULL && unit->isAlive()) {
|
||||
Vec3f unitPos = unit->getCurrVector();
|
||||
bool insideQuad = CubeInFrustum(quadSelectionCacheItem.frustumData,
|
||||
unitPos.x, unitPos.y, unitPos.z, unit->getType()->getSize());
|
||||
if(insideQuad == true) {
|
||||
units.push_back(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit *unit = qCache.visibleQuadUnitList[index];
|
||||
if(unit != NULL && unit->isAlive()) {
|
||||
units.push_back(unit);
|
||||
}
|
||||
|
||||
if(withObjectSelection == true) {
|
||||
if(qCache.visibleObjectList.empty() == false) {
|
||||
for(int visibleIndex = 0;
|
||||
visibleIndex < qCache.visibleObjectList.size(); ++visibleIndex) {
|
||||
Object *object = qCache.visibleObjectList[visibleIndex];
|
||||
if(object != NULL) {
|
||||
bool insideQuad = CubeInFrustum(quadSelectionCacheItem.frustumData,
|
||||
object->getPos().x, object->getPos().y, object->getPos().z, 1);
|
||||
if(insideQuad == true) {
|
||||
obj = object;
|
||||
if(withObjectSelection == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
else {
|
||||
//declarations
|
||||
GLuint selectBuffer[Gui::maxSelBuff];
|
||||
|
||||
//setup matrices
|
||||
glSelectBuffer(Gui::maxSelBuff, selectBuffer);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
GLint view[]= {0, 0, metrics.getVirtualW(), metrics.getVirtualH()};
|
||||
glRenderMode(GL_SELECT);
|
||||
glLoadIdentity();
|
||||
gluPickMatrix(x, y, w, h, view);
|
||||
gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, perspFarPlane);
|
||||
loadGameCameraMatrix();
|
||||
|
||||
//render units to find which ones should be selected
|
||||
renderUnitsFast();
|
||||
if(withObjectSelection == true) {
|
||||
renderObjectsFast(false,true);
|
||||
}
|
||||
|
||||
//pop matrices
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
||||
// Added this to ensure all the selection calls are done now
|
||||
// (see http://www.unknownroad.com/rtfm/graphics/glselection.html section: [0x4])
|
||||
glFlush();
|
||||
|
||||
//select units by checking the selected buffer
|
||||
int selCount= glRenderMode(GL_RENDER);
|
||||
if(selCount > 0) {
|
||||
VisibleQuadContainerCache &qCache = getQuadCache();
|
||||
for(int i = 1; i <= selCount; ++i) {
|
||||
int index = selectBuffer[i*4-1];
|
||||
if(index >= OBJECT_SELECT_OFFSET) {
|
||||
Object *object = qCache.visibleObjectList[index - OBJECT_SELECT_OFFSET];
|
||||
if(object != NULL) {
|
||||
obj = object;
|
||||
if(withObjectSelection == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Unit *unit = qCache.visibleQuadUnitList[index];
|
||||
if(unit != NULL && unit->isAlive()) {
|
||||
units.push_back(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6268,16 +6476,17 @@ Vec4f Renderer::computeWaterColor(float waterLevel, float cellHeight) {
|
||||
// ==================== fast render ====================
|
||||
|
||||
//render units for selection purposes
|
||||
void Renderer::renderUnitsFast(bool renderingShadows) {
|
||||
vector<Unit *> Renderer::renderUnitsFast(bool renderingShadows, bool colorPickingSelection) {
|
||||
vector<Unit *> unitsList;
|
||||
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
|
||||
return;
|
||||
return unitsList;
|
||||
}
|
||||
|
||||
assert(game != NULL);
|
||||
const World *world= game->getWorld();
|
||||
assert(world != NULL);
|
||||
|
||||
assertGl();
|
||||
//assertGl();
|
||||
|
||||
bool modelRenderStarted = false;
|
||||
VisibleQuadContainerCache &qCache = getQuadCache();
|
||||
@ -6288,35 +6497,54 @@ void Renderer::renderUnitsFast(bool renderingShadows) {
|
||||
|
||||
if(modelRenderStarted == false) {
|
||||
modelRenderStarted = true;
|
||||
//glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT);
|
||||
glDisable(GL_LIGHTING);
|
||||
if (renderingShadows == false) {
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if(colorPickingSelection == false) {
|
||||
//glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT);
|
||||
glDisable(GL_LIGHTING);
|
||||
if (renderingShadows == false) {
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
else {
|
||||
glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glAlphaFunc(GL_GREATER, 0.4f);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
//set color to the texture alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
|
||||
//set alpha to the texture alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
else {
|
||||
glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glAlphaFunc(GL_GREATER, 0.4f);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
//set color to the texture alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
|
||||
//set alpha to the texture alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
//assertGl();
|
||||
|
||||
modelRenderer->begin(false, renderingShadows, false);
|
||||
glInitNames();
|
||||
|
||||
//assertGl();
|
||||
|
||||
if(colorPickingSelection == true) {
|
||||
BaseColorPickEntity::beginPicking();
|
||||
}
|
||||
else {
|
||||
glInitNames();
|
||||
}
|
||||
|
||||
//assertGl();
|
||||
}
|
||||
|
||||
glPushName(visibleUnitIndex);
|
||||
if(colorPickingSelection == false) {
|
||||
glPushName(visibleUnitIndex);
|
||||
}
|
||||
|
||||
//assertGl();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
//debuxar modelo
|
||||
@ -6332,25 +6560,55 @@ void Renderer::renderUnitsFast(bool renderingShadows) {
|
||||
//render
|
||||
Model *model= unit->getCurrentModelPtr();
|
||||
model->updateInterpolationVertices(unit->getAnimProgress(), unit->isAlive() && !unit->isAnimProgressBound());
|
||||
|
||||
if(colorPickingSelection == true) {
|
||||
unit->setUniquePickingColor();
|
||||
unitsList.push_back(unit);
|
||||
|
||||
//assertGl();
|
||||
}
|
||||
|
||||
//assertGl();
|
||||
|
||||
modelRenderer->render(model);
|
||||
|
||||
glPopMatrix();
|
||||
glPopName();
|
||||
|
||||
if(colorPickingSelection == false) {
|
||||
glPopName();
|
||||
}
|
||||
|
||||
//assertGl();
|
||||
}
|
||||
|
||||
if(modelRenderStarted == true) {
|
||||
//assertGl();
|
||||
|
||||
modelRenderer->end();
|
||||
glPopAttrib();
|
||||
|
||||
//assertGl();
|
||||
|
||||
if(colorPickingSelection == true) {
|
||||
BaseColorPickEntity::endPicking();
|
||||
}
|
||||
else {
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
// assertGl();
|
||||
}
|
||||
}
|
||||
|
||||
assertGl();
|
||||
// assertGl();
|
||||
|
||||
return unitsList;
|
||||
}
|
||||
|
||||
//render objects for selection purposes
|
||||
void Renderer::renderObjectsFast(bool renderingShadows, bool resourceOnly) {
|
||||
vector<Object *> Renderer::renderObjectsFast(bool renderingShadows, bool resourceOnly, bool colorPickingSelection) {
|
||||
vector<Object *> objectList;
|
||||
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
|
||||
return;
|
||||
return objectList;
|
||||
}
|
||||
|
||||
//const World *world= game->getWorld();
|
||||
@ -6370,54 +6628,86 @@ void Renderer::renderObjectsFast(bool renderingShadows, bool resourceOnly) {
|
||||
if(modelRenderStarted == false) {
|
||||
modelRenderStarted = true;
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
if(colorPickingSelection == false) {
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if (renderingShadows == false){
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if (renderingShadows == false){
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
else {
|
||||
glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT);
|
||||
glAlphaFunc(GL_GREATER, 0.5f);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
//set color to the texture alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
|
||||
//set alpha to the texture alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
modelRenderer->begin(false, renderingShadows, false);
|
||||
|
||||
if(colorPickingSelection == true) {
|
||||
BaseColorPickEntity::beginPicking();
|
||||
}
|
||||
else {
|
||||
glPushAttrib(GL_ENABLE_BIT| GL_TEXTURE_BIT);
|
||||
glAlphaFunc(GL_GREATER, 0.5f);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
//set color to the texture alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
|
||||
|
||||
//set alpha to the texture alpha
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
glInitNames();
|
||||
}
|
||||
modelRenderer->begin(false, renderingShadows, false);
|
||||
glInitNames();
|
||||
}
|
||||
if(!resourceOnly || o->getResource()!= NULL){
|
||||
|
||||
if(resourceOnly == false || o->getResource()!= NULL) {
|
||||
Model *objModel= o->getModelPtr();
|
||||
const Vec3f &v= o->getConstPos();
|
||||
glPushName(OBJECT_SELECT_OFFSET+visibleIndex);
|
||||
|
||||
if(colorPickingSelection == false) {
|
||||
glPushName(OBJECT_SELECT_OFFSET+visibleIndex);
|
||||
}
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glTranslatef(v.x, v.y, v.z);
|
||||
glRotatef(o->getRotation(), 0.f, 1.f, 0.f);
|
||||
|
||||
if(colorPickingSelection == true) {
|
||||
o->setUniquePickingColor();
|
||||
objectList.push_back(o);
|
||||
|
||||
//assertGl();
|
||||
}
|
||||
|
||||
modelRenderer->render(objModel);
|
||||
|
||||
glPopMatrix();
|
||||
glPopName();
|
||||
|
||||
if(colorPickingSelection == false) {
|
||||
glPopName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(modelRenderStarted == true) {
|
||||
modelRenderer->end();
|
||||
glPopAttrib();
|
||||
|
||||
if(colorPickingSelection == true) {
|
||||
BaseColorPickEntity::endPicking();
|
||||
}
|
||||
else {
|
||||
glPopAttrib();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertGl();
|
||||
|
||||
return objectList;
|
||||
}
|
||||
|
||||
// ==================== gl caps ====================
|
||||
|
@ -249,6 +249,7 @@ private:
|
||||
Quad2i visibleQuadFromCamera;
|
||||
Vec4f nearestLightPos;
|
||||
VisibleQuadContainerCache quadCache;
|
||||
VisibleQuadContainerCache quadCacheSelection;
|
||||
|
||||
//renderers
|
||||
ModelRenderer *modelRenderer;
|
||||
@ -370,6 +371,7 @@ private:
|
||||
|
||||
bool ExtractFrustum(VisibleQuadContainerCache &quadCacheItem);
|
||||
bool PointInFrustum(vector<vector<float> > &frustum, float x, float y, float z );
|
||||
bool SphereInFrustum(vector<vector<float> > &frustum, float x, float y, float z, float radius);
|
||||
bool CubeInFrustum(vector<vector<float> > &frustum, float x, float y, float z, float size );
|
||||
|
||||
private:
|
||||
@ -580,8 +582,8 @@ private:
|
||||
void checkExtension(const string &extension, const string &msg);
|
||||
|
||||
//selection render
|
||||
void renderObjectsFast(bool renderingShadows = false, bool resourceOnly = false);
|
||||
void renderUnitsFast(bool renderingShadows = false);
|
||||
vector<Object *> renderObjectsFast(bool renderingShadows = false, bool resourceOnly = false, bool colorPickingSelection = false);
|
||||
vector<Unit *> renderUnitsFast(bool renderingShadows = false, bool colorPickingSelection = false);
|
||||
|
||||
//gl requirements
|
||||
void checkGlCaps();
|
||||
|
@ -33,7 +33,7 @@ ObjectStateInterface *Object::stateCallback=NULL;
|
||||
// class Object
|
||||
// =====================================================
|
||||
|
||||
Object::Object(ObjectType *objectType, const Vec3f &pos, const Vec2i &mapPos) {
|
||||
Object::Object(ObjectType *objectType, const Vec3f &pos, const Vec2i &mapPos) : BaseColorPickEntity() {
|
||||
RandomGen random;
|
||||
|
||||
random.init(static_cast<int>(pos.x*pos.z));
|
||||
@ -172,4 +172,13 @@ void Object::setVisible( bool visible)
|
||||
}
|
||||
}
|
||||
|
||||
string Object::getUniquePickName() const {
|
||||
string result = "";
|
||||
if(resource != NULL) {
|
||||
result += resource->getDescription() + " : ";
|
||||
}
|
||||
result += mapPos.getString();
|
||||
return result;
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
virtual void removingObjectEvent(Object *object) = 0;
|
||||
};
|
||||
|
||||
class Object {
|
||||
class Object : public BaseColorPickEntity {
|
||||
private:
|
||||
typedef vector<UnitParticleSystem*> UnitParticleSystems;
|
||||
|
||||
@ -86,6 +86,8 @@ public:
|
||||
void setLastRenderFrame(int value) { lastRenderFrame = value; }
|
||||
|
||||
const Vec2i & getMapPos() const { return mapPos; }
|
||||
|
||||
virtual string getUniquePickName() const;
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
@ -284,7 +284,8 @@ const int Unit::invalidId= -1;
|
||||
|
||||
Game *Unit::game = NULL;
|
||||
|
||||
Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing):id(id) {
|
||||
Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos,
|
||||
const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing) : BaseColorPickEntity(), id(id) {
|
||||
#ifdef LEAK_CHECK_UNITS
|
||||
Unit::mapMemoryList[this]=true;
|
||||
#endif
|
||||
@ -3245,6 +3246,12 @@ Vec2i Unit::getPosWithCellMapSet() const {
|
||||
return cellMapPos;
|
||||
}
|
||||
|
||||
string Unit::getUniquePickName() const {
|
||||
string result = intToStr(id) + " - " + type->getName() + " : ";
|
||||
result += pos.getString();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Unit::toString() const {
|
||||
std::string result = "";
|
||||
|
||||
|
@ -277,7 +277,7 @@ public:
|
||||
UnitAttackBoostEffect *currentAppliedEffect;
|
||||
};
|
||||
|
||||
class Unit : public ValueCheckerVault {
|
||||
class Unit : public BaseColorPickEntity, ValueCheckerVault {
|
||||
private:
|
||||
typedef list<Command*> Commands;
|
||||
typedef list<UnitObserver*> Observers;
|
||||
@ -625,6 +625,8 @@ public:
|
||||
void setUsePathfinderExtendedMaxNodes(bool value) { usePathfinderExtendedMaxNodes = value; }
|
||||
|
||||
void updateTimedParticles();
|
||||
|
||||
virtual string getUniquePickName() const;
|
||||
private:
|
||||
float computeHeight(const Vec2i &pos) const;
|
||||
void calculateXZRotation();
|
||||
|
@ -216,6 +216,31 @@ private:
|
||||
void buildInterpolationData() const;
|
||||
};
|
||||
|
||||
class BaseColorPickEntity {
|
||||
private:
|
||||
static const int COLOR_COMPONENTS = 3;
|
||||
unsigned char uniqueColorID[COLOR_COMPONENTS];
|
||||
|
||||
static unsigned char nextColorID[COLOR_COMPONENTS];
|
||||
static Mutex mutexNextColorID;
|
||||
|
||||
public:
|
||||
|
||||
BaseColorPickEntity();
|
||||
static void beginPicking();
|
||||
static void endPicking();
|
||||
static vector<int> getPickedList(int x,int y,int w,int h, const vector<BaseColorPickEntity *> &rendererModels);
|
||||
|
||||
void setUniquePickingColor() const;
|
||||
bool isUniquePickingColor(unsigned char *pixel) const;
|
||||
|
||||
string getColorDescription() const;
|
||||
virtual string getUniquePickName() const = 0;
|
||||
|
||||
~BaseColorPickEntity() {};
|
||||
};
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
||||
|
@ -119,9 +119,10 @@ private:
|
||||
bool lastStopped;
|
||||
|
||||
public:
|
||||
Chrono();
|
||||
Chrono(bool autoStart=false);
|
||||
void start();
|
||||
void stop();
|
||||
void reset();
|
||||
int64 getMicros();
|
||||
int64 getMillis();
|
||||
int64 getSeconds();
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "platform_common.h"
|
||||
#include "opengl.h"
|
||||
#include "platform_util.h"
|
||||
#include <memory>
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
@ -34,8 +35,6 @@ namespace Shared{ namespace Graphics{
|
||||
|
||||
using namespace Util;
|
||||
|
||||
//bool Model::masterserverMode = false;
|
||||
|
||||
// =====================================================
|
||||
// class Mesh
|
||||
// =====================================================
|
||||
@ -960,4 +959,225 @@ void Model::deletePixels() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//unsigned char BaseColorPickEntity::nextColorID[COLOR_COMPONENTS] = {1, 1, 1, 1};
|
||||
unsigned char BaseColorPickEntity::nextColorID[COLOR_COMPONENTS] = { 1, 1, 1 };
|
||||
Mutex BaseColorPickEntity::mutexNextColorID;
|
||||
|
||||
BaseColorPickEntity::BaseColorPickEntity() {
|
||||
MutexSafeWrapper safeMutex(&mutexNextColorID);
|
||||
|
||||
uniqueColorID[0] = nextColorID[0];
|
||||
uniqueColorID[1] = nextColorID[1];
|
||||
uniqueColorID[2] = nextColorID[2];
|
||||
//uniqueColorID[3] = nextColorID[3];
|
||||
|
||||
const int colorSpacing = 2;
|
||||
|
||||
if(nextColorID[0] + colorSpacing <= 255) {
|
||||
nextColorID[0] += colorSpacing;
|
||||
}
|
||||
else {
|
||||
nextColorID[0] = 1;
|
||||
if(nextColorID[1] + colorSpacing <= 255) {
|
||||
nextColorID[1] += colorSpacing;
|
||||
}
|
||||
else {
|
||||
nextColorID[1] = 1;
|
||||
if(nextColorID[2] + colorSpacing <= 255) {
|
||||
nextColorID[2] += colorSpacing;
|
||||
}
|
||||
else {
|
||||
|
||||
//printf("Color rolled over on 3rd level!\n");
|
||||
|
||||
nextColorID[0] = 1;
|
||||
nextColorID[1] = 1;
|
||||
nextColorID[2] = 1;
|
||||
|
||||
|
||||
// nextColorID[2] = 1;
|
||||
// nextColorID[3]+=colorSpacing;
|
||||
//
|
||||
// if(nextColorID[3] > 255) {
|
||||
// nextColorID[0] = 1;
|
||||
// nextColorID[1] = 1;
|
||||
// nextColorID[2] = 1;
|
||||
// nextColorID[3] = 1;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string BaseColorPickEntity::getColorDescription() const {
|
||||
string result = "";
|
||||
char szBuf[100]="";
|
||||
//sprintf(szBuf,"%d.%d.%d.%d",uniqueColorID[0],uniqueColorID[1],uniqueColorID[2],uniqueColorID[3]);
|
||||
sprintf(szBuf,"%d.%d.%d",uniqueColorID[0],uniqueColorID[1],uniqueColorID[2]);
|
||||
result = szBuf;
|
||||
return result;
|
||||
}
|
||||
|
||||
void BaseColorPickEntity::beginPicking() {
|
||||
// turn off texturing, lighting and fog
|
||||
//glClearColor (0.0,0.0,0.0,0.0);
|
||||
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_FOG);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
glDisable(GL_DITHER);
|
||||
|
||||
//glDisable(GL_LIGHT0);
|
||||
//glDisable(GL_LIGHT1);
|
||||
//glDisable(GL_LIGHT2);
|
||||
//glDisable(GL_LIGHT3);
|
||||
//glDisable(GL_LIGHT4);
|
||||
//glDisable(GL_LIGHT5);
|
||||
//glDisable(GL_LIGHT6);
|
||||
//glDisable(GL_LIGHT7);
|
||||
|
||||
//glDisable(GL_ALPHA_TEST);
|
||||
//glDisable(GL_COLOR_MATERIAL);
|
||||
|
||||
//glDisable(GL_DEPTH_TEST);
|
||||
//glDisable(GL_TEXTURE_GEN_S);
|
||||
//glDisable(GL_TEXTURE_GEN_T);
|
||||
//glDisable(GL_TEXTURE_GEN_R);
|
||||
//glDisable(GL_TEXTURE_GEN_Q);
|
||||
|
||||
}
|
||||
|
||||
void BaseColorPickEntity::endPicking() {
|
||||
// turn off texturing, lighting and fog
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_FOG);
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glEnable(GL_DITHER);
|
||||
|
||||
//glEnable(GL_TEXTURE_2D);
|
||||
//glEnable(GL_FOG);
|
||||
//glEnable(GL_LIGHTING);
|
||||
|
||||
//glEnable(GL_BLEND);
|
||||
//glEnable(GL_MULTISAMPLE);
|
||||
//glEnable(GL_DITHER);
|
||||
}
|
||||
|
||||
vector<int> BaseColorPickEntity::getPickedList(int x,int y,int w,int h, const vector<BaseColorPickEntity *> &rendererModels) {
|
||||
vector<int> pickedModels;
|
||||
|
||||
//printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
//Pixmap2D *pixmapScreenShot = new Pixmap2D(w+1, h+1, COLOR_COMPONENTS);
|
||||
static auto_ptr<unsigned char> cachedPixels;
|
||||
static int cachedPixelsW = -1;
|
||||
static int cachedPixelsH = -1;
|
||||
unsigned char *pixelBuffer = NULL;
|
||||
|
||||
//printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
static Chrono lastSnapshot(true);
|
||||
|
||||
// Only update the pixel buffer every 350 milliseconds or as required
|
||||
if(cachedPixels.get() == NULL || cachedPixelsW != w+1 || cachedPixelsH != h+1 ||
|
||||
lastSnapshot.getMillis() > 350) {
|
||||
//printf("Updating selection millis = %ld\n",lastSnapshot.getMillis());
|
||||
|
||||
lastSnapshot.reset();
|
||||
|
||||
Pixmap2D *pixmapScreenShot = new Pixmap2D(w+1, h+1, COLOR_COMPONENTS);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixmapScreenShot->getPixels());
|
||||
//glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixmapScreenShot->getPixels());
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
cachedPixels.reset(new unsigned char[pixmapScreenShot->getPixelByteCount()]);
|
||||
memcpy(cachedPixels.get(),pixmapScreenShot->getPixels(),pixmapScreenShot->getPixelByteCount());
|
||||
cachedPixelsW = w+1;
|
||||
cachedPixelsH = h+1;
|
||||
|
||||
delete pixmapScreenShot;
|
||||
}
|
||||
pixelBuffer = cachedPixels.get();
|
||||
|
||||
// Enable screenshots to debug selection scene
|
||||
//pixmapScreenShot->save("debug.png");
|
||||
|
||||
//printf("In [%s::%s] Line: %d x,y,w,h [%d,%d,%d,%d] pixels = %d\n",__FILE__,__FUNCTION__,__LINE__,x,y,w,h,pixmapScreenShot->getPixelByteCount());
|
||||
|
||||
// now our picked screen pixel color is stored in pixel[3]
|
||||
// so we search through our object list looking for the object that was selected
|
||||
|
||||
map<int,bool> modelAlreadyPickedList;
|
||||
map<unsigned char,map<unsigned char, map<unsigned char,bool> > > colorAlreadyPickedList;
|
||||
int nEnd = w * h;
|
||||
for(int x = 0; x < nEnd && pickedModels.size() < rendererModels.size(); ++x) {
|
||||
int index = x * COLOR_COMPONENTS;
|
||||
unsigned char *pixel = &pixelBuffer[index];
|
||||
|
||||
// Skip duplicate scanned colors
|
||||
map<unsigned char,map<unsigned char, map<unsigned char,bool> > >::iterator iterFind1 = colorAlreadyPickedList.find(pixel[0]);
|
||||
if(iterFind1 != colorAlreadyPickedList.end()) {
|
||||
map<unsigned char, map<unsigned char,bool> >::iterator iterFind2 = iterFind1->second.find(pixel[1]);
|
||||
if(iterFind2 != iterFind1->second.end()) {
|
||||
map<unsigned char,bool>::iterator iterFind3 = iterFind2->second.find(pixel[2]);
|
||||
if(iterFind3 != iterFind2->second.end()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < rendererModels.size(); ++i) {
|
||||
// Skip models already selected
|
||||
if(modelAlreadyPickedList.find(i) != modelAlreadyPickedList.end()) {
|
||||
continue;
|
||||
}
|
||||
const BaseColorPickEntity *model = rendererModels[i];
|
||||
|
||||
if( model != NULL && model->isUniquePickingColor(pixel) == true) {
|
||||
//printf("Found match pixel [%d.%d.%d] for model [%s] ptr [%p][%s]\n",pixel[0],pixel[1],pixel[2],model->getColorDescription().c_str(), model,model->getUniquePickName().c_str());
|
||||
|
||||
pickedModels.push_back(i);
|
||||
modelAlreadyPickedList[i]=true;
|
||||
colorAlreadyPickedList[pixel[0]][pixel[1]][pixel[2]]=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
//delete pixmapScreenShot;
|
||||
|
||||
//printf("In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
return pickedModels;
|
||||
}
|
||||
|
||||
bool BaseColorPickEntity::isUniquePickingColor(unsigned char *pixel) const {
|
||||
bool result = false;
|
||||
if( uniqueColorID[0] == pixel[0] &&
|
||||
uniqueColorID[1] == pixel[1] &&
|
||||
uniqueColorID[2] == pixel[2]) {
|
||||
//uniqueColorID[3] == pixel[3]) {
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void BaseColorPickEntity::setUniquePickingColor() const {
|
||||
glColor3f( uniqueColorID[0] / 255.0f,
|
||||
uniqueColorID[1] / 255.0f,
|
||||
uniqueColorID[2] / 255.0f);
|
||||
//uniqueColorID[3] / 255.0f);
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
@ -116,7 +116,7 @@ void PerformanceTimer::reset(){
|
||||
// Chrono
|
||||
// =====================================
|
||||
|
||||
Chrono::Chrono() {
|
||||
Chrono::Chrono(bool autoStart) {
|
||||
freq = 1000;
|
||||
stopped= true;
|
||||
accumCount= 0;
|
||||
@ -126,6 +126,10 @@ Chrono::Chrono() {
|
||||
lastResult = 0;
|
||||
lastMultiplier = 0;
|
||||
lastStopped = false;
|
||||
|
||||
if(autoStart == true) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void Chrono::start() {
|
||||
@ -140,6 +144,16 @@ void Chrono::stop() {
|
||||
stopped= true;
|
||||
}
|
||||
|
||||
void Chrono::reset() {
|
||||
accumCount = 0;
|
||||
lastStartCount = 0;
|
||||
lastTickCount = 0;
|
||||
lastResult = 0;
|
||||
lastMultiplier = 0;
|
||||
|
||||
startCount = SDL_GetTicks();
|
||||
}
|
||||
|
||||
int64 Chrono::getMicros() {
|
||||
return queryCounter(1000000);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user