// // 设置本地朝向 // VOID CSceneNode::SetLocalOrientation(FLOAT x, FLOAT y, FLOAT z, FLOAT w) { m_bNeedUpdateAABB = TRUE; m_bNeedUpdateTransform = TRUE; QuatSet(&m_localOrientation, x, y, z, w); }
void CL_Init_Entity (entity_t *ent) { memset (ent, 0, sizeof (*ent)); ent->skin = 0; QuatSet (1.0, 1.0, 1.0, 1.0, ent->colormod); ent->scale = 1.0; ent->pose1 = ent->pose2 = -1; }
// // 初始化 // VOID CSceneNode::Identity(VOID) { m_bNeedUpdateAABB = TRUE; m_bNeedUpdateTransform = TRUE; Vec3Set(&m_localScale, 1.0f, 1.0f, 1.0f); Vec3Set(&m_localPosition, 0.0f, 0.0f, 0.0f); QuatSet(&m_localOrientation, 0.0f, 0.0f, 0.0f, 1.0f); MtxIdentity(&m_mtxLocal); }
float *findRotChannel(skcHeader_t *h, const char *name, int frameNum, int parentIndex) { #if 0 char channelName[32]; strcpy(channelName,name); strcat(channelName," rot"); return getChannelValue(h,channelName,frameNum); #else static int i = 0; static quat_t qs[1024]; float *q; char channelName[32]; float *f; float len; i++; i %= 1024; q = qs[i]; strcpy(channelName,name); strcat(channelName," rot"); f = getChannelValue(h,channelName,frameNum); if(f == 0) { //return quat_identity; QuatSet(q,0,0,0,-1); } else { QuatCopy(f,q); } //QuatInverse(q); ////if(parentIndex == -1) // QuatInverse(q); len = QuatNormalize(q); if(abs(len-1.f) > 0.1) { T_Error("Non-normalized quat in skc file (%f)\n",len); } #if 1 FixQuatForMD5_P(q); #endif return q; #endif }
// // 设置世界朝向 // VOID CSceneNode::SetWorldOrientation(FLOAT x, FLOAT y, FLOAT z, FLOAT w) { if (m_pParentNode) { // 算法: // worldOrientation = localOrientation * parentOrientation // localOrientation = worldOrientation * parentOrientationInv QUAT parentOrientationInv; QuatInverse(&parentOrientationInv, m_pParentNode->GetWorldOrientation()); QUAT localOrientation; QUAT worldOrientation; QuatSet(&worldOrientation, x, y, z, w); QuatMul(&localOrientation, &worldOrientation, &parentOrientationInv); x = localOrientation[0]; y = localOrientation[1]; z = localOrientation[2]; w = localOrientation[3]; } SetLocalOrientation(x, y, z, w); }
tAnim_t *appendSKC(tModel_t *m, const char *fname, float scale) { int len; skcHeader_t *h; skcFrame_t *f; //, *firstFrame; tAnim_t *out; tFrame_t *of; // const char *c; int i, j; int cFlags[512]; bone_t baseFrame[512]; int numAnimatedComponents; T_Printf("Loading MoHAA skc animation file %s...\n",fname); len = F_LoadBuf(fname,(byte**)&h); if(len == -1) { T_Printf("Cannot open %s\n",fname); return 0; } memset(cFlags,0,sizeof(cFlags)); out = T_Malloc(sizeof(tAnim_t)); out->frameRate = 1.f / h->frameTime; out->numBones = m->numBones; out->numFrames = h->numFrames; out->frames = T_Malloc(sizeof(tFrame_t)*h->numFrames); out->boneData = T_Malloc(sizeof(tAnimBone_t)*m->numBones); // copy frame bounding boxes f = (skcFrame_t *)( (byte *)h + sizeof(*h) ); of = out->frames; for(i = 0; i < h->numFrames; i++,of++,f++) { //anim->frames[i].radius = f->radius; VectorCopy(f->bounds[1],of->maxs); VectorCopy(f->bounds[0],of->mins); } // detect which components changes for(j = 0; j < m->numBones; j++) { float *baseRot, *testRot; float *basePos, *testPos; basePos = findPosChannel(h,m->bones[j].name,0); if(basePos == 0) { VectorSet(baseFrame[j].p,0,0,0); } else { VectorScale(basePos,scale,basePos); VectorCopy(basePos,baseFrame[j].p); for(i = 1; i < h->numFrames; i++) { testPos = findPosChannel(h,m->bones[j].name,i); VectorScale(testPos,scale,testPos); // detect X change if(testPos[0] != basePos[0]) { cFlags[j] |= COMPONENT_BIT_TX; } // detect Y change if(testPos[1] != basePos[1]) { cFlags[j] |= COMPONENT_BIT_TY; } // detect Z change if(testPos[2] != basePos[2]) { cFlags[j] |= COMPONENT_BIT_TZ; } } } baseRot = findRotChannel(h,m->bones[j].name,0,m->bones[j].parent); if(baseRot == 0) { QuatSet(baseFrame[j].q,0,0,0,-1); } else { QuatCopy(baseRot,baseFrame[j].q); for(i = 1; i < h->numFrames; i++) { testRot = findRotChannel(h,m->bones[j].name,i,m->bones[j].parent); // detect X change if(testRot[0] != baseRot[0]) { cFlags[j] |= COMPONENT_BIT_QX; } // detect Y change if(testRot[1] != baseRot[1]) { cFlags[j] |= COMPONENT_BIT_QY; } // detect Z change if(testRot[2] != baseRot[2]) { cFlags[j] |= COMPONENT_BIT_QZ; } // NOTE: quaternion W component is not stored at all in md5 files } } } // count the number of animated components and copy some bone data numAnimatedComponents = 0; for(j = 0; j < m->numBones; j++) { //int c; out->boneData[j].firstComponent = numAnimatedComponents; //c = 0; for(i = 0; i < 6; i++) { if(cFlags[j] & (1 << i)) { numAnimatedComponents++; // c++; } } //out->boneData[j].numAnimatedComponents = c; out->boneData[j].componentBits = cFlags[j]; strcpy(out->boneData[j].name,m->bones[j].name); out->boneData[j].parent = m->bones[j].parent; } // copy results out out->baseFrame = T_Malloc(sizeof(bone_t)*m->numBones); memcpy(out->baseFrame,baseFrame,sizeof(bone_t)*m->numBones); out->numAnimatedComponents = numAnimatedComponents; of = out->frames; for(i = 0; i < h->numFrames; i++,of++) { int c; float *cp; cp = of->components = T_Malloc(numAnimatedComponents*sizeof(float)); //c = 0; for(j = 0; j < m->numBones; j++) { float *pos, *rot; pos = findPosChannel(h,m->bones[j].name,i); if(pos) { VectorScale(pos,scale,pos); // write X change if(cFlags[j] & COMPONENT_BIT_TX) { *cp = pos[0]; cp++; } // write Y change if(cFlags[j] & COMPONENT_BIT_TY) { *cp = pos[1]; cp++; } // write Z change if(cFlags[j] & COMPONENT_BIT_TZ) { *cp = pos[2]; cp++; } } rot = findRotChannel(h,m->bones[j].name,i,m->bones[j].parent); if(rot) { // write X change if(cFlags[j] & COMPONENT_BIT_QX) { *cp = rot[0]; cp++; } // write Y change if(cFlags[j] & COMPONENT_BIT_QY) { *cp = rot[1]; cp++; } // write Z change if(cFlags[j] & COMPONENT_BIT_QZ) { *cp = rot[2]; cp++; } } } c = cp - of->components; assert(c == numAnimatedComponents); } #if 0 // validate generated tAnim_t components for(i = 0; i < out->numFrames; i++) { bone_t *b = setupMD5AnimBones(out,0); for(j = 0; j < m->numBones; j++, b++) { float *o; o = findRotChannel_raw(h,m->bones[j].name,i,m->bones[j].parent); if(o) { T_Printf("Generated: %f %f %f %f, original %f %f %f %f\n",b->q[0],b->q[1],b->q[2],b->q[3], o[0],o[1],o[2],o[3]); } else { T_Printf("Generated: %f %f %f %f, original <none>\n",b->q[0],b->q[1],b->q[2],b->q[3]); } } } #endif // generate baseFrame, but only once, // from the first appended SKC if(m->baseFrame == 0) { #if 0 // FIXME! bone_t *b = setupMD5AnimBones(out,0); //for(i = 0; i < m->numBones; i++) { // QuatInverse(b[i].q); //} #else bone_t b[512]; for(i = 0; i < m->numBones; i++) { float *p, *q; p = findPosChannel(h,m->bones[i].name,0); if(p) { VectorScale(p,scale,b[i].p); } else { VectorSet(b[i].p,0,0,0); } q = findRotChannel(h,m->bones[i].name,0,m->bones[i].parent); if(q) { QuatCopy(q,b[i].q); } else { QuatSet(b[i].q,0,0,0,1); } } #endif md5AnimateBones(m,b); m->baseFrame = T_Malloc(m->numBones*sizeof(bone_t)); memcpy(m->baseFrame,b,m->numBones*sizeof(bone_t)); } F_FreeBuf((byte*)h); T_Printf("Succesfully loaded MoHAA animation %s\n",fname); return out; }
void CL_ParseTEnt (void) { byte type; dlight_t *dl; tent_obj_t *to; explosion_t *ex; int colorStart, colorLength; int cnt = -1; vec3_t pos; sfx_t *spike_sound[] = { cl_sfx_ric3, cl_sfx_ric3, cl_sfx_ric2, cl_sfx_ric1, }; type = MSG_ReadByte (net_message); switch (type) { case TE_WIZSPIKE: // spike hitting wall MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_WizSpikeEffect (pos); S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); break; case TE_KNIGHTSPIKE: // spike hitting wall MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_KnightSpikeEffect (pos); S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); break; case TE_SPIKE: // spike hitting wall MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_SpikeEffect (pos); { int i; sfx_t *sound; i = (rand () % 20) - 16; if (i >= 0) sound = spike_sound[i]; else sound = cl_sfx_tink1; S_StartSound (-1, 0, sound, pos, 1, 1); } break; case TE_SUPERSPIKE: // super spike hitting wall MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_SuperSpikeEffect (pos); { int i; sfx_t *sound; i = (rand () % 20) - 16; if (i >= 0) sound = spike_sound[i]; else sound = cl_sfx_tink1; S_StartSound (-1, 0, sound, pos, 1, 1); } break; case TE_EXPLOSION: // rocket explosion // particles MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_ParticleExplosion (pos); // light dl = r_funcs->R_AllocDlight (0); if (dl) { VectorCopy (pos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; QuatSet (0.86, 0.31, 0.24, 0.7, dl->color); } // sound S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); // sprite to = new_tent_object (); to->next = cl_explosions; cl_explosions = to; ex = &to->to.ex; ex->tent = new_temp_entity (); VectorCopy (pos, ex->tent->ent.origin); ex->start = cl.time; //FIXME need better model management if (!cl_spr_explod->cache.data) cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); ex->tent->ent.model = cl_spr_explod; CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true); break; case TE_TAREXPLOSION: // tarbaby explosion MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_BlobExplosion (pos); S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); break; case TE_LIGHTNING1: // lightning bolts CL_ParseBeam (cl_mod_bolt); break; case TE_LIGHTNING2: // lightning bolts CL_ParseBeam (cl_mod_bolt2); break; case TE_LIGHTNING3: // lightning bolts CL_ParseBeam (cl_mod_bolt3); break; // PGM 01/21/97 case TE_BEAM: // grappling hook beam CL_ParseBeam (cl_mod_beam); break; // PGM 01/21/97 case TE_LAVASPLASH: MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_LavaSplash (pos); break; case TE_TELEPORT: MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_TeleportSplash (pos); break; case TE_EXPLOSION2: // color mapped explosion MSG_ReadCoordV (net_message, pos); colorStart = MSG_ReadByte (net_message); colorLength = MSG_ReadByte (net_message); S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); r_funcs->particles->R_ParticleExplosion2 (pos, colorStart, colorLength); dl = r_funcs->R_AllocDlight (0); if (!dl) break; VectorCopy (pos, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; colorStart = (colorStart + (rand () % colorLength)) * 3; VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0, dl->color); dl->color[3] = 0.7; break; case TE_GUNSHOT: // bullet hitting wall cnt = MSG_ReadByte (net_message) * 20; MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_GunshotEffect (pos, cnt); break; case TE_BLOOD: // bullet hitting body cnt = MSG_ReadByte (net_message) * 20; MSG_ReadCoordV (net_message, pos); r_funcs->particles->R_BloodPuffEffect (pos, cnt); break; case TE_LIGHTNINGBLOOD: // lightning hitting body MSG_ReadCoordV (net_message, pos); // light dl = r_funcs->R_AllocDlight (0); if (dl) { VectorCopy (pos, dl->origin); dl->radius = 150; dl->die = cl.time + 0.1; dl->decay = 200; QuatSet (0.25, 0.40, 0.65, 1, dl->color); } r_funcs->particles->R_LightningBloodEffect (pos); break; default: Sys_Error ("CL_ParseTEnt: bad type %d", type); } }