Commit a2d8e808 authored by hybrid's avatar hybrid

Added some checks and documentation. Reenabled the normal calculation for...

Added some checks and documentation. Reenabled the normal calculation for non-lighted meshes to make them complete in all occasions. Due to lack of meshes not tested against animated meshes.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1145 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 05667475
...@@ -19,7 +19,7 @@ namespace scene ...@@ -19,7 +19,7 @@ namespace scene
//! Constructor //! Constructor
CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr) CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr)
: B3dStack(), NormalsInFile(false), SceneManager(smgr), AnimatedMesh(0), file(0) : NormalsInFile(false), SceneManager(smgr), AnimatedMesh(0), B3DFile(0)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CB3DMeshFileLoader"); setDebugName("CB3DMeshFileLoader");
...@@ -52,7 +52,7 @@ IAnimatedMesh* CB3DMeshFileLoader::createMesh(io::IReadFile* f) ...@@ -52,7 +52,7 @@ IAnimatedMesh* CB3DMeshFileLoader::createMesh(io::IReadFile* f)
if (!f) if (!f)
return 0; return 0;
file = f; B3DFile = f;
AnimatedMesh = new scene::CSkinnedMesh(); AnimatedMesh = new scene::CSkinnedMesh();
Buffers = &AnimatedMesh->getMeshBuffers(); Buffers = &AnimatedMesh->getMeshBuffers();
...@@ -81,78 +81,56 @@ bool CB3DMeshFileLoader::load() ...@@ -81,78 +81,56 @@ bool CB3DMeshFileLoader::load()
//------ Get header ------ //------ Get header ------
SB3dChunkHeader header; SB3dChunkHeader header;
file->read(&header, sizeof(header)); B3DFile->read(&header, sizeof(header));
#ifdef __BIG_ENDIAN__
#ifdef __BIG_ENDIAN__
header.size = os::Byteswap::byteswap(header.size); header.size = os::Byteswap::byteswap(header.size);
#endif #endif
if ( strncmp( header.name, "BB3D", 4 ) != 0 ) if ( strncmp( header.name, "BB3D", 4 ) != 0 )
{ {
os::Printer::log("File is not a b3d file. Loading failed (No header found)", file->getFileName(), ELL_ERROR); os::Printer::log("File is not a b3d file. Loading failed (No header found)", B3DFile->getFileName(), ELL_ERROR);
return false; return false;
} }
// Add main chunk... // Add main chunk...
B3dStack.push_back(SB3dChunk()); B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));
B3dStack.getLast().name[0] = header.name[0];
B3dStack.getLast().name[1] = header.name[1];
B3dStack.getLast().name[2] = header.name[2];
B3dStack.getLast().name[3] = header.name[3];
B3dStack.getLast().startposition = file->getPos()-8;
B3dStack.getLast().length = header.size+8;
// Get file version, but ignore it, as it's not important with b3d files... // Get file version, but ignore it, as it's not important with b3d files...
u32 FileVersion; s32 fileVersion;
file->read(&FileVersion, sizeof(FileVersion)); B3DFile->read(&fileVersion, sizeof(fileVersion));
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
FileVersion = os::Byteswap::byteswap(FileVersion); fileVersion = os::Byteswap::byteswap(fileVersion);
#endif #endif
//------ Read main chunk ------ //------ Read main chunk ------
while ( (B3dStack.getLast().startposition + B3dStack.getLast().length) > file->getPos() ) while ( (B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos() )
{ {
B3dStack.push_back(SB3dChunk()); B3DFile->read(&header, sizeof(header));
#ifdef __BIG_ENDIAN__
file->read(&header, sizeof(header));
#ifdef __BIG_ENDIAN__
header.size = os::Byteswap::byteswap(header.size); header.size = os::Byteswap::byteswap(header.size);
#endif #endif
B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));
B3dStack.getLast().name[0] = header.name[0];
B3dStack.getLast().name[1] = header.name[1];
B3dStack.getLast().name[2] = header.name[2];
B3dStack.getLast().name[3] = header.name[3];
B3dStack.getLast().startposition = file->getPos() - 8;
B3dStack.getLast().length = header.size + 8;
bool knownChunk = false;
if ( strncmp( B3dStack.getLast().name, "TEXS", 4 ) == 0 ) if ( strncmp( B3dStack.getLast().name, "TEXS", 4 ) == 0 )
{ {
knownChunk=true;
if (!readChunkTEXS()) if (!readChunkTEXS())
return false; return false;
} }
else if ( strncmp( B3dStack.getLast().name, "BRUS", 4 ) == 0 ) else if ( strncmp( B3dStack.getLast().name, "BRUS", 4 ) == 0 )
{ {
knownChunk=true;
if (!readChunkBRUS()) if (!readChunkBRUS())
return false; return false;
} }
else if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 ) else if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 )
{ {
knownChunk=true;
if (!readChunkNODE((CSkinnedMesh::SJoint*)0) ) if (!readChunkNODE((CSkinnedMesh::SJoint*)0) )
return false; return false;
} }
else
if (!knownChunk)
{ {
os::Printer::log("Unknown chunk found in mesh base - skipping"); os::Printer::log("Unknown chunk found in mesh base - skipping");
file->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);
B3dStack.erase(B3dStack.size()-1); B3dStack.erase(B3dStack.size()-1);
} }
} }
...@@ -205,61 +183,45 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint) ...@@ -205,61 +183,45 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint)
else else
Joint->GlobalMatrix = Joint->LocalMatrix; Joint->GlobalMatrix = Joint->LocalMatrix;
while(B3dStack.getLast().startposition + B3dStack.getLast().length > file->getPos()) // this chunk repeats while(B3dStack.getLast().startposition + B3dStack.getLast().length > B3DFile->getPos()) // this chunk repeats
{ {
B3dStack.push_back(SB3dChunk());
SB3dChunkHeader header; SB3dChunkHeader header;
file->read(&header, sizeof(header)); B3DFile->read(&header, sizeof(header));
#ifdef __BIG_ENDIAN__
#ifdef __BIG_ENDIAN__
header.size = os::Byteswap::byteswap(header.size); header.size = os::Byteswap::byteswap(header.size);
#endif #endif
B3dStack.getLast().name[0] = header.name[0]; B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));
B3dStack.getLast().name[1] = header.name[1];
B3dStack.getLast().name[2] = header.name[2];
B3dStack.getLast().name[3] = header.name[3];
B3dStack.getLast().length = header.size+8;
B3dStack.getLast().startposition = file->getPos() - 8;
bool knownChunk = false;
if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 ) if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 )
{ {
knownChunk = true;
if (!readChunkNODE(Joint)) if (!readChunkNODE(Joint))
return false; return false;
} }
else if ( strncmp( B3dStack.getLast().name, "MESH", 4 ) == 0 ) else if ( strncmp( B3dStack.getLast().name, "MESH", 4 ) == 0 )
{ {
knownChunk = true;
if (!readChunkMESH(Joint)) if (!readChunkMESH(Joint))
return false; return false;
} }
else if ( strncmp( B3dStack.getLast().name, "ANIM", 4 ) == 0 )
{
knownChunk = true;
if (!readChunkANIM())
return false;
}
else if ( strncmp( B3dStack.getLast().name, "BONE", 4 ) == 0 ) else if ( strncmp( B3dStack.getLast().name, "BONE", 4 ) == 0 )
{ {
knownChunk = true;
if (!readChunkBONE(Joint)) if (!readChunkBONE(Joint))
return false; return false;
} }
else if ( strncmp( B3dStack.getLast().name, "KEYS", 4 ) == 0 ) else if ( strncmp( B3dStack.getLast().name, "KEYS", 4 ) == 0 )
{ {
knownChunk = true;
if(!readChunkKEYS(Joint)) if(!readChunkKEYS(Joint))
return false; return false;
} }
else if ( strncmp( B3dStack.getLast().name, "ANIM", 4 ) == 0 )
if (!knownChunk) {
if (!readChunkANIM())
return false;
}
else
{ {
os::Printer::log("Unknown chunk found in node chunk - skipping"); os::Printer::log("Unknown chunk found in node chunk - skipping");
file->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);
B3dStack.erase(B3dStack.size()-1); B3dStack.erase(B3dStack.size()-1);
} }
} }
...@@ -269,50 +231,36 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint) ...@@ -269,50 +231,36 @@ bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint)
return true; return true;
} }
bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint) bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint)
{ {
const s32 vertices_Start=BaseVertices.size(); //B3Ds have Vertex ID's local within the mesh I don't want this const s32 vertices_Start=BaseVertices.size(); //B3Ds have Vertex ID's local within the mesh I don't want this
s32 brush_id; s32 brush_id;
B3DFile->read(&brush_id, sizeof(brush_id));
file->read(&brush_id, sizeof(brush_id)); #ifdef __BIG_ENDIAN__
#ifdef __BIG_ENDIAN__
brush_id = os::Byteswap::byteswap(brush_id); brush_id = os::Byteswap::byteswap(brush_id);
#endif #endif
NormalsInFile=false; NormalsInFile=false;
while(B3dStack.getLast().startposition + B3dStack.getLast().length>file->getPos()) //this chunk repeats while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
{ {
B3dStack.push_back(SB3dChunk());
SB3dChunkHeader header; SB3dChunkHeader header;
file->read(&header, sizeof(header)); B3DFile->read(&header, sizeof(header));
#ifdef __BIG_ENDIAN__
#ifdef __BIG_ENDIAN__
header.size = os::Byteswap::byteswap(header.size); header.size = os::Byteswap::byteswap(header.size);
#endif #endif
B3dStack.getLast().name[0]=header.name[0];
B3dStack.getLast().name[1]=header.name[1]; //Not sure of an easier way
B3dStack.getLast().name[2]=header.name[2];
B3dStack.getLast().name[3]=header.name[3];
B3dStack.getLast().length = header.size + 8;
B3dStack.getLast().startposition = file->getPos() - 8;
bool knownChunk=false; B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));
if ( strncmp( B3dStack.getLast().name, "VRTS", 4 ) == 0 ) if ( strncmp( B3dStack.getLast().name, "VRTS", 4 ) == 0 )
{ {
knownChunk=true;
if (!readChunkVRTS(InJoint)) if (!readChunkVRTS(InJoint))
return false; return false;
} }
else if ( strncmp( B3dStack.getLast().name, "TRIS", 4 ) == 0 ) else if ( strncmp( B3dStack.getLast().name, "TRIS", 4 ) == 0 )
{ {
knownChunk=true;
scene::SSkinMeshBuffer *MeshBuffer = AnimatedMesh->createBuffer(); scene::SSkinMeshBuffer *MeshBuffer = AnimatedMesh->createBuffer();
if (brush_id!=-1) if (brush_id!=-1)
...@@ -321,13 +269,13 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint) ...@@ -321,13 +269,13 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint)
if(readChunkTRIS(MeshBuffer,AnimatedMesh->getMeshBuffers().size()-1, vertices_Start)==false) if(readChunkTRIS(MeshBuffer,AnimatedMesh->getMeshBuffers().size()-1, vertices_Start)==false)
return false; return false;
if (!NormalsInFile && MeshBuffer->Material.Lighting) // No point wasting time on lightmapped levels if (!NormalsInFile)
{ {
s32 i; s32 i;
for ( i=0; i<(s32)MeshBuffer->Indices.size(); i+=3) for ( i=0; i<(s32)MeshBuffer->Indices.size(); i+=3)
{ {
core::plane3d<f32> p( MeshBuffer->getVertex(MeshBuffer->Indices[i+0])->Pos, core::plane3df p(MeshBuffer->getVertex(MeshBuffer->Indices[i+0])->Pos,
MeshBuffer->getVertex(MeshBuffer->Indices[i+1])->Pos, MeshBuffer->getVertex(MeshBuffer->Indices[i+1])->Pos,
MeshBuffer->getVertex(MeshBuffer->Indices[i+2])->Pos); MeshBuffer->getVertex(MeshBuffer->Indices[i+2])->Pos);
...@@ -338,16 +286,15 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint) ...@@ -338,16 +286,15 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint)
for ( i = 0; i<(s32)MeshBuffer->getVertexCount(); ++i ) for ( i = 0; i<(s32)MeshBuffer->getVertexCount(); ++i )
{ {
MeshBuffer->getVertex(i)->Normal.normalize (); MeshBuffer->getVertex(i)->Normal.normalize();
BaseVertices[vertices_Start+i].Normal=MeshBuffer->getVertex(i)->Normal; BaseVertices[vertices_Start+i].Normal=MeshBuffer->getVertex(i)->Normal;
} }
} }
} }
else
if (!knownChunk)
{ {
os::Printer::log("Unknown chunk found in mesh - skipping"); os::Printer::log("Unknown chunk found in mesh - skipping");
file->seek(B3dStack.getLast().startposition + B3dStack.getLast().length); B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);
B3dStack.erase(B3dStack.size()-1); B3dStack.erase(B3dStack.size()-1);
} }
} }
...@@ -362,6 +309,7 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint) ...@@ -362,6 +309,7 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint)
VRTS: VRTS:
int flags ;1=normal values present, 2=rgba values present int flags ;1=normal values present, 2=rgba values present
int tex_coord_sets ;texture coords per vertex (eg: 1 for simple U/V) max=8 int tex_coord_sets ;texture coords per vertex (eg: 1 for simple U/V) max=8
but we only support 3
int tex_coord_set_size ;components per set (eg: 2 for simple U/V) max=4 int tex_coord_set_size ;components per set (eg: 2 for simple U/V) max=4
{ {
float x,y,z ;always present float x,y,z ;always present
...@@ -372,27 +320,26 @@ VRTS: ...@@ -372,27 +320,26 @@ VRTS:
*/ */
bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint)
{ {
const s32 max_tex_coords = 3;
s32 flags, tex_coord_sets, tex_coord_set_size; s32 flags, tex_coord_sets, tex_coord_set_size;
file->read(&flags, sizeof(flags)); B3DFile->read(&flags, sizeof(flags));
file->read(&tex_coord_sets, sizeof(tex_coord_sets)); B3DFile->read(&tex_coord_sets, sizeof(tex_coord_sets));
file->read(&tex_coord_set_size, sizeof(tex_coord_set_size)); B3DFile->read(&tex_coord_set_size, sizeof(tex_coord_set_size));
#ifdef __BIG_ENDIAN__
#ifdef __BIG_ENDIAN__
flags = os::Byteswap::byteswap(flags); flags = os::Byteswap::byteswap(flags);
tex_coord_sets = os::Byteswap::byteswap(tex_coord_sets); tex_coord_sets = os::Byteswap::byteswap(tex_coord_sets);
tex_coord_set_size = os::Byteswap::byteswap(tex_coord_set_size); tex_coord_set_size = os::Byteswap::byteswap(tex_coord_set_size);
#endif #endif
if (tex_coord_sets >= 3 || tex_coord_set_size >= 4) // Something is wrong if (tex_coord_sets >= max_tex_coords || tex_coord_set_size >= 4) // Something is wrong
{ {
os::Printer::log("tex_coord_sets or tex_coord_set_size too big", file->getFileName(), ELL_ERROR); os::Printer::log("tex_coord_sets or tex_coord_set_size too big", B3DFile->getFileName(), ELL_ERROR);
return false; return false;
} }
//------ Allocate Memory, for speed -----------// //------ Allocate Memory, for speed -----------//
s32 MemoryNeeded = B3dStack.getLast().length / sizeof(f32);
s32 NumberOfReads = 3; s32 NumberOfReads = 3;
if (flags & 1) if (flags & 1)
...@@ -402,19 +349,19 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) ...@@ -402,19 +349,19 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint)
NumberOfReads += tex_coord_sets*tex_coord_set_size; NumberOfReads += tex_coord_sets*tex_coord_set_size;
MemoryNeeded /= NumberOfReads; const s32 MemoryNeeded = (B3dStack.getLast().length / sizeof(f32)) / NumberOfReads;
BaseVertices.reallocate(MemoryNeeded + BaseVertices.size() + 1); BaseVertices.reallocate(MemoryNeeded + BaseVertices.size() + 1);
AnimatedVertices_VertexID.reallocate(MemoryNeeded + AnimatedVertices_VertexID.size() + 1); AnimatedVertices_VertexID.reallocate(MemoryNeeded + AnimatedVertices_VertexID.size() + 1);
//--------------------------------------------// //--------------------------------------------//
while(B3dStack.getLast().startposition + B3dStack.getLast().length > file->getPos()) // this chunk repeats while( (B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats
{ {
f32 position[3]; f32 position[3];
f32 normal[3]={0.f, 0.f, 0.f}; f32 normal[3]={0.f, 0.f, 0.f};
f32 color[4]={1.0f, 1.0f, 1.0f, 1.0f}; f32 color[4]={1.0f, 1.0f, 1.0f, 1.0f};
f32 tex_coords[3][4]; f32 tex_coords[max_tex_coords][4];
readFloats(position, 3); readFloats(position, 3);
...@@ -438,7 +385,7 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) ...@@ -438,7 +385,7 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint)
} }
f32 tu2=0.0f, tv2=0.0f; f32 tu2=0.0f, tv2=0.0f;
if (tex_coord_sets>=2 && tex_coord_set_size>=2) if (tex_coord_sets>1 && tex_coord_set_size>1)
{ {
tu2=tex_coords[1][0]; tu2=tex_coords[1][0];
tv2=tex_coords[1][1]; tv2=tex_coords[1][1];
...@@ -469,16 +416,13 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint) ...@@ -469,16 +416,13 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint)
bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 vertices_Start) bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 vertices_Start)
{ {
bool showVertexWarning=false; bool showVertexWarning=false;
s32 triangle_brush_id; // Note: Irrlicht can't have different brushes for each triangle (I'm using a workaround) s32 triangle_brush_id; // Note: Irrlicht can't have different brushes for each triangle (using a workaround)
B3DFile->read(&triangle_brush_id, sizeof(triangle_brush_id));
file->read(&triangle_brush_id, sizeof(triangle_brush_id)); #ifdef __BIG_ENDIAN__
#ifdef __BIG_ENDIAN__
triangle_brush_id = os::Byteswap::byteswap(triangle_brush_id); triangle_brush_id = os::Byteswap::byteswap(triangle_brush_id);
#endif #endif
SB3dMaterial *B3dMaterial; SB3dMaterial *B3dMaterial;
...@@ -490,22 +434,19 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M ...@@ -490,22 +434,19 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M
if (B3dMaterial) if (B3dMaterial)
MeshBuffer->Material = (*B3dMaterial->Material); MeshBuffer->Material = (*B3dMaterial->Material);
s32 MemoryNeeded = B3dStack.getLast().length / sizeof(s32); const s32 MemoryNeeded = B3dStack.getLast().length / sizeof(s32);
MeshBuffer->Indices.reallocate(MemoryNeeded + MeshBuffer->Indices.size() + 1); MeshBuffer->Indices.reallocate(MemoryNeeded + MeshBuffer->Indices.size() + 1);
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > file->getPos()) // this chunk repeats while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats
{ {
s32 vertex_id[3]; s32 vertex_id[3];
file->read(&vertex_id[0], sizeof(s32)); B3DFile->read(vertex_id, 3*sizeof(s32));
file->read(&vertex_id[1], sizeof(s32)); #ifdef __BIG_ENDIAN__
file->read(&vertex_id[2], sizeof(s32));
#ifdef __BIG_ENDIAN__
vertex_id[0] = os::Byteswap::byteswap(vertex_id[0]); vertex_id[0] = os::Byteswap::byteswap(vertex_id[0]);
vertex_id[1] = os::Byteswap::byteswap(vertex_id[1]); vertex_id[1] = os::Byteswap::byteswap(vertex_id[1]);
vertex_id[2] = os::Byteswap::byteswap(vertex_id[2]); vertex_id[2] = os::Byteswap::byteswap(vertex_id[2]);
#endif #endif
//Make Ids global: //Make Ids global:
vertex_id[0] += vertices_Start; vertex_id[0] += vertices_Start;
...@@ -515,7 +456,10 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M ...@@ -515,7 +456,10 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M
for(s32 i=0; i<3; ++i) for(s32 i=0; i<3; ++i)
{ {
if ((u32)vertex_id[i] >= AnimatedVertices_VertexID.size()) if ((u32)vertex_id[i] >= AnimatedVertices_VertexID.size())
{
os::Printer::log("Illegal vertex index found", B3DFile->getFileName(), ELL_ERROR);
return false; return false;
}
if (AnimatedVertices_VertexID[ vertex_id[i] ] != -1) if (AnimatedVertices_VertexID[ vertex_id[i] ] != -1)
{ {
...@@ -528,7 +472,6 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M ...@@ -528,7 +472,6 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M
} }
if (AnimatedVertices_VertexID[ vertex_id[i] ] == -1) //If this vertex is not in the meshbuffer if (AnimatedVertices_VertexID[ vertex_id[i] ] == -1) //If this vertex is not in the meshbuffer
{ {
//Check for lightmapping: //Check for lightmapping:
if (BaseVertices[ vertex_id[i] ].TCoords2 != core::vector2df(0.f,0.f)) if (BaseVertices[ vertex_id[i] ].TCoords2 != core::vector2df(0.f,0.f))
MeshBuffer->MoveTo_2TCoords(); //Will only affect the meshbuffer the first time this is called MeshBuffer->MoveTo_2TCoords(); //Will only affect the meshbuffer the first time this is called
...@@ -548,10 +491,9 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M ...@@ -548,10 +491,9 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M
// Apply Material/Colour/etc... // Apply Material/Colour/etc...
video::S3DVertex *Vertex=MeshBuffer->getVertex(MeshBuffer->getVertexCount()-1); video::S3DVertex *Vertex=MeshBuffer->getVertex(MeshBuffer->getVertexCount()-1);
if (Vertex->Color.getAlpha() == 255) //Note: Irrlicht docs state that 0 is opaque, are they wrong? if (Vertex->Color.getAlpha() == 255)
Vertex->Color.setAlpha( (s32)(B3dMaterial->alpha * 255.0f) ); Vertex->Color.setAlpha( (s32)(B3dMaterial->alpha * 255.0f) );
// Use texture's scale // Use texture's scale
if (B3dMaterial->Textures[0]) if (B3dMaterial->Textures[0])
{ {
...@@ -565,7 +507,6 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M ...@@ -565,7 +507,6 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M
Vertex->TCoords2.Y *=B3dMaterial->Textures[1]->Yscale; Vertex->TCoords2.Y *=B3dMaterial->Textures[1]->Yscale;
} }
*/ */
} }
} }
} }
...@@ -577,8 +518,6 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M ...@@ -577,8 +518,6 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 M
B3dStack.erase(B3dStack.size()-1); B3dStack.erase(B3dStack.size()-1);
if (showVertexWarning) if (showVertexWarning)
os::Printer::log("B3dMeshLoader: Warning, different meshbuffers linking to the same vertex, this will cause problems with animated meshes"); os::Printer::log("B3dMeshLoader: Warning, different meshbuffers linking to the same vertex, this will cause problems with animated meshes");
...@@ -590,30 +529,29 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *InJoint) ...@@ -590,30 +529,29 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *InJoint)
{ {
if (B3dStack.getLast().length > 8) if (B3dStack.getLast().length > 8)
{ {
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > file->getPos()) // this chunk repeats while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats
{ {
CSkinnedMesh::SWeight *Weight=AnimatedMesh->createWeight(InJoint); CSkinnedMesh::SWeight *weight=AnimatedMesh->createWeight(InJoint);
u32 GlobalVertexID;
file->read(&GlobalVertexID, sizeof(GlobalVertexID)); u32 globalVertexID;
file->read(&Weight->strength, sizeof(Weight->strength));
#ifdef __BIG_ENDIAN__ B3DFile->read(&globalVertexID, sizeof(globalVertexID));
GlobalVertexID = os::Byteswap::byteswap(GlobalVertexID); B3DFile->read(&weight->strength, sizeof(weight->strength));
Weight->strength = os::Byteswap::byteswap(Weight->strength); #ifdef __BIG_ENDIAN__
#endif globalVertexID = os::Byteswap::byteswap(globalVertexID);
weight->strength = os::Byteswap::byteswap(weight->strength);
#endif
if (AnimatedVertices_VertexID[GlobalVertexID]==-1) if (AnimatedVertices_VertexID[globalVertexID]==-1)
{ {
os::Printer::log("B3dMeshLoader: Weight has bad vertex id (no link to meshbuffer index found)"); os::Printer::log("B3dMeshLoader: Weight has bad vertex id (no link to meshbuffer index found)");
Weight->vertex_id = Weight->buffer_id = 0; weight->vertex_id = weight->buffer_id = 0;
} }
else else
{ {
//Find the MeshBuffer and Vertex index from the Global Vertex ID: //Find the MeshBuffer and Vertex index from the Global Vertex ID:
Weight->vertex_id = AnimatedVertices_VertexID[GlobalVertexID]; weight->vertex_id = AnimatedVertices_VertexID[globalVertexID];
Weight->buffer_id = AnimatedVertices_BufferID[GlobalVertexID]; weight->buffer_id = AnimatedVertices_BufferID[globalVertexID];
} }
} }
} }
...@@ -626,56 +564,44 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *InJoint) ...@@ -626,56 +564,44 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *InJoint)
bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *InJoint) bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *InJoint)
{ {
s32 flags; s32 flags;
file->read(&flags, sizeof(flags)); B3DFile->read(&flags, sizeof(flags));
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
flags = os::Byteswap::byteswap(flags); flags = os::Byteswap::byteswap(flags);
#endif #endif
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > file->getPos()) //this chunk repeats while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
{ {
s32 frame; s32 frame;
f32 positionData[3]; B3DFile->read(&frame, sizeof(frame));
f32 scaleData[3];
f32 rotationData[4];
file->read(&frame, sizeof(frame));
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
frame = os::Byteswap::byteswap(frame); frame = os::Byteswap::byteswap(frame);
#endif #endif
if (flags&1) // Add key frames
readFloats(positionData, 3);
if (flags&2)
readFloats(scaleData, 3);
if (flags&4)
readFloats(rotationData, 4);
core::vector3df position = core::vector3df(positionData[0], positionData[1], positionData[2]);
core::vector3df scale = core::vector3df(scaleData[0], scaleData[1], scaleData[2]);
core::quaternion rotation = core::quaternion(rotationData[1], rotationData[2], rotationData[3], rotationData[0]); // meant to be in this order
// Add key frame
if (flags & 1) if (flags & 1)
{ {
f32 positionData[3];
readFloats(positionData, 3);
CSkinnedMesh::SPositionKey *Key=AnimatedMesh->createPositionKey(InJoint); CSkinnedMesh::SPositionKey *Key=AnimatedMesh->createPositionKey(InJoint);
Key->frame = (f32)frame; Key->frame = (f32)frame;
Key->position = position; Key->position.set(positionData[0], positionData[1], positionData[2]);
} }
if (flags & 2) if (flags & 2)
{ {
f32 scaleData[3];
readFloats(scaleData, 3);
CSkinnedMesh::SScaleKey *Key=AnimatedMesh->createScaleKey(InJoint); CSkinnedMesh::SScaleKey *Key=AnimatedMesh->createScaleKey(InJoint);
Key->frame = (f32)frame; Key->frame = (f32)frame;
Key->scale=scale; Key->scale.set(scaleData[0], scaleData[1], scaleData[2]);
} }
if (flags & 4) if (flags & 4)
{ {
f32 rotationData[4];
readFloats(rotationData, 4);
CSkinnedMesh::SRotationKey *Key=AnimatedMesh->createRotationKey(InJoint); CSkinnedMesh::SRotationKey *Key=AnimatedMesh->createRotationKey(InJoint);
Key->frame = (f32)frame; Key->frame = (f32)frame;
Key->rotation = rotation; Key->rotation.set(rotationData[1], rotationData[2], rotationData[3], rotationData[0]); // meant to be in this order
} }
} }
...@@ -686,50 +612,50 @@ bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *InJoint) ...@@ -686,50 +612,50 @@ bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *InJoint)
bool CB3DMeshFileLoader::readChunkANIM() bool CB3DMeshFileLoader::readChunkANIM()
{ {
s32 AnimFlags; //not stored\used s32 animFlags; //not stored\used
s32 AnimFrames;//not stored\used s32 animFrames;//not stored\used
f32 AnimFPS; //not stored\used f32 animFPS; //not stored\used
file->read(&AnimFlags, sizeof(s32)); B3DFile->read(&animFlags, sizeof(s32));
file->read(&AnimFrames, sizeof(s32)); B3DFile->read(&animFrames, sizeof(s32));
readFloats(&AnimFPS, 1); readFloats(&animFPS, 1);
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
AnimFlags = os::Byteswap::byteswap(AnimFlags); animFlags = os::Byteswap::byteswap(animFlags);
AnimFrames = os::Byteswap::byteswap(AnimFrames); animFrames = os::Byteswap::byteswap(animFrames);
#endif #endif
B3dStack.erase(B3dStack.size()-1); B3dStack.erase(B3dStack.size()-1);
return true; return true;
} }
bool CB3DMeshFileLoader::readChunkTEXS() bool CB3DMeshFileLoader::readChunkTEXS()
{ {
bool Previous32BitTextureFlag = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_ALWAYS_32_BIT); bool Previous32BitTextureFlag = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_ALWAYS_32_BIT);
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > file->getPos()) //this chunk repeats while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
{ {
core::stringc TextureName=readString(); core::stringc TextureName=readString();
TextureName=stripPathFromString(file->getFileName(),true) + stripPathFromString(TextureName,false); TextureName=stripPathFromString(B3DFile->getFileName(),true) + stripPathFromString(TextureName,false);
SB3dTexture B3dTexture; SB3dTexture B3dTexture;
B3dTexture.Texture=SceneManager->getVideoDriver()->getTexture ( TextureName.c_str() ); B3dTexture.Texture=SceneManager->getVideoDriver()->getTexture ( TextureName.c_str() );
file->read(&B3dTexture.Flags, sizeof(s32)); B3DFile->read(&B3dTexture.Flags, sizeof(s32));
file->read(&B3dTexture.Blend, sizeof(s32)); B3DFile->read(&B3dTexture.Blend, sizeof(s32));
#ifdef __BIG_ENDIAN__
B3dTexture.Flags = os::Byteswap::byteswap(B3dTexture.Flags);
B3dTexture.Blend = os::Byteswap::byteswap(B3dTexture.Blend);
#endif
readFloats(&B3dTexture.Xpos, 1); readFloats(&B3dTexture.Xpos, 1);
readFloats(&B3dTexture.Ypos, 1); readFloats(&B3dTexture.Ypos, 1);
readFloats(&B3dTexture.Xscale, 1); readFloats(&B3dTexture.Xscale, 1);
readFloats(&B3dTexture.Yscale, 1); readFloats(&B3dTexture.Yscale, 1);
readFloats(&B3dTexture.Angle, 1); readFloats(&B3dTexture.Angle, 1);
#ifdef __BIG_ENDIAN__
B3dTexture.Flags = os::Byteswap::byteswap(B3dTexture.Flags);
B3dTexture.Blend = os::Byteswap::byteswap(B3dTexture.Blend);
#endif
Textures.push_back(B3dTexture); Textures.push_back(B3dTexture);
} }
...@@ -743,35 +669,30 @@ bool CB3DMeshFileLoader::readChunkTEXS() ...@@ -743,35 +669,30 @@ bool CB3DMeshFileLoader::readChunkTEXS()
bool CB3DMeshFileLoader::readChunkBRUS() bool CB3DMeshFileLoader::readChunkBRUS()
{ {
s32 n_texs; u32 n_texs;
B3DFile->read(&n_texs, sizeof(u32));
file->read(&n_texs, sizeof(s32)); #ifdef __BIG_ENDIAN__
#ifdef __BIG_ENDIAN__
n_texs = os::Byteswap::byteswap(n_texs); n_texs = os::Byteswap::byteswap(n_texs);
#endif #endif
if (n_texs>8) if (n_texs>video::MATERIAL_MAX_TEXTURES)
{ {
os::Printer::log("n_texs too big", file->getFileName(), ELL_ERROR); os::Printer::log("Too many textures used in one material", B3DFile->getFileName(), ELL_WARNING);
return false;
} }
// number of texture ids read for Irrlicht
const u32 num_textures = core::min_(n_texs, video::MATERIAL_MAX_TEXTURES);
// number of bytes to skip (for ignored texture ids)
const u32 n_texs_offset = (num_textures<n_texs)?(n_texs-num_textures)*sizeof(s32):0;
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > file->getPos()) //this chunk repeats while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
{ {
// This is what blitz basic calls a brush, like a Irrlicht Material // This is what blitz basic calls a brush, like a Irrlicht Material
readString(); //core::stringc MaterialName, not used but we still need the read it readString(); //MaterialName not used, but still need to read it
SB3dMaterial B3dMaterial; SB3dMaterial B3dMaterial;
B3dMaterial.Material = new video::SMaterial(); B3dMaterial.Material = new video::SMaterial();
B3dMaterial.Textures[0]=0;
B3dMaterial.Textures[1]=0;
s32 texture_id[8];
texture_id[0]=-1;
texture_id[1]=-1;
readFloats(&B3dMaterial.red, 1); readFloats(&B3dMaterial.red, 1);
readFloats(&B3dMaterial.green, 1); readFloats(&B3dMaterial.green, 1);
...@@ -779,29 +700,34 @@ bool CB3DMeshFileLoader::readChunkBRUS() ...@@ -779,29 +700,34 @@ bool CB3DMeshFileLoader::readChunkBRUS()
readFloats(&B3dMaterial.alpha, 1); readFloats(&B3dMaterial.alpha, 1);
readFloats(&B3dMaterial.shininess, 1); readFloats(&B3dMaterial.shininess, 1);
file->read(&B3dMaterial.blend, sizeof(B3dMaterial.blend)); B3DFile->read(&B3dMaterial.blend, sizeof(B3dMaterial.blend));
file->read(&B3dMaterial.fx, sizeof(B3dMaterial.fx)); B3DFile->read(&B3dMaterial.fx, sizeof(B3dMaterial.fx));
#ifdef __BIG_ENDIAN__
file->read(texture_id, n_texs*sizeof(s32));
#ifdef __BIG_ENDIAN__
B3dMaterial.blend = os::Byteswap::byteswap(B3dMaterial.blend); B3dMaterial.blend = os::Byteswap::byteswap(B3dMaterial.blend);
B3dMaterial.fx = os::Byteswap::byteswap(B3dMaterial.fx); B3dMaterial.fx = os::Byteswap::byteswap(B3dMaterial.fx);
#endif
for (s32 n=0; n < n_texs; ++n)
texture_id[n] = os::Byteswap::byteswap(texture_id[n]); for (u32 i=0; i<num_textures; ++i)
#endif {
s32 texture_id=-1;
//------ Get pointers to the texture, based on the IDs ------ B3DFile->read(&texture_id, sizeof(s32));
if (texture_id[0] != -1) #ifdef __BIG_ENDIAN__
B3dMaterial.Textures[0]=&Textures[texture_id[0]]; texture_id = os::Byteswap::byteswap(texture_id);
if (texture_id[1] != -1) #endif
B3dMaterial.Textures[1]=&Textures[texture_id[1]]; //--- Get pointers to the texture, based on the IDs ---
if (texture_id != -1)
B3dMaterial.Textures[i]=&Textures[texture_id];
else
B3dMaterial.Textures[i]=0;
}
// skip other texture ids
if (n_texs_offset)
B3DFile->seek(n_texs_offset, true);
//Fixes problems when the lightmap is on the first texture: //Fixes problems when the lightmap is on the first texture:
if (texture_id[0] != -1) if (B3dMaterial.Textures[0] != 0)
{ {
if (Textures[texture_id[0]].Flags & 65536) // 65536 = secondary UV if (B3dMaterial.Textures[0]->Flags & 65536) // 65536 = secondary UV
{ {
SB3dTexture *TmpTexture; SB3dTexture *TmpTexture;
TmpTexture = B3dMaterial.Textures[1]; TmpTexture = B3dMaterial.Textures[1];
...@@ -810,11 +736,6 @@ bool CB3DMeshFileLoader::readChunkBRUS() ...@@ -810,11 +736,6 @@ bool CB3DMeshFileLoader::readChunkBRUS()
} }
} }
if (B3dMaterial.Textures[0] != 0)
B3dMaterial.Material->setTexture(0, B3dMaterial.Textures[0]->Texture);
if (B3dMaterial.Textures[1] != 0)
B3dMaterial.Material->setTexture(1, B3dMaterial.Textures[1]->Texture);
//If the first texture is empty: //If the first texture is empty:
if (B3dMaterial.Textures[1] != 0 && B3dMaterial.Textures[0] == 0) if (B3dMaterial.Textures[1] != 0 && B3dMaterial.Textures[0] == 0)
{ {
...@@ -822,6 +743,11 @@ bool CB3DMeshFileLoader::readChunkBRUS() ...@@ -822,6 +743,11 @@ bool CB3DMeshFileLoader::readChunkBRUS()
B3dMaterial.Textures[1] = 0; B3dMaterial.Textures[1] = 0;
} }
if (B3dMaterial.Textures[0] != 0)
B3dMaterial.Material->setTexture(0, B3dMaterial.Textures[0]->Texture);
if (B3dMaterial.Textures[1] != 0)
B3dMaterial.Material->setTexture(1, B3dMaterial.Textures[1]->Texture);
//------ Convert blitz flags/blend to irrlicht ------- //------ Convert blitz flags/blend to irrlicht -------
//Two textures: //Two textures:
...@@ -890,21 +816,23 @@ bool CB3DMeshFileLoader::readChunkBRUS() ...@@ -890,21 +816,23 @@ bool CB3DMeshFileLoader::readChunkBRUS()
return true; return true;
} }
core::stringc CB3DMeshFileLoader::readString() core::stringc CB3DMeshFileLoader::readString()
{ {
core::stringc newstring; core::stringc newstring;
while (file->getPos() <= file->getSize()) while (B3DFile->getPos() <= B3DFile->getSize())
{ {
c8 character; c8 character;
file->read(&character, sizeof(character)); B3DFile->read(&character, sizeof(character));
if (character==0) if (character==0)
return newstring; break;
newstring.append(character); newstring.append(character);
} }
return newstring; return newstring;
} }
core::stringc CB3DMeshFileLoader::stripPathFromString(core::stringc string, bool returnPath) const
core::stringc CB3DMeshFileLoader::stripPathFromString(const core::stringc& string, bool returnPath) const
{ {
s32 slashIndex=string.findLast('/'); // forward slash s32 slashIndex=string.findLast('/'); // forward slash
s32 backSlash=string.findLast('\\'); // back slash s32 backSlash=string.findLast('\\'); // back slash
...@@ -927,7 +855,7 @@ core::stringc CB3DMeshFileLoader::stripPathFromString(core::stringc string, bool ...@@ -927,7 +855,7 @@ core::stringc CB3DMeshFileLoader::stripPathFromString(core::stringc string, bool
void CB3DMeshFileLoader::readFloats(f32* vec, u32 count) void CB3DMeshFileLoader::readFloats(f32* vec, u32 count)
{ {
file->read(vec, count*sizeof(f32)); B3DFile->read(vec, count*sizeof(f32));
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
for (u32 n=0; n<count; ++n) for (u32 n=0; n<count; ++n)
vec[n] = os::Byteswap::byteswap(vec[n]); vec[n] = os::Byteswap::byteswap(vec[n]);
......
...@@ -47,9 +47,18 @@ private: ...@@ -47,9 +47,18 @@ private:
struct SB3dChunk struct SB3dChunk
{ {
SB3dChunk(const SB3dChunkHeader& header, long sp)
: length(header.size+8), startposition(sp)
{
name[0]=header.name[0];
name[1]=header.name[1];
name[2]=header.name[2];
name[3]=header.name[3];
}
c8 name[4]; c8 name[4];
s32 length; s32 length;
s32 startposition; long startposition;
}; };
struct SB3dTexture struct SB3dTexture
...@@ -70,7 +79,7 @@ private: ...@@ -70,7 +79,7 @@ private:
f32 red, green, blue, alpha; f32 red, green, blue, alpha;
f32 shininess; f32 shininess;
s32 blend,fx; s32 blend,fx;
SB3dTexture *Textures[2]; SB3dTexture *Textures[video::MATERIAL_MAX_TEXTURES];
}; };
bool load(); bool load();
...@@ -85,7 +94,7 @@ private: ...@@ -85,7 +94,7 @@ private:
bool readChunkBRUS(); bool readChunkBRUS();
core::stringc readString(); core::stringc readString();
core::stringc stripPathFromString(core::stringc string, bool returnPath=false) const; core::stringc stripPathFromString(const core::stringc& string, bool returnPath=false) const;
void readFloats(f32* vec, u32 count); void readFloats(f32* vec, u32 count);
core::array<SB3dChunk> B3dStack; core::array<SB3dChunk> B3dStack;
...@@ -107,7 +116,7 @@ private: ...@@ -107,7 +116,7 @@ private:
// //
ISceneManager* SceneManager; ISceneManager* SceneManager;
CSkinnedMesh* AnimatedMesh; CSkinnedMesh* AnimatedMesh;
io::IReadFile* file; io::IReadFile* B3DFile;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment