📄 ms3d.cpp
字号:
// Create materials and ranges //////////////////////////
Mesh->m_Ranges = new cMeshRange[Mesh->m_NumMaterials]();
Mesh->m_Materials = new D3DMATERIAL8[Mesh->m_NumMaterials];
Mesh->m_Textures = new IDirect3DTexture8*[Mesh->m_NumMaterials];
for(i=0;i<Mesh->m_NumMaterials;i++) {
Mesh->m_Materials[i].Diffuse.r = msMaterials[i].Diffuse[0];
Mesh->m_Materials[i].Diffuse.g = msMaterials[i].Diffuse[1];
Mesh->m_Materials[i].Diffuse.b = msMaterials[i].Diffuse[2];
Mesh->m_Materials[i].Ambient.r = msMaterials[i].Ambient[0];
Mesh->m_Materials[i].Ambient.g = msMaterials[i].Ambient[1];
Mesh->m_Materials[i].Ambient.b = msMaterials[i].Ambient[2];
Mesh->m_Materials[i].Specular.r = msMaterials[i].Specular[0];
Mesh->m_Materials[i].Specular.g = msMaterials[i].Specular[1];
Mesh->m_Materials[i].Specular.b = msMaterials[i].Specular[2];
Mesh->m_Materials[i].Emissive.r = msMaterials[i].Emissive[0];
Mesh->m_Materials[i].Emissive.g = msMaterials[i].Emissive[1];
Mesh->m_Materials[i].Emissive.b = msMaterials[i].Emissive[2];
Mesh->m_Materials[i].Power = msMaterials[i].Shininess;
Mesh->m_Textures[i] = NULL;
if(msMaterials[i].Texture[0]) {
char TextureFilename[MAX_PATH];
sprintf(TextureFilename, "%s%s", TexturePath, msMaterials[i].Texture);
Mesh->m_Textures[i] = pManager->Get(TextureFilename, 0, pDevice);
}
}
// Build vertex data ////////////////////////////////////
pDevice->CreateVertexBuffer(Mesh->m_NumVertices * sizeof(sMeshVertex), 0, MESHFVF, D3DPOOL_MANAGED, &Mesh->m_VertexBuffer);
Mesh->m_VertexBuffer->Lock(0, 0, (BYTE**)&Vertices, 0);
Pos = 0;
for(i=0;i<Mesh->m_NumFaces;i++) {
for(j=0;j<3;j++) {
// Store vertex coordinates
// Notice that x is reversed to change
// from right-handed to left-handed coordinates
Vertices[Pos].x = -msVertices[msFaces[i].Indices[j]].Pos[0];
Vertices[Pos].y = msVertices[msFaces[i].Indices[j]].Pos[1];
Vertices[Pos].z = msVertices[msFaces[i].Indices[j]].Pos[2];
// Store vertex normals
// Ditto on reversal of normal's x
Vertices[Pos].nx = -msFaces[i].Normal[j][0];
Vertices[Pos].ny = msFaces[i].Normal[j][1];
Vertices[Pos].nz = msFaces[i].Normal[j][2];
// Store vertex texture coordinates
Vertices[Pos].u = msFaces[i].u[j];
Vertices[Pos].v = msFaces[i].v[j];
// Assign bone, defaulting to #0 if none assigned.
// Multiply bone index by 3 to put in constant memory
Vertices[Pos].Bone = (float)msVertices[msFaces[i].Indices[j]].Bone * 3.0f;
// Go to next vertex/index
Pos++;
}
}
Mesh->m_VertexBuffer->Unlock();
// Indices are built by materials and groups - not by the
// face array. Go through each material and looking for
// matching groups. For each matching group, add those
// indices belonging to the group.
pDevice->CreateIndexBuffer(Mesh->m_NumFaces * 3 * sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &Mesh->m_IndexBuffer);
Mesh->m_IndexBuffer->Lock(0, 0, (BYTE**)&Indices, 0);
Pos = 0;
for(i=0;i<Mesh->m_NumMaterials;i++) {
// Store starting position of material range
Mesh->m_Ranges[i].m_StartFace = Pos;
// Scan through each group looking for matching materials
Num = 0;
for(j=0;j<msNumGroups;j++) {
if((DWORD)msGroups[j].Material == i) {
// Store indices in index buffer.
// Notice that order reversed, as Milkshape 3D
// uses right-hand system, not left as we do here.
for(k=0;k<msGroups[j].Header.NumFaces;k++) {
DWORD Face = msGroups[j].Indices[k] * 3;
Indices[Pos++] = msGroups[j].Indices[k] * 3 + 2;
Indices[Pos++] = msGroups[j].Indices[k] * 3 + 1;
Indices[Pos++] = msGroups[j].Indices[k] * 3 + 0;
}
// Increase face count
Num += msGroups[j].Header.NumFaces;
}
}
// Store # faces
Mesh->m_Ranges[i].m_NumFaces = Num;
}
Mesh->m_IndexBuffer->Unlock();
// Load animations //////////////////////////////////////
for(i=0;i<NumAnimations;i++)
LoadMS3DAnimation(MeshGroup, Mesh, AnimFilenames[i*2], AnimFilenames[i*2+1], AnimPos);
// Release all used data
delete [] msVertices;
delete [] msFaces;
delete [] msGroups;
delete [] msMaterials;
delete [] msBones;
// Return success
return TRUE;
}
BOOL LoadMS3DAnimation(cMeshGroup *MeshGroup,
cMeshContainer *Mesh,
char *Filename, char *Name,
DWORD Pos)
{
FILE *fp;
cAnimationContainer *Anim = NULL;
float msAnimationFPS, msCurrentTime;
int msTotalFrames;
unsigned short msNumBones;
sMS3DBone *msBones = NULL;
DWORD i, j, Num, NumFrames=0;
// Error checking
if(MeshGroup == NULL || Filename == NULL || Name == NULL || !Mesh->m_NumBones)
return FALSE;
// Open file and seek to start of bone data
if((fp=fopen(Filename, "rb"))==NULL)
return FALSE;
fseek(fp, Pos, SEEK_SET);
// Get animation FPS, editor time, and total frames
fread(&msAnimationFPS, 1, sizeof(float), fp);
fread(&msCurrentTime, 1, sizeof(float), fp);
fread(&msTotalFrames, 1, sizeof(int), fp);
// Read in # of bones and compare to # in mesh
fread(&msNumBones, 1, sizeof(short), fp);
if((DWORD)msNumBones != Mesh->m_NumBones) {
fclose(fp);
return FALSE;
}
// Read in bone data
msBones = new sMS3DBone[Mesh->m_NumBones];
for(i=0;i<Mesh->m_NumBones;i++) {
fread(&msBones[i], 1, sizeof(msBones[i].Header), fp);
// Read in animation rotation keys
if((Num = msBones[i].Header.NumRotFrames)) {
// Store highest keyframe #
if(Num > NumFrames)
NumFrames = Num;
// Create and read in keyframe data
msBones[i].RotKeyFrames = new sMS3DKeyFrame[Num];
for(j=0;j<Num;j++)
fread(&msBones[i].RotKeyFrames[j], 1, sizeof(sMS3DKeyFrame), fp);
}
// Read in animation position keys
if((Num=msBones[i].Header.NumPosFrames)) {
// Store highest keyframe #
if(Num > NumFrames)
NumFrames = Num;
// Create and read in keyframe data
msBones[i].PosKeyFrames = new sMS3DKeyFrame[Num];
for(j=0;j<Num;j++)
fread(&msBones[i].PosKeyFrames[j], 1, sizeof(sMS3DKeyFrame), fp);
}
}
// Close file
fclose(fp);
// Don't go any further if there is no keyframes
if(!NumFrames) {
delete [] msBones;
return FALSE;
}
// Build animation data
Anim = new cAnimationContainer();
// Assign a name to animation
Anim->m_Name = strdup(Name);
// Allocate the frames (using # of position keys as length)
Anim->m_NumFrames = (DWORD)NumFrames;
Anim->m_Frames = new cAnimationFrame[Anim->m_NumFrames]();
// Go through each frame and create transformation matrices
for(i=0;i<Anim->m_NumFrames;i++) {
// Point frame to next (for linked list)
if(i < Anim->m_NumFrames-1)
Anim->m_Frames[i].m_Next = &Anim->m_Frames[i+1];
// Allocate the matrices
Anim->m_Frames[i].m_matTransformations = new D3DXMATRIX[Mesh->m_NumBones];
// Store the time of this frame (from 1st bone Position key)
Anim->m_Frames[i].m_Time = (DWORD)(msBones[0].PosKeyFrames[i].Time * msAnimationFPS) * 30;
// Store length of animation based on last time
Anim->m_Length = Anim->m_Frames[i].m_Time + 1;
// Go through each bone and create transformation matrix
for(j=0;j<Mesh->m_NumBones;j++) {
// Calculate the bone's orientation
D3DXMATRIX matX, matY, matZ, matXYZ, matWorld;
D3DXMatrixRotationX(&matX, msBones[j].RotKeyFrames[i].Value[0]);
D3DXMatrixRotationY(&matY, msBones[j].RotKeyFrames[i].Value[1]);
D3DXMatrixRotationZ(&matZ, msBones[j].RotKeyFrames[i].Value[2]);
D3DXMatrixTranslation(&matXYZ,
msBones[j].PosKeyFrames[i].Value[0],
msBones[j].PosKeyFrames[i].Value[1],
msBones[j].PosKeyFrames[i].Value[2]);
D3DXMatrixMultiply(&matWorld, &matX, &matY);
D3DXMatrixMultiply(&matWorld, &matWorld, &matZ);
D3DXMatrixMultiply(&matWorld, &matWorld, &matXYZ);
// Combine the frame's transformation matrix to
// the bone's transformation matrix to obtain
// the final transformation matrix.
D3DXMatrixMultiply(&Anim->m_Frames[i].m_matTransformations[j],
&matWorld,
&Mesh->m_Bones->m_matTransformations[j]);
}
}
// Free used resources
delete [] msBones;
// Link animation into list (as last in list)
if(MeshGroup->m_Animations == NULL)
MeshGroup->m_Animations = Anim;
else {
// Scan to end of list and link in
cAnimationContainer *AnimPtr = MeshGroup->m_Animations;
while(AnimPtr->m_Next != NULL)
AnimPtr = AnimPtr->m_Next;
AnimPtr->m_Next = Anim;
}
MeshGroup->m_NumAnimations++;
return TRUE;
}
char *CleanMS3DName(char *Name)
{
char *NewName, *NamePtr, *Ptr;
// Error checking
if(Name == NULL)
return NULL;
// Find beginning of filename (remove path)
if((Ptr = strrchr(Name, '\\')) == NULL)
Ptr = Name;
// Allocate some memory to save new name
NamePtr = NewName = new char[strlen(Ptr)];
// Copy over until a period or EOL found
while(Ptr && *Ptr != '.')
*NamePtr++ = *Ptr++;
*NamePtr = 0;
// Return resulting string
return strdup(NewName);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -