void stat_gl_model( gl_model *__model, char *psAttachedVia ) { #define ARB_NAME_PADDING 26 #define ARB_LOD_PADDING 9 #define ARB_ATTACHNAME_PADDING 24 #define ARB_VERTINFO_PADDING 15 gl_model* model = __model; if (model) { giModelsStatted++; if (model->modelType == MODTYPE_MD3) { switch (mdview.iLODLevel) { case 0: break; case 1: model = model->pModel_LOD1; break; case 2: model = model->pModel_LOD2; break; } if (!model) { Text_DisplayFlat( va("%s", String_EnsureMinLength("( LOD model missing )",ARB_NAME_PADDING)), iTextX, iTextY, 0, 255,0, // RGB false ); iTextY += TEXT_DEPTH; return; } } } int iNextX = 0; if (model) { iNextX = Text_DisplayFlat( va("%s Frame %4d/%4d", String_EnsureMinLength(va("\"%s\"",model->sMD3BaseName),ARB_NAME_PADDING), model->currentFrame, model->iNumFrames), iTextX, iTextY, 0, 255,0, // RGB false ); } else { iTextY += TEXT_DEPTH; // seperate totals a bit iNextX = // va("%s Frame 1234/1234" Text_DisplayFlat( va("%s ", String_EnsureMinLength("( totals )",ARB_NAME_PADDING)), iTextX, iTextY, 0, 255,0, // RGB false ); } if (model) { // LODs info... // if (model->modelType == MODTYPE_MDR) { md4LOD_t *pLOD = (md4LOD_t *) ((byte *)model->Q3ModelStuff.md4 + model->Q3ModelStuff.md4->ofsLODs); int iWhichLod = mdview.iLODLevel; if (iWhichLod >= model->Q3ModelStuff.md4->numLODs) iWhichLod = model->Q3ModelStuff.md4->numLODs-1; iNextX = Text_DisplayFlat( String_EnsureMinLength(va("(LOD %1d/%1d)",iWhichLod+1,model->Q3ModelStuff.md4->numLODs),ARB_LOD_PADDING), iNextX+(2*TEXT_WIDTH), iTextY, 255/2,255,255/2, // RGB false ); } else { iNextX = Text_DisplayFlat( String_EnsureMinLength(va("(LOD %1d)",mdview.iLODLevel+1),ARB_LOD_PADDING), iNextX+(2*TEXT_WIDTH), iTextY, 255/2,255,255/2, // RGB false ); } } else { iNextX = Text_DisplayFlat( String_EnsureMinLength("",ARB_LOD_PADDING), iNextX+(2*TEXT_WIDTH), iTextY, 255/2,255,255/2, // RGB false ); } if (model) { // Verts/tris info... // iNextX = Text_DisplayFlat( String_EnsureMinLength( va("(V:%4d T:%4d)",model->iRenderedVerts,model->iRenderedTris), ARB_VERTINFO_PADDING ), iNextX+(2*TEXT_WIDTH), iTextY, 255, 255/2, 255/2, // RGB (pink) false ); giTotVerts+= model->iRenderedVerts; giTotTris += model->iRenderedTris; } else { // Verts/tris info... // iNextX = Text_DisplayFlat( String_EnsureMinLength( va("(V:%4d T:%4d)",giTotVerts,giTotTris), ARB_VERTINFO_PADDING ), iNextX+(2*TEXT_WIDTH), iTextY, 255, 255/2, 255/2, // RGB (pink) false ); } if (model) { // attached-via info... // iNextX = Text_DisplayFlat( String_EnsureMinLength( va("%s", psAttachedVia?va("(attached: \"%s\")",psAttachedVia):""), ARB_ATTACHNAME_PADDING ), iNextX+(2*TEXT_WIDTH), iTextY, 0, 255/2,0, // RGB false ); // print either the locked local frame number in red (if anim locking is on), or just the anim sequence name // if there's one corresponding to this... // Sequence_t* pSeq = NULL; bool bIsUpper = false; if ((model == pModel_Upper || model->pModel_LOD0 == pModel_Upper ) && iAnimLockNumber_Upper) { pSeq = Animation_GetUpperSequence( iAnimLockNumber_Upper-1 ); bIsUpper = true; } if ((model == pModel_Lower || model->pModel_LOD0 == pModel_Lower ) && iAnimLockNumber_Lower) { pSeq = Animation_GetLowerSequence( iAnimLockNumber_Lower-1 ); bIsUpper = false; } if (pSeq) { bool bWasMulti = false; if (pSeq->bMultiSeq) { pSeq = GetMultiLockedSequenceFromFrame(model->currentFrame, bIsUpper ); bWasMulti = true; } if (pSeq) { iNextX = Text_DisplayFlat( va("%d/%d",model->currentFrame-pSeq->iTargetFrame,pSeq->iFrameCount), iNextX+(2*TEXT_WIDTH), iTextY, 255, // R 0, // G bWasMulti?255:0, // B // multi displays as purple false ); } } //else if (!pSeq) { if ((model == pModel_Upper || model->pModel_LOD0 == pModel_Upper ) && !iAnimLockNumber_Upper) { pSeq = Animation_FromUpperFrame( model->currentFrame ); } if ((model == pModel_Lower || model->pModel_LOD0 == pModel_Lower ) && !iAnimLockNumber_Lower) { pSeq = Animation_FromLowerFrame( model->currentFrame ); } if (pSeq) { iNextX = Text_DisplayFlat( va("%s",pSeq->sName.c_str()), iNextX + (2*TEXT_WIDTH), iTextY, 0,200,200, true); // dim cyan } } } iTextY += TEXT_DEPTH; }
void draw_stats() { if (mdview.baseModel) { iTextX = 2*TEXT_WIDTH; // arb start pos 2 in from both edges iTextY = 4*TEXT_DEPTH; // ... or 4... :-) // // Displays text at a 2d screen coord. 0,0 is top left corner, add TEXT_DEPTH per Y to go down a line // // Text_DisplayFlat("testing testing HELLO!!", 100,100, 0, 255,0, true); // // Vec3 v={0,0,0}; // Text_Display("testing testing HELLO!!", v, 255,0,0); // // gl_model *model = mdview.baseModel; stat_skeleton( model, NULL ); // anim locks on the whole model?, if so display 'em... // char sString[1024]; for (int i=0; i<2; i++) { // display anim locks at bottom of screen... // Sequence_t* pSeq=NULL; bool bIsUpper = false; if (i==0 && iAnimLockNumber_Upper ) { pSeq = Animation_GetUpperSequence( iAnimLockNumber_Upper-1 ); bIsUpper = true; } if (i==1 && iAnimLockNumber_Lower ) { pSeq = Animation_GetLowerSequence( iAnimLockNumber_Lower-1 ); bIsUpper = false; } if (pSeq) { int iYpos = g_iScreenHeight-((!i?4:3)*TEXT_DEPTH); // cheat, do this next bit here just to get the X coord, then overwrite later sprintf(sString,"%s anim lock: %s Frames: %4d...%4d%s",!i?"Upper":"Lower",String_EnsureMinLength(pSeq->sName.c_str(),iAnimLockLongestString),pSeq->iTargetFrame,(pSeq->iTargetFrame+pSeq->iFrameCount)-1,String_EnsureMinLength((pSeq->iLoopFrame==-1)?"":va(" loop: %3d(%3d)",pSeq->iLoopFrame,pSeq->iTargetFrame+pSeq->iLoopFrame),25)); int iXpos = (g_iScreenWidth/2)-( (strlen(sString)/2)*TEXT_WIDTH); if (pSeq->bMultiSeq) { Sequence_t *pCurrentMultiSeq = GetMultiLockedSequenceFromFrame(bIsUpper?pModel_Upper->currentFrame:pModel_Lower->currentFrame, bIsUpper ); int iStrlenAtCurrentSeqPoint = 0; sprintf(sString,"%s anim lock: ",bIsUpper?"Upper":"Lower"); MultiSequenceLock_t* pMultiLock = (bIsUpper)?&MultiSequenceLock_Upper:&MultiSequenceLock_Lower; MultiSequenceLock_t::iterator it; for (it = pMultiLock->begin(); it != pMultiLock->end(); ++it) { int iSeqIndex = *it; pSeq = (bIsUpper)?Animation_GetUpperSequence(iSeqIndex):Animation_GetLowerSequence(iSeqIndex); assert(pSeq); if (pSeq) { if (pSeq == pCurrentMultiSeq) iStrlenAtCurrentSeqPoint = strlen(sString); strcat(sString,va("%s ",pSeq->sName.c_str())); } } // int iXpos = (g_iScreenWidth/2)-( (strlen(sString)/2)*TEXT_WIDTH); Text_DisplayFlat(sString, iXpos, iYpos, 255,0,0, true); // now overlay the highlighted one for current... // if (pCurrentMultiSeq) { iXpos += iStrlenAtCurrentSeqPoint*TEXT_WIDTH; Text_DisplayFlat(pCurrentMultiSeq->sName.c_str(), iXpos, iYpos, 255,0,255, true); } } else { sprintf(sString,"%s anim lock: %s Frames: %4d...%4d%s",!i?"Upper":"Lower",String_EnsureMinLength(pSeq->sName.c_str(),iAnimLockLongestString),pSeq->iTargetFrame,(pSeq->iTargetFrame+pSeq->iFrameCount)-1,String_EnsureMinLength((pSeq->iLoopFrame==-1)?"":va(" loop: %3d(%3d)",pSeq->iLoopFrame,pSeq->iTargetFrame+pSeq->iLoopFrame),25)); // int iXpos = (g_iScreenWidth/2)-( (strlen(sString)/2)*TEXT_WIDTH); Text_DisplayFlat(sString, iXpos, iYpos, 255,0,0, true); } } if (RunningNT() == 4) // only needed on NT4, NT 2000 and W95/98 are ok { pSeq = NULL; if (i==0 && iAnimDisplayNumber_Upper) pSeq = Animation_GetUpperSequence( iAnimDisplayNumber_Upper-1); if (i==1 && iAnimDisplayNumber_Lower) pSeq = Animation_GetLowerSequence( iAnimDisplayNumber_Lower-1); if (pSeq) { if (pSeq->bMultiSeq) { assert(0); // should never be able to get here in the animlock display-cycler } else { sprintf(sString,"( %s anim : %s Frames: %4d...%4d%s )",!i?"Upper":"Lower",String_EnsureMinLength(pSeq->sName.c_str(),iAnimLockLongestString),pSeq->iTargetFrame,(pSeq->iTargetFrame+pSeq->iFrameCount)-1,String_EnsureMinLength((pSeq->iLoopFrame==-1)?"":va(" loop: %3d(%3d)",pSeq->iLoopFrame,pSeq->iTargetFrame+pSeq->iLoopFrame),25)); int iXpos = (g_iScreenWidth/2)-( ((strlen(sString)/2)/*+2*/)*TEXT_WIDTH); // 2 chars back from LOCk string, because of bracket+space at start int iYpos = g_iScreenHeight-((!i?7:6)*TEXT_DEPTH); Text_DisplayFlat(sString, iXpos, iYpos, 0,200,200, true); // dim yellow } } } } // display current FPS and interp state... // sprintf(sString,"FPS: %2.2f %s",1/(mdview.animSpeed),mdview.animate?"(Playing)":"(Stopped)"); iTextX = Text_DisplayFlat(sString, (g_iScreenWidth/2)-( (strlen(sString)/2)*TEXT_WIDTH), 1*TEXT_DEPTH, 255,255,255, false ); if (mdview.interpolate) { iTextX = Text_DisplayFlat("(Interpolated)", iTextX+(2*TEXT_WIDTH),1*TEXT_DEPTH, 255/2,255/2,255/2,false); } iTextX = Text_DisplayFlat(va("(LOD: %d)",mdview.iLODLevel+1), iTextX+(2*TEXT_WIDTH), 1*TEXT_DEPTH, 255/2,255,255/2,false); /* Text_DisplayFlat(sString, g_iScreenWidth-((strlen(sString)+2)*TEXT_WIDTH), 2 *TEXT_DEPTH, 255,255,255, false );*/ iTextX = Text_DisplayFlat(va("( FOV: %g )",mdview.dFOV), iTextX+(2*TEXT_WIDTH),1*TEXT_DEPTH, 255, 255, 255, false); if (mdview.bUseAlpha) { Text_DisplayFlat("( Alpha )", iTextX+(2*TEXT_WIDTH),1*TEXT_DEPTH, 128, 128, 128, false); } // display head skin numbers in top left... // gl_model* pModel = R_FindModel( mdview.baseModel, "head"); if (pModel) { sprintf(sString,"Head skin: %s", va("\"%s%s\"",model->sHeadSkinName,!mdview.iSkinNumber?"":va("-%1d",mdview.iSkinNumber))); Text_DisplayFlat(sString, 2*TEXT_WIDTH,//(g_iScreenWidth/2)-( (strlen(sString)/2)*TEXT_WIDTH), 1*TEXT_DEPTH, 200,200,200, false ); } // display which format anim table this is using (if any)... // if (mdview.bAnimCFGLoaded) { if (mdview.bAnimIsMultiPlayerFormat) sprintf(sString,"( MultiPlayer ) "); else sprintf(sString,"( SinglePlayer ) "); int iYpos = g_iScreenHeight-(2*TEXT_DEPTH); int iXpos = g_iScreenWidth -(strlen(sString)*TEXT_WIDTH); Text_DisplayFlat(sString, iXpos, iYpos, 128,128,128, true); // grey } // display current picmip state... // { extern int TextureList_GetMip(void); int iYpos = g_iScreenHeight-(2*TEXT_DEPTH); int iXpos = 1*TEXT_WIDTH; sprintf(sString,"( PICMIP: %d )",TextureList_GetMip()); Text_DisplayFlat(sString, iXpos, iYpos, 100,100,100, false ); } } }
// if psFilename == NULL, takes a memory screenshot in DIB format (for copying to clipboard) // bool ScreenShot(LPCSTR psFilename, // else NULL = take memory snapshot (for clipboard) LPCSTR psCopyrightMessage, // /* = NULL */ int iWidth, // /* = <screenwidth> */ int iHeight // /* = <screenheight> */ ) { bool bReturn = false; int iOldPack; glGetIntegerv(GL_PACK_ALIGNMENT,&iOldPack); glPixelStorei(GL_PACK_ALIGNMENT,1); void *pvGLPixels = malloc (iWidth * iHeight * 3); // 3 = R,G,B if (pvGLPixels) { if (psCopyrightMessage) { bool bOldInhibit = gbTextInhibit; gbTextInhibit = false; Text_DisplayFlat(psCopyrightMessage, 0, (iHeight-TEXT_DEPTH)-1,255,255,255); // y-1 = aesthetic only gbTextInhibit = bOldInhibit; } glReadPixels( 0, // x 0, // y (from bottom left) iWidth, // width iHeight, // height GL_RGB, // format GL_UNSIGNED_BYTE, // type pvGLPixels // buffer ptr ); // save area is valid size... // if (BMP_Open(psFilename, iWidth, iHeight)) { for (int y=0; y<iHeight; y++) { LPGLRGBBYTES lpGLRGBBytes = (LPGLRGBBYTES) pvGLPixels; lpGLRGBBytes+= y * iWidth; for (int x=0; x<iWidth; x++, lpGLRGBBytes++) { BMP_WritePixel(lpGLRGBBytes->r,lpGLRGBBytes->g,lpGLRGBBytes->b); } BMP_WriteLinePadding(iWidth); // arg is # pixels per row } BMP_Close(psFilename,false); // false = bFlipFinal bReturn = true; } free(pvGLPixels); pvGLPixels = NULL; // yeah...yeah } glPixelStorei(GL_PACK_ALIGNMENT,iOldPack); return bReturn; }