📄 3ds.cpp
字号:
// The current chunk to work with
tChunk currentChunk = {0};
// Continue to read these chunks until we read the end of this sub chunk
while (pPreviousChunk->bytesRead < pPreviousChunk->length)
{
// Read the next chunk
ReadChunk(¤tChunk);
// Check which chunk we just read in
switch (currentChunk.ID)
{
case MATNAME: // This chunk holds the name of the material
// Here we read in the material name
currentChunk.bytesRead += fread(pModel->pMaterials[pModel->numOfMaterials - 1].strName, 1, currentChunk.length - currentChunk.bytesRead, m_FilePointer);
break;
case MATDIFFUSE: // This holds the R G B color of our object
ReadColorChunk(&(pModel->pMaterials[pModel->numOfMaterials - 1]), ¤tChunk);
break;
case MATMAP: // This is the header for the texture info
// Proceed to read in the material information
ProcessNextMaterialChunk(pModel, ¤tChunk);
break;
case MATMAPFILE: // This stores the file name of the material
// Here we read in the material's file name
currentChunk.bytesRead += fread(pModel->pMaterials[pModel->numOfMaterials - 1].strFile, 1, currentChunk.length - currentChunk.bytesRead, m_FilePointer);
break;
default:
// Read past the ignored or unknown chunks
currentChunk.bytesRead += fread(gBuffer, 1, currentChunk.length - currentChunk.bytesRead, m_FilePointer);
break;
}
// Add the bytes read from the last chunk to the previous chunk passed in.
pPreviousChunk->bytesRead += currentChunk.bytesRead;
}
}
///////////////////////////////// READ CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function reads in a chunk ID and it's length in bytes
/////
///////////////////////////////// READ CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CLoad3DS::ReadChunk(tChunk *pChunk)
{
// This reads the chunk ID which is 2 bytes.
// The chunk ID is like OBJECT or MATERIAL. It tells what data is
// able to be read in within the chunks section.
pChunk->bytesRead = fread(&pChunk->ID, 1, 2, m_FilePointer);
// Then, we read the length of the chunk which is 4 bytes.
// This is how we know how much to read in, or read past.
pChunk->bytesRead += fread(&pChunk->length, 1, 4, m_FilePointer);
}
///////////////////////////////// GET STRING \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function reads in a string of characters
/////
///////////////////////////////// GET STRING \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
int CLoad3DS::GetString(char *pBuffer)
{
int index = 0;
// Read 1 byte of data which is the first letter of the string
fread(pBuffer, 1, 1, m_FilePointer);
// Loop until we get NULL
while (*(pBuffer + index++) != 0) {
// Read in a character at a time until we hit NULL.
fread(pBuffer + index, 1, 1, m_FilePointer);
}
// Return the string length, which is how many bytes we read in (including the NULL)
return strlen(pBuffer) + 1;
}
///////////////////////////////// READ COLOR \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function reads in the RGB color data
/////
///////////////////////////////// READ COLOR \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CLoad3DS::ReadColorChunk(tMaterialInfo *pMaterial, tChunk *pChunk)
{
tChunk tempChunk = {0};
// Read the color chunk info
ReadChunk(&tempChunk);
// Read in the R G B color (3 bytes - 0 through 255)
tempChunk.bytesRead += fread(pMaterial->color, 1, tempChunk.length - tempChunk.bytesRead, m_FilePointer);
// Add the bytes read to our chunk
pChunk->bytesRead += tempChunk.bytesRead;
}
///////////////////////////////// READ VERTEX INDECES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function reads in the indices for the vertex array
/////
///////////////////////////////// READ VERTEX INDECES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CLoad3DS::ReadVertexIndices(t3DObject *pObject, tChunk *pPreviousChunk)
{
unsigned short index = 0; // This is used to read in the current face index
// In order to read in the vertex indices for the object, we need to first
// read in the number of them, then read them in. Remember,
// we only want 3 of the 4 values read in for each face. The fourth is
// a visibility flag for 3D Studio Max that doesn't mean anything to us.
// Read in the number of faces that are in this object (int)
pPreviousChunk->bytesRead += fread(&pObject->numOfFaces, 1, 2, m_FilePointer);
// Alloc enough memory for the faces and initialize the structure
pObject->pFaces = new tFace [pObject->numOfFaces];
memset(pObject->pFaces, 0, sizeof(tFace) * pObject->numOfFaces);
// Go through all of the faces in this object
for(int i = 0; i < pObject->numOfFaces; i++)
{
// Next, we read in the A then B then C index for the face, but ignore the 4th value.
// The fourth value is a visibility flag for 3D Studio Max, we don't care about this.
for(int j = 0; j < 4; j++)
{
// Read the first vertice index for the current face
pPreviousChunk->bytesRead += fread(&index, 1, sizeof(index), m_FilePointer);
if(j < 3)
{
// Store the index in our face structure.
pObject->pFaces[i].vertIndex[j] = index;
}
}
}
}
///////////////////////////////// READ UV COORDINATES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function reads in the UV coordinates for the object
/////
///////////////////////////////// READ UV COORDINATES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CLoad3DS::ReadUVCoordinates(t3DObject *pObject, tChunk *pPreviousChunk)
{
// In order to read in the UV indices for the object, we need to first
// read in the amount there are, then read them in.
// Read in the number of UV coordinates there are (int)
pPreviousChunk->bytesRead += fread(&pObject->numTexVertex, 1, 2, m_FilePointer);
// Allocate memory to hold the UV coordinates
pObject->pTexVerts = new CVector2 [pObject->numTexVertex];
// Read in the texture coodinates (an array 2 float)
pPreviousChunk->bytesRead += fread(pObject->pTexVerts, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);
}
///////////////////////////////// READ VERTICES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function reads in the vertices for the object
/////
///////////////////////////////// READ VERTICES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CLoad3DS::ReadVertices(t3DObject *pObject, tChunk *pPreviousChunk)
{
// Like most chunks, before we read in the actual vertices, we need
// to find out how many there are to read in. Once we have that number
// we then fread() them into our vertice array.
// Read in the number of vertices (int)
pPreviousChunk->bytesRead += fread(&(pObject->numOfVerts), 1, 2, m_FilePointer);
// Allocate the memory for the verts and initialize the structure
pObject->pVerts = new CVector3 [pObject->numOfVerts];
memset(pObject->pVerts, 0, sizeof(CVector3) * pObject->numOfVerts);
// Read in the array of vertices (an array of 3 floats)
pPreviousChunk->bytesRead += fread(pObject->pVerts, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);
// Now we should have all of the vertices read in. Because 3D Studio Max
// Models with the Z-Axis pointing up (strange and ugly I know!), we need
// to flip the y values with the z values in our vertices. That way it
// will be normal, with Y pointing up. If you prefer to work with Z pointing
// up, then just delete this next loop. Also, because we swap the Y and Z
// we need to negate the Z to make it come out correctly.
// Go through all of the vertices that we just read and swap the Y and Z values
for(int i = 0; i < pObject->numOfVerts; i++)
{
// Store off the Y value
float fTempY = pObject->pVerts[i].y;
// Set the Y value to the Z value
pObject->pVerts[i].y = pObject->pVerts[i].z;
// Set the Z value to the Y value,
// but negative Z because 3D Studio max does the opposite.
pObject->pVerts[i].z = -fTempY;
}
}
///////////////////////////////// READ OBJECT MATERIAL \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function reads in the material name assigned to the object and sets the materialID
/////
///////////////////////////////// READ OBJECT MATERIAL \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void CLoad3DS::ReadObjectMaterial(t3DModel *pModel, t3DObject *pObject, tChunk *pPreviousChunk)
{
char strMaterial[255] = {0}; // This is used to hold the objects material name
// *What is a material?* - A material is either the color or the texture map of the object.
// It can also hold other information like the brightness, shine, etc... Stuff we don't
// really care about. We just want the color, or the texture map file name really.
// Here we read the material name that is assigned to the current object.
// strMaterial should now have a string of the material name, like "Material #2" etc..
pPreviousChunk->bytesRead += GetString(strMaterial);
// Now that we have a material name, we need to go through all of the materials
// and check the name against each material. When we find a material in our material
// list that matches this name we just read in, then we assign the materialID
// of the object to that material index. You will notice that we passed in the
// model to this function. This is because we need the number of textures.
// Yes though, we could have just passed in the model and not the object too.
// Go through all of the textures
for(int i = 0; i < pModel->numOfMaterials; i++)
{
// If the material we just read in matches the current texture name
if(strcmp(strMaterial, pModel->pMaterials[i].strName) == 0)
{
// Set the material ID to the current index 'i' and stop checking
pObject->materialID = i;
// Now that we found the material, check if it's a texture map.
// If the strFile has a string length of 1 and over it's a texture
if(strlen(pModel->pMaterials[i].strFile) > 0) {
// Set the object's flag to say it has a texture map to bind.
pObject->bHasTexture = true;
}
break;
}
else
{
// Set the ID to -1 to show there is no material for this object
pObject->materialID = -1;
}
}
// Read past the rest of the chunk since we don't care about shared vertices
// You will notice we subtract the bytes already read in this chunk from the total length.
pPreviousChunk->bytesRead += fread(gBuffer, 1, pPreviousChunk->length - pPreviousChunk->bytesRead, m_FilePointer);
}
// *Note*
//
// Below are some math functions for calculating vertex normals. We want vertex normals
// because it makes the lighting look really smooth and life like. You probably already
// have these functions in the rest of your engine, so you can delete these and call
// your own. I wanted to add them so I could show how to calculate vertex normals.
////////////////////////////// Math Functions ////////////////////////////////*
// This computes the magnitude of a normal. (magnitude = sqrt(x^2 + y^2 + z^2)
#define Mag(Normal) (sqrt(Normal.x*Normal.x + Normal.y*Normal.y + Normal.z*Normal.z))
// This calculates a vector between 2 points and returns the result
CVector3 Vector(CVector3 vPoint1, CVector3 vPoint2)
{
CVector3 vVector; // The variable to hold the resultant vector
vVector.x = vPoint1.x - vPoint2.x; // Subtract point1 and point2 x's
vVector.y = vPoint1.y - vPoint2.y; // Subtract point1 and point2 y's
vVector.z = vPoint1.z - vPoint2.z; // Subtract point1 and point2 z's
return vVector; // Return the resultant vector
}
// This adds 2 vectors together and returns the result
CVector3 AddVector(CVector3 vVector1, CVector3 vVector2)
{
CVector3 vResult; // The variable to hold the resultant vector
vResult.x = vVector2.x + vVector1.x; // Add Vector1 and Vector2 x's
vResult.y = vVector2.y + vVector1.y; // Add Vector1 and Vector2 y's
vResult.z = vVector2.z + vVector1.z; // Add Vector1 and Vector2 z's
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -