vec3_t *G2Exporter_Surface_GetVertNormal(int iSurfaceIndex, int iVertIndex, int iLODIndex) { static vec3_t v3={0}; memset(v3,0,sizeof(v3)); if (iLODIndex == giNumLODs-1) { // q3data surface... // if (iSurfaceIndex < giNumSurfaces) { // standard surface... // md3SurfaceData_t *pSurfaceData = GetMD3SurfaceData(iSurfaceIndex); if (pSurfaceData) { // this logic is kinda gay, not sure why the *6 etc, but that's how other q3data code works, so... // float **ppVerts = pSurfaceData->verts; memcpy(v3,(vec3_t*) &ppVerts[0][iVertIndex*6+3], sizeof(v3)); { Matrix4 Swap; Swap.Identity(); if (1) { Swap.SetRow(0,Vect3(0.0f,-1.0f,0.0f)); Swap.SetRow(1,Vect3(1.0f,0.0f,0.0f)); } Swap.CalcFlags(); Vect3 v3In((const float *)v3); static Vect3 v3Out; Swap.XFormVect(v3Out,v3In); return (vec3_t*) &v3Out; } } } else { // tag surface... // // I don't think tag-surfaces normals have any meaning for ghoul2, so... // return &v3; } } else { // imported surface... // vec3_t &v3Src = ImportedModel.ImportedLODs[iLODIndex].ImportedSurfaces[ImportedModel.SurfaceIndexRemaps[iSurfaceIndex]].ImportedVerts[iVertIndex].normal; memcpy(v3,v3Src,sizeof(v3)); return &v3; } assert(0); return &v3; }
int FindPKeys(TxtNode *t) { if (t->child) { TxtNode *sib=t->child; if (!sib) return 200; char framename[100]; { if (!sib->child) return 201; if (!sib->child->text) return 202; if (!strncmp("frm-",sib->child->text,4)) mystrncpy(framename,sib->child->text+4,sib->child->length-4); else { if (!strncmp("SCENE",sib->child->text,4)) return 0; mystrncpy(framename,sib->child->text,sib->child->length); } sib=sib->sibling; } int foundkeys=0; maxmatframe=0; while (sib) { if (sib->text&&!mystrncmp("SI_AnimationKey",sib->text,sib->length)) { if (!sib->sibling) return 103; sib=sib->sibling; int err=ProcNKeys(sib,foundkeys); if (err) return err; } sib=sib->sibling; } { if (maxmatframe>maxframe) maxframe=maxmatframe; int i; for (i=0;i<nsNodes;i++) { if (!strcmp(sNodes[i].name,framename)) { int j; if (sNodes[i].nanimat<maxmatframe+1) { delete[] sNodes[i].animat; sNodes[i].nanimat=maxmatframe+1; sNodes[i].animat=new Matrix4[maxmatframe+1]; for (j=0;j<=maxmatframe;j++) sNodes[i].animat[j].Identity(); } for (j=0;j<=maxmatframe;j++) { Matrix4 xf; xf=sNodes[i].mat; Vect3 tt,t2; if (foundkeys&1) { mats[j].GetRow(3,tt); xf.SetRow(3,tt); } if (foundkeys&2) { float l; xf.GetRow(0,t2); l=t2.Len(); mats[j].GetRow(0,tt); tt*=l; xf.SetRow(0,tt); xf.GetRow(1,t2); l=t2.Len(); mats[j].GetRow(1,tt); tt*=l; xf.SetRow(1,tt); xf.GetRow(2,t2); l=t2.Len(); mats[j].GetRow(2,tt); tt*=l; xf.SetRow(2,tt); } if (foundkeys&4) { xf.GetRow(0,tt); tt.Norm(); tt*=scales[j].x(); xf.SetRow(0,tt); xf.GetRow(1,tt); tt.Norm(); tt*=scales[j].x(); xf.SetRow(1,tt); xf.GetRow(2,tt); tt.Norm(); tt*=scales[j].x(); xf.SetRow(2,tt); } xf.CalcFlags(); Matrix4 par,tmat; if (sNodes[i].parent) { if (j<sNodes[i].parent->nanimat) par=sNodes[i].parent->animat[j]; else par=sNodes[i].parent->BaseMat; tmat.Concat(xf,par); } else tmat=xf; sNodes[i].animat[j]=tmat; #if 0 par.Inverse(sNodes[i].BaseMat); tmat.Concat(par,sNodes[i].animat[j]); char tmp[1000]; int r; sprintf(tmp,"final frame %d %s\n",j,sNodes[i].name); OutputDebugString(tmp); for (r=0;r<4;r++) { sprintf(tmp,"%6f %6f %6f\n",tmat[r][0],tmat[r][1],tmat[r][2]); OutputDebugString(tmp); } sprintf(tmp,"baseinv frame %d %s\n",j,sNodes[i].name); OutputDebugString(tmp); for (r=0;r<4;r++) { sprintf(tmp,"%6f %6f %6f\n",par[r][0],par[r][1],par[r][2]); OutputDebugString(tmp); } sprintf(tmp,"bone frame %d %s\n",j,sNodes[i].name); OutputDebugString(tmp); for (r=0;r<4;r++) { sprintf(tmp,"%6f %6f %6f\n",sNodes[i].animat[j][r][0],sNodes[i].animat[j][r][1],sNodes[i].animat[j][r][2]); OutputDebugString(tmp); } #endif } } } } } return 0; }
int ProcNKeys(TxtNode *t,int& foundkeys) { if (t->child) { TxtNode *sib=t->child; if (!sib->text) return 207; int tp=myatoi(sib->text,sib->length); sib=sib->sibling; if (!sib||!sib->text) return 208; int num=myatoi(sib->text,sib->length); sib=sib->sibling; int i; int lastframe=startframe-1; TxtNode *s=sib; for (i=0;i<num;i++) { if (!s||!s->text) return 110; int frame=myatoi(s->text,s->length); if (frame>33000) frame=frame-65536; if (frame<startframe) { assert(!i); lastframe=frame-1; startframe=frame; } if (frame>endframe) endframe=frame; if (frame-startframe>maxmatframe) maxmatframe=frame-startframe; s=s->sibling; if (!s||!s->text) return 212; int junk=myatoi(s->text,s->length); if (junk!=3) return 213; s=s->sibling; if (!s||!s->text) return 216; float x=(float)myatof(s->text,s->length); s=s->sibling; if (!s||!s->text) return 216; float y=(float)myatof(s->text,s->length); s=s->sibling; if (!s||!s->text) return 216; float z=(float)myatof(s->text,s->length); s=s->sibling; int k; if (tp==1) //scale { Vect3 v=Vect3(x,z,y); for (k=lastframe+1;k<=frame;k++) scales[k-startframe]=v; foundkeys|=4; } else if (tp==2) //translation { Vect3 v(x,-z,y); for (k=lastframe+1;k<=frame;k++) { mats[k-startframe].SetRow(3,v); mats[k-startframe].CalcFlags(); } foundkeys|=1; } else if (tp==3) //rotation { Matrix4 tmp; tmp.Rotate(-x*M_PI/180.0f,-y*M_PI/180.0f,-z*M_PI/180.0f); Vect3 t,tt; tmp.GetRow(2,t); t*=-1.0f; tmp.GetRow(1,tt); tmp.SetRow(2,tt); tmp.SetRow(1,t); for (k=0;k<3;k++) { float tt=-tmp[k][2]; tmp[k][2]=tmp[k][1]; tmp[k][1]=tt; } for (k=lastframe+1;k<=frame;k++) { int l; for (l=0;l<3;l++) { tmp.GetRow(l,t); mats[k-startframe].SetRow(l,t); mats[k-startframe].CalcFlags(); } } foundkeys|=2; } lastframe=frame; } } return 0; }
vec3_t *G2Exporter_Surface_GetVertCoords(int iSurfaceIndex, int iVertIndex, int iLODIndex) { static vec3_t v3={0}; memset(&v3,0,sizeof(v3)); if (iLODIndex == giNumLODs-1) { // q3data surface... // if (iSurfaceIndex < giNumSurfaces) { // standard surface... // md3SurfaceData_t *pSurfaceData = GetMD3SurfaceData(iSurfaceIndex); if (pSurfaceData) { // this logic is kinda gay, not sure why the *6 etc, but that's how other q3data code works, so... // float **ppVerts = pSurfaceData->verts; static vec3_t v3; for (int i=0; i<3; i++) { v3[i] = ppVerts[0][iVertIndex*6+i];// /MD3_XYZ_SCALE; } // return &v3; Matrix4 Swap; Swap.Identity(); if (1) { Swap.SetRow(0,Vect3(0.0f,-1.0f,0.0f)); Swap.SetRow(1,Vect3(1.0f,0.0f,0.0f)); } Swap.CalcFlags(); Vect3 v3In((const float *)v3); static Vect3 v3Out; Swap.XFormVect(v3Out,v3In); return (vec3_t*) &v3Out; } } else { // tag surface... // assert(iVertIndex<3); md3Tag_t *pTag = &g_data.tags[0][iSurfaceIndex - giNumSurfaces]; vec3_t v3New; //#ifdef PERFECT_CONVERSION v3New[0] = pTag->axis[0][iVertIndex] ; v3New[1] = pTag->axis[1][iVertIndex] ; v3New[2] = pTag->axis[2][iVertIndex] ; // don't worry about how this crap works, it just does (arrived at by empirical methods... :-) // // (mega-thanks to Gil as usual) // if (iVertIndex==2) { VectorCopy(pTag->origin,v3); } else if (iVertIndex==1) { v3New[0] = 2.0f * pTag->axis[1][iG2_TRISIDE_MIDDLE]; v3New[1] = -(2.0f * pTag->axis[0][iG2_TRISIDE_MIDDLE]); v3New[2] = 2.0f * pTag->axis[2][iG2_TRISIDE_MIDDLE]; VectorSubtract(pTag->origin,v3New,v3); } else { v3New[0] = pTag->axis[1][iG2_TRISIDE_LONGEST]; v3New[1] = -pTag->axis[0][iG2_TRISIDE_LONGEST]; v3New[2] = pTag->axis[2][iG2_TRISIDE_LONGEST]; VectorSubtract(pTag->origin,v3New,v3); } // return (vec3_t*) &v3; Matrix4 Swap; Swap.Identity(); if (1) { Swap.SetRow(0,Vect3(0.0f,-1.0f,0.0f)); Swap.SetRow(1,Vect3(1.0f,0.0f,0.0f)); } Swap.CalcFlags(); Vect3 v3In((const float *)v3); static Vect3 v3Out; Swap.XFormVect(v3Out,v3In); return (vec3_t*) &v3Out; } } else { // imported surface... // vec3_t &v3Src = ImportedModel.ImportedLODs[iLODIndex].ImportedSurfaces[ImportedModel.SurfaceIndexRemaps[iSurfaceIndex]].ImportedVerts[iVertIndex].vertCoords; memcpy(v3,v3Src,sizeof(v3)); return &v3; } assert(0); return &v3; }