static void chasePointDraw( demoChasePoint_t *point ) { int times[4]; vec4_t origins[4]; Quat_t quats[4]; float lerp; vec4_t lerpOrigin, lastOrigin; Quat_t lerpQuat; vec3_t axis[3], start, end; qboolean firstOne = qtrue; chasePointControl( point, times, origins, quats ); for (lerp = 0; lerp < 1.1f; lerp+=0.1f) { QuatTimeSpline( lerp, times, quats, lerpQuat ); VectorTimeSpline( lerp, times, (float *)origins, (float *)lerpOrigin, 4 ); QuatToAxis( lerpQuat, axis ); if (firstOne) { demoDrawCross( lerpOrigin, colorRed ); VectorCopy( lerpOrigin, start ); VectorMA( start, -lerpOrigin[3], axis[0], end ); demoDrawLine( start, end, colorBlue ); demoDrawCross( end, colorBlue ); firstOne = qfalse; } else { demoDrawLine( lerpOrigin, lastOrigin, colorRed ); } Vector4Copy( lerpOrigin, lastOrigin ); } }
int RE_LerpTagET( orientation_t *tag, const refEntity_t *refent, const char *tagNameIn, int startIndex ) { mdvTag_t *start, *end; int i; float frontLerp, backLerp; model_t *model; char tagName[ MAX_QPATH ]; //, *ch; int retval; qhandle_t handle; int startFrame, endFrame; float frac; handle = refent->hModel; startFrame = refent->oldframe; endFrame = refent->frame; frac = 1.0 - refent->backlerp; Q_strncpyz( tagName, tagNameIn, MAX_QPATH ); /* // if the tagName has a space in it, then it is passing through the starting tag number if (ch = strrchr(tagName, ' ')) { *ch = 0; ch++; startIndex = atoi(ch); } */ model = R_GetModelByHandle( handle ); /* if(!model->mdv[0]) //if(!model->model.md3[0] && !model->model.mdc[0] && !model->model.mds) { AxisClear(tag->axis); VectorClear(tag->origin); return -1; } */ frontLerp = frac; backLerp = 1.0 - frac; start = end = NULL; /* else if(model->type == MOD_MDS) { // use bone lerping retval = R_GetBoneTag(tag, model->model.mds, startIndex, refent, tagNameIn); if(retval >= 0) { return retval; } // failed return -1; } */ if ( model->type == MOD_MDM ) { // use bone lerping retval = R_MDM_GetBoneTag( tag, model->mdm, startIndex, refent, tagNameIn ); if ( retval >= 0 ) { return retval; } // failed return -1; } else if ( model->type == MOD_MD5 ) { vec3_t tmp; retval = RE_BoneIndex( handle, tagName ); if ( retval <= 0 ) { return -1; } VectorCopy( refent->skeleton.bones[ retval ].origin, tag->origin ); QuatToAxis( refent->skeleton.bones[ retval ].rotation, tag->axis ); VectorCopy( tag->axis[ 2 ], tmp ); VectorCopy( tag->axis[ 1 ], tag->axis[ 2 ] ); VectorCopy( tag->axis[ 0 ], tag->axis[ 1 ] ); VectorCopy( tmp, tag->axis[ 0 ] ); VectorNormalize( tag->axis[ 0 ] ); VectorNormalize( tag->axis[ 1 ] ); VectorNormalize( tag->axis[ 2 ] ); return retval; } /* else { // psuedo-compressed MDC tags mdcTag_t *cstart, *cend; retval = R_GetMDCTag((byte *) model->model.mdc[0], startFrame, tagName, startIndex, &cstart); retval = R_GetMDCTag((byte *) model->model.mdc[0], endFrame, tagName, startIndex, &cend); // uncompress the MDC tags into MD3 style tags if(cstart && cend) { for(i = 0; i < 3; i++) { ustart.origin[i] = (float)cstart->xyz[i] * MD3_XYZ_SCALE; uend.origin[i] = (float)cend->xyz[i] * MD3_XYZ_SCALE; sangles[i] = (float)cstart->angles[i] * MDC_TAG_ANGLE_SCALE; eangles[i] = (float)cend->angles[i] * MDC_TAG_ANGLE_SCALE; } AnglesToAxis(sangles, ustart.axis); AnglesToAxis(eangles, uend.axis); start = &ustart; end = &uend; } else { start = NULL; end = NULL; } } */ else if ( model->type == MOD_MESH ) { // old MD3 style retval = R_GetTag( model->mdv[ 0 ], startFrame, tagName, startIndex, &start ); retval = R_GetTag( model->mdv[ 0 ], endFrame, tagName, startIndex, &end ); if ( !start || !end ) { AxisClear( tag->axis ); VectorClear( tag->origin ); return -1; } for ( i = 0; i < 3; i++ ) { tag->origin[ i ] = start->origin[ i ] * backLerp + end->origin[ i ] * frontLerp; tag->axis[ 0 ][ i ] = start->axis[ 0 ][ i ] * backLerp + end->axis[ 0 ][ i ] * frontLerp; tag->axis[ 1 ][ i ] = start->axis[ 1 ][ i ] * backLerp + end->axis[ 1 ][ i ] * frontLerp; tag->axis[ 2 ][ i ] = start->axis[ 2 ][ i ] * backLerp + end->axis[ 2 ][ i ] * frontLerp; } VectorNormalize( tag->axis[ 0 ] ); VectorNormalize( tag->axis[ 1 ] ); VectorNormalize( tag->axis[ 2 ] ); return retval; } return -1; }
void writeSKL(tModel_t *m, tAnim_t *a, const char *outFName) { FILE *out; int i, j, k, v, t, addVerts; out = F_Open(outFName,"wb"); fprintf(out,"//////////////////////////////////////////////////////////////////////////\n"); fprintf(out,"//\n"); fprintf(out,"// Exported by md5_2_skX\n"); fprintf(out,"//\n"); fprintf(out,"//////////////////////////////////////////////////////////////////////////\n"); fprintf(out,"\n"); fprintf(out,"SKELETON\n"); fprintf(out,"VERSION 1\n"); fprintf(out,"\n"); fprintf(out,"NUMMATERIALS %i\n",m->numSurfaces); for(i = 0; i < m->numSurfaces; i++) { fprintf(out,"MATERIAL %i %s\n",i,m->surfs[i].name); } fprintf(out,"\n"); fprintf(out,"NUMBONES %i\n",m->numBones); for(i = 0; i < m->numBones; i++) { fprintf(out,"BONE %i %i %s\n",i,m->bones[i].parent,m->bones[i].name); } fprintf(out,"NUMVERTS %i\n",getTotalVertCount(m)); v = 0; for(i = 0; i < m->numSurfaces; i++) { tVert_t *vt; tSurf_t *sf; sf = m->surfs + i; vt = sf->verts; for(j = 0; j < sf->numVerts; j++,v++,vt++) { fprintf(out,"VERT %i\n",v); fprintf(out,"NORMAL %f %f %f\n",vt->normal[0],vt->normal[1],vt->normal[2]); //fprintf(out,"NORMAL 1 0 0\n"); fprintf(out,"BONES %i\n",vt->numWeights); for(k = 0; k < vt->numWeights; k++) { fprintf(out,"BONE %i %f %f %f %f\n",vt->weights[k].boneNum,vt->weights[k].boneWeight, vt->weights[k].offset[0],vt->weights[k].offset[1],vt->weights[k].offset[2]); } fprintf(out,"\n"); } } fprintf(out,"\n"); fprintf(out,"NUMFACES %i\n",getTotalTriCount(m)); t = 0; addVerts = 0; for(i = 0; i < m->numSurfaces; i++) { tTri_t *tt; tSurf_t *sf; sf = m->surfs + i; tt = sf->tris; for(j = 0; j < sf->numTris; j++,t++,tt++) { int v0, v1, v2; tVert_t *vp0, *vp1, *vp2; v0 = tt->indexes[0] + addVerts; v1 = tt->indexes[1] + addVerts; v2 = tt->indexes[2] + addVerts; vp0 = sf->verts + tt->indexes[0]; vp1 = sf->verts + tt->indexes[1]; vp2 = sf->verts + tt->indexes[2]; // TRI <surface/material index> fprintf(out,"TRI %i",i); fprintf(out," %i %f %f", v0, vp0->texCoords[0], vp0->texCoords[1]); fprintf(out," %i %f %f", v1, vp1->texCoords[0], vp1->texCoords[1]); fprintf(out," %i %f %f", v2, vp2->texCoords[0], vp2->texCoords[1]); fprintf(out,"\n"); } addVerts += sf->numVerts; } fprintf(out,"\n"); fprintf(out,"FRAMERATE %f\n",a->frameRate); fprintf(out,"NUMFRAMES %i\n",a->numFrames); fprintf(out,"\n"); for(i = 0; i < a->numFrames; i++) { tFrame_t *f; bone_t *bones, *b; bones = b = setupMD5AnimBones(a,i); md5AnimateBones(m,bones); f = a->frames + i; fprintf(out,"\nFRAME %i\n",i); for(j = 0; j < a->numBones; j++,b++) { vec3_t axis[3]; fprintf(out,"BONE %i\n",j); fprintf(out,"OFFSET %f %f %f\n", b->p[0],b->p[1],b->p[2]); QuatToAxis(b->q,axis); fprintf(out,"X %f %f %f\n",axis[0][0],axis[0][1],axis[0][2]); fprintf(out,"Y %f %f %f\n",axis[1][0],axis[1][1],axis[1][2]); fprintf(out,"Z %f %f %f\n",axis[2][0],axis[2][1],axis[2][2]); fprintf(out,"\n"); } } fprintf(out,"\nNUMBOXES 0\n"); fprintf(out,"\n"); fprintf(out,"END\n"); fclose(out); T_Printf("Wrote %s\n",outFName); }
/* ================ CG_AddFragment ================ */ void CG_AddFragment(localEntity_t * le) { vec3_t newOrigin; trace_t trace; if(le->pos.trType == TR_STATIONARY) { // sink into the ground if near the removal time int t; float oldZ; t = le->endTime - cg.time; if(t < SINK_TIME) { // we must use an explicit lighting origin, otherwise the // lighting would be lost as soon as the origin went // into the ground VectorCopy(le->refEntity.origin, le->refEntity.lightingOrigin); le->refEntity.renderfx |= RF_LIGHTING_ORIGIN; oldZ = le->refEntity.origin[2]; le->refEntity.origin[2] -= 16 * (1.0 - (float)t / SINK_TIME); trap_R_AddRefEntityToScene(&le->refEntity); le->refEntity.origin[2] = oldZ; } else { trap_R_AddRefEntityToScene(&le->refEntity); } return; } // calculate new position BG_EvaluateTrajectory(&le->pos, cg.time, newOrigin); // trace a line from previous position to new position CG_Trace(&trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID); if(trace.fraction == 1.0) { // still in free fall VectorCopy(newOrigin, le->refEntity.origin); if(le->leFlags & LEF_TUMBLE) { #if 0 vec3_t angles; BG_EvaluateTrajectory(&le->angles, cg.time, angles); AnglesToAxis(angles, le->refEntity.axis); #else // Tr3B - new quaternion code quat_t qrot; // angular rotation for this frame float angle = le->angVel * (cg.time - le->angles.trTime) * 0.001 / 2; // create the rotation quaternion qrot[3] = cos(angle); // real part VectorScale(le->rotAxis, sin(angle), qrot); // imaginary part QuatNormalize(qrot); // create the new orientation QuatMultiply0(le->quatOrient, qrot); // apply the combined previous rotations around other axes QuatMultiply1(le->quatOrient, le->quatRot, qrot); // convert the orientation into the form the renderer wants QuatToAxis(qrot, le->refEntity.axis); le->angles.trTime = cg.time; #endif } trap_R_AddRefEntityToScene(&le->refEntity); // add a blood trail if(le->leBounceSoundType == LEBS_BLOOD) { CG_BloodTrail(le); } return; } // if it is in a nodrop zone, remove it // this keeps gibs from waiting at the bottom of pits of death // and floating levels if(trap_CM_PointContents(trace.endpos, 0) & CONTENTS_NODROP) { CG_FreeLocalEntity(le); return; } // leave a mark CG_FragmentBounceMark(le, &trace); // do a bouncy sound CG_FragmentBounceSound(le, &trace); // reflect the velocity on the trace plane CG_ReflectVelocity(le, &trace); trap_R_AddRefEntityToScene(&le->refEntity); }