2008-05-22 04:51:37 -07:00
|
|
|
// Copyright (C) 2006-2008 Luke Hoschke
|
|
|
|
// This file is part of the "Irrlicht Engine".
|
|
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
// B3D Mesh loader
|
2008-05-22 04:51:37 -07:00
|
|
|
// File format designed by Mark Sibly for the Blitz3D engine and has been
|
|
|
|
// declared public domain
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
#include "IrrCompileConfig.h"
|
|
|
|
#ifdef _IRR_COMPILE_WITH_B3D_LOADER_
|
|
|
|
|
|
|
|
#include "CB3DMeshFileLoader.h"
|
|
|
|
|
|
|
|
#include "IVideoDriver.h"
|
|
|
|
#include "os.h"
|
|
|
|
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _DEBUG
|
|
|
|
#define _B3D_READER_DEBUG
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
namespace irr
|
|
|
|
{
|
|
|
|
namespace scene
|
|
|
|
{
|
|
|
|
|
|
|
|
//! Constructor
|
|
|
|
CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr)
|
2008-01-17 16:54:01 -08:00
|
|
|
: SceneManager(smgr), AnimatedMesh(0), B3DFile(0), NormalsInFile(false),
|
|
|
|
ShowWarning(true)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
|
|
|
setDebugName("CB3DMeshFileLoader");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2007-09-05 06:10:36 -07:00
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
//! returns true if the file maybe is able to be loaded by this class
|
|
|
|
//! based on the file extension (e.g. ".bsp")
|
2007-09-16 16:41:55 -07:00
|
|
|
bool CB3DMeshFileLoader::isALoadableFileExtension(const c8* fileName) const
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
return strstr(fileName, ".b3d") != 0;
|
|
|
|
}
|
|
|
|
|
2007-09-05 06:10:36 -07:00
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
//! creates/loads an animated mesh from the file.
|
|
|
|
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
|
|
|
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
2007-09-06 23:11:47 -07:00
|
|
|
//! See IReferenceCounted::drop() for more information.
|
2007-09-19 07:08:28 -07:00
|
|
|
IAnimatedMesh* CB3DMeshFileLoader::createMesh(io::IReadFile* f)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
if (!f)
|
|
|
|
return 0;
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile = f;
|
2007-09-04 11:51:42 -07:00
|
|
|
AnimatedMesh = new scene::CSkinnedMesh();
|
2008-01-17 16:54:01 -08:00
|
|
|
ShowWarning = true; // If true a warning is issued if too many textures are used
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
Buffers = &AnimatedMesh->getMeshBuffers();
|
|
|
|
AllJoints = &AnimatedMesh->getAllJoints();
|
|
|
|
|
|
|
|
if ( load() )
|
|
|
|
{
|
|
|
|
AnimatedMesh->finalize();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AnimatedMesh->drop();
|
|
|
|
AnimatedMesh = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AnimatedMesh;
|
|
|
|
}
|
|
|
|
|
2007-09-05 06:10:36 -07:00
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
bool CB3DMeshFileLoader::load()
|
|
|
|
{
|
|
|
|
B3dStack.clear();
|
|
|
|
|
|
|
|
NormalsInFile=false;
|
|
|
|
|
|
|
|
//------ Get header ------
|
|
|
|
|
|
|
|
SB3dChunkHeader header;
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&header, sizeof(header));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
header.size = os::Byteswap::byteswap(header.size);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
if ( strncmp( header.name, "BB3D", 4 ) != 0 )
|
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
os::Printer::log("File is not a b3d file. Loading failed (No header found)", B3DFile->getFileName(), ELL_ERROR);
|
2007-09-04 11:51:42 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add main chunk...
|
2007-12-30 17:28:38 -08:00
|
|
|
B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
// Get file version, but ignore it, as it's not important with b3d files...
|
2007-12-30 17:28:38 -08:00
|
|
|
s32 fileVersion;
|
|
|
|
B3DFile->read(&fileVersion, sizeof(fileVersion));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
fileVersion = os::Byteswap::byteswap(fileVersion);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
//------ Read main chunk ------
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
while ( (B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos() )
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&header, sizeof(header));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
header.size = os::Byteswap::byteswap(header.size);
|
|
|
|
#endif
|
|
|
|
B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
if ( strncmp( B3dStack.getLast().name, "TEXS", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
if (!readChunkTEXS())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ( strncmp( B3dStack.getLast().name, "BRUS", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
if (!readChunkBRUS())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
if (!readChunkNODE((CSkinnedMesh::SJoint*)0) )
|
|
|
|
return false;
|
|
|
|
}
|
2007-12-30 17:28:38 -08:00
|
|
|
else
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
os::Printer::log("Unknown chunk found in mesh base - skipping");
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);
|
2007-09-04 11:51:42 -07:00
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.clear();
|
|
|
|
|
|
|
|
BaseVertices.clear();
|
|
|
|
AnimatedVertices_VertexID.clear();
|
|
|
|
AnimatedVertices_BufferID.clear();
|
|
|
|
|
|
|
|
Materials.clear();
|
|
|
|
Textures.clear();
|
|
|
|
|
|
|
|
Buffers=0;
|
|
|
|
AllJoints=0;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CB3DMeshFileLoader::readChunkNODE(CSkinnedMesh::SJoint *InJoint)
|
|
|
|
{
|
2007-12-03 02:07:40 -08:00
|
|
|
const core::stringc JointName = readString();
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkNODE", JointName.c_str());
|
|
|
|
#endif
|
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
f32 position[3], scale[3], rotation[4];
|
|
|
|
|
2007-12-03 02:07:40 -08:00
|
|
|
readFloats(position, 3);
|
|
|
|
readFloats(scale, 3);
|
|
|
|
readFloats(rotation, 4);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
CSkinnedMesh::SJoint *Joint = AnimatedMesh->createJoint(InJoint);
|
|
|
|
|
|
|
|
Joint->Name = JointName;
|
|
|
|
Joint->Animatedposition = core::vector3df(position[0],position[1],position[2]) ;
|
|
|
|
Joint->Animatedscale = core::vector3df(scale[0],scale[1],scale[2]);
|
|
|
|
Joint->Animatedrotation = core::quaternion(rotation[1], rotation[2], rotation[3], rotation[0]);
|
|
|
|
|
|
|
|
//Build LocalMatrix:
|
|
|
|
|
2007-09-19 07:08:28 -07:00
|
|
|
core::matrix4 positionMatrix;
|
|
|
|
positionMatrix.setTranslation( Joint->Animatedposition );
|
|
|
|
core::matrix4 scaleMatrix;
|
|
|
|
scaleMatrix.setScale( Joint->Animatedscale );
|
|
|
|
core::matrix4 rotationMatrix = Joint->Animatedrotation.getMatrix();
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
Joint->LocalMatrix = positionMatrix * rotationMatrix * scaleMatrix;
|
|
|
|
|
|
|
|
if (InJoint)
|
|
|
|
Joint->GlobalMatrix = InJoint->GlobalMatrix * Joint->LocalMatrix;
|
|
|
|
else
|
|
|
|
Joint->GlobalMatrix = Joint->LocalMatrix;
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
while(B3dStack.getLast().startposition + B3dStack.getLast().length > B3DFile->getPos()) // this chunk repeats
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
SB3dChunkHeader header;
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&header, sizeof(header));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
header.size = os::Byteswap::byteswap(header.size);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
if ( strncmp( B3dStack.getLast().name, "NODE", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
if (!readChunkNODE(Joint))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ( strncmp( B3dStack.getLast().name, "MESH", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
if (!readChunkMESH(Joint))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ( strncmp( B3dStack.getLast().name, "BONE", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
if (!readChunkBONE(Joint))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ( strncmp( B3dStack.getLast().name, "KEYS", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
if(!readChunkKEYS(Joint))
|
|
|
|
return false;
|
|
|
|
}
|
2007-12-30 17:28:38 -08:00
|
|
|
else if ( strncmp( B3dStack.getLast().name, "ANIM", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
if (!readChunkANIM())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
os::Printer::log("Unknown chunk found in node chunk - skipping");
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);
|
2007-09-04 11:51:42 -07:00
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *InJoint)
|
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkMESH");
|
|
|
|
#endif
|
|
|
|
|
2007-10-15 05:27:19 -07:00
|
|
|
const s32 vertices_Start=BaseVertices.size(); //B3Ds have Vertex ID's local within the mesh I don't want this
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
s32 brush_id;
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&brush_id, sizeof(brush_id));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
brush_id = os::Byteswap::byteswap(brush_id);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
NormalsInFile=false;
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
SB3dChunkHeader header;
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&header, sizeof(header));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
header.size = os::Byteswap::byteswap(header.size);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3dStack.push_back(SB3dChunk(header, B3DFile->getPos()-8));
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
if ( strncmp( B3dStack.getLast().name, "VRTS", 4 ) == 0 )
|
|
|
|
{
|
2007-12-03 02:07:40 -08:00
|
|
|
if (!readChunkVRTS(InJoint))
|
2007-09-04 11:51:42 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ( strncmp( B3dStack.getLast().name, "TRIS", 4 ) == 0 )
|
|
|
|
{
|
|
|
|
scene::SSkinMeshBuffer *MeshBuffer = AnimatedMesh->createBuffer();
|
|
|
|
|
|
|
|
if (brush_id!=-1)
|
2008-08-10 08:26:45 -07:00
|
|
|
{
|
|
|
|
loadTextures(Materials[brush_id]);
|
2008-07-30 07:13:25 -07:00
|
|
|
MeshBuffer->Material=Materials[brush_id].Material;
|
2008-08-10 08:26:45 -07:00
|
|
|
}
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-03 02:07:40 -08:00
|
|
|
if(readChunkTRIS(MeshBuffer,AnimatedMesh->getMeshBuffers().size()-1, vertices_Start)==false)
|
2007-09-04 11:51:42 -07:00
|
|
|
return false;
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
if (!NormalsInFile)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
s32 i;
|
|
|
|
|
|
|
|
for ( i=0; i<(s32)MeshBuffer->Indices.size(); i+=3)
|
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
core::plane3df p(MeshBuffer->getVertex(MeshBuffer->Indices[i+0])->Pos,
|
|
|
|
MeshBuffer->getVertex(MeshBuffer->Indices[i+1])->Pos,
|
|
|
|
MeshBuffer->getVertex(MeshBuffer->Indices[i+2])->Pos);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
MeshBuffer->getVertex(MeshBuffer->Indices[i+0])->Normal += p.Normal;
|
|
|
|
MeshBuffer->getVertex(MeshBuffer->Indices[i+1])->Normal += p.Normal;
|
|
|
|
MeshBuffer->getVertex(MeshBuffer->Indices[i+2])->Normal += p.Normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i = 0; i<(s32)MeshBuffer->getVertexCount(); ++i )
|
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
MeshBuffer->getVertex(i)->Normal.normalize();
|
2007-10-15 05:27:19 -07:00
|
|
|
BaseVertices[vertices_Start+i].Normal=MeshBuffer->getVertex(i)->Normal;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-30 17:28:38 -08:00
|
|
|
else
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
os::Printer::log("Unknown chunk found in mesh - skipping");
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->seek(B3dStack.getLast().startposition + B3dStack.getLast().length);
|
2007-09-04 11:51:42 -07:00
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
VRTS:
|
|
|
|
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
|
2007-12-30 17:28:38 -08:00
|
|
|
but we only support 3
|
2007-09-04 11:51:42 -07:00
|
|
|
int tex_coord_set_size ;components per set (eg: 2 for simple U/V) max=4
|
|
|
|
{
|
|
|
|
float x,y,z ;always present
|
|
|
|
float nx,ny,nz ;vertex normal: present if (flags&1)
|
|
|
|
float red,green,blue,alpha ;vertex color: present if (flags&2)
|
|
|
|
float tex_coords[tex_coord_sets][tex_coord_set_size] ;tex coords
|
|
|
|
}
|
|
|
|
*/
|
2007-12-03 02:07:40 -08:00
|
|
|
bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *InJoint)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkVRTS");
|
|
|
|
#endif
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
const s32 max_tex_coords = 3;
|
2007-09-04 11:51:42 -07:00
|
|
|
s32 flags, tex_coord_sets, tex_coord_set_size;
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&flags, sizeof(flags));
|
|
|
|
B3DFile->read(&tex_coord_sets, sizeof(tex_coord_sets));
|
|
|
|
B3DFile->read(&tex_coord_set_size, sizeof(tex_coord_set_size));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
flags = os::Byteswap::byteswap(flags);
|
|
|
|
tex_coord_sets = os::Byteswap::byteswap(tex_coord_sets);
|
|
|
|
tex_coord_set_size = os::Byteswap::byteswap(tex_coord_set_size);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
if (tex_coord_sets >= max_tex_coords || tex_coord_set_size >= 4) // Something is wrong
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
os::Printer::log("tex_coord_sets or tex_coord_set_size too big", B3DFile->getFileName(), ELL_ERROR);
|
2007-09-04 11:51:42 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------ Allocate Memory, for speed -----------//
|
|
|
|
|
|
|
|
s32 NumberOfReads = 3;
|
|
|
|
|
2007-09-05 06:10:36 -07:00
|
|
|
if (flags & 1)
|
|
|
|
NumberOfReads += 3;
|
|
|
|
if (flags & 2)
|
|
|
|
NumberOfReads += 4;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-09-05 06:10:36 -07:00
|
|
|
NumberOfReads += tex_coord_sets*tex_coord_set_size;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2008-07-30 07:13:25 -07:00
|
|
|
const s32 memoryNeeded = (B3dStack.getLast().length / sizeof(f32)) / NumberOfReads;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2008-07-30 07:13:25 -07:00
|
|
|
BaseVertices.reallocate(memoryNeeded + BaseVertices.size() + 1);
|
|
|
|
AnimatedVertices_VertexID.reallocate(memoryNeeded + AnimatedVertices_VertexID.size() + 1);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
//--------------------------------------------//
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
while( (B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2007-12-03 02:07:40 -08:00
|
|
|
f32 position[3];
|
|
|
|
f32 normal[3]={0.f, 0.f, 0.f};
|
|
|
|
f32 color[4]={1.0f, 1.0f, 1.0f, 1.0f};
|
2007-12-30 17:28:38 -08:00
|
|
|
f32 tex_coords[max_tex_coords][4];
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-03 02:07:40 -08:00
|
|
|
readFloats(position, 3);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
if (flags & 1)
|
|
|
|
{
|
|
|
|
NormalsInFile = true;
|
2007-12-03 02:07:40 -08:00
|
|
|
readFloats(normal, 3);
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & 2)
|
2007-12-05 01:20:51 -08:00
|
|
|
readFloats(color, 4);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
for (s32 i=0; i<tex_coord_sets; ++i)
|
2007-12-03 02:07:40 -08:00
|
|
|
readFloats(tex_coords[i], tex_coord_set_size);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
f32 tu=0.0f, tv=0.0f;
|
|
|
|
if (tex_coord_sets >= 1 && tex_coord_set_size >= 2)
|
|
|
|
{
|
|
|
|
tu=tex_coords[0][0];
|
|
|
|
tv=tex_coords[0][1];
|
|
|
|
}
|
|
|
|
|
|
|
|
f32 tu2=0.0f, tv2=0.0f;
|
2007-12-30 17:28:38 -08:00
|
|
|
if (tex_coord_sets>1 && tex_coord_set_size>1)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
tu2=tex_coords[1][0];
|
|
|
|
tv2=tex_coords[1][1];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create Vertex...
|
2007-12-03 02:07:40 -08:00
|
|
|
video::S3DVertex2TCoords Vertex(position[0], position[1], position[2],
|
|
|
|
normal[0], normal[1], normal[2],
|
|
|
|
video::SColorf(color[0], color[1], color[2], color[3]).toSColor(),
|
|
|
|
tu, tv, tu2, tv2);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
// Transform the Vertex position by nested node...
|
2007-11-15 00:35:20 -08:00
|
|
|
InJoint->GlobalMatrix.transformVect(Vertex.Pos);
|
|
|
|
InJoint->GlobalMatrix.rotateVect(Vertex.Normal);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
//Add it...
|
|
|
|
BaseVertices.push_back(Vertex);
|
|
|
|
|
|
|
|
AnimatedVertices_VertexID.push_back(-1);
|
|
|
|
AnimatedVertices_BufferID.push_back(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-03 02:07:40 -08:00
|
|
|
bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 vertices_Start)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkTRIS");
|
|
|
|
#endif
|
|
|
|
|
2007-09-08 01:57:43 -07:00
|
|
|
bool showVertexWarning=false;
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
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));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
triangle_brush_id = os::Byteswap::byteswap(triangle_brush_id);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
SB3dMaterial *B3dMaterial;
|
|
|
|
|
|
|
|
if (triangle_brush_id != -1)
|
2008-08-10 08:26:45 -07:00
|
|
|
{
|
|
|
|
loadTextures(Materials[triangle_brush_id]);
|
2007-09-04 11:51:42 -07:00
|
|
|
B3dMaterial = &Materials[triangle_brush_id];
|
2008-08-10 08:26:45 -07:00
|
|
|
MeshBuffer->Material = B3dMaterial->Material;
|
|
|
|
}
|
2007-09-04 11:51:42 -07:00
|
|
|
else
|
|
|
|
B3dMaterial = 0;
|
|
|
|
|
2008-07-30 07:13:25 -07:00
|
|
|
const s32 memoryNeeded = B3dStack.getLast().length / sizeof(s32);
|
|
|
|
MeshBuffer->Indices.reallocate(memoryNeeded + MeshBuffer->Indices.size() + 1);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
s32 vertex_id[3];
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(vertex_id, 3*sizeof(s32));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
vertex_id[0] = os::Byteswap::byteswap(vertex_id[0]);
|
|
|
|
vertex_id[1] = os::Byteswap::byteswap(vertex_id[1]);
|
|
|
|
vertex_id[2] = os::Byteswap::byteswap(vertex_id[2]);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
//Make Ids global:
|
2007-10-15 05:27:19 -07:00
|
|
|
vertex_id[0] += vertices_Start;
|
|
|
|
vertex_id[1] += vertices_Start;
|
|
|
|
vertex_id[2] += vertices_Start;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
for(s32 i=0; i<3; ++i)
|
|
|
|
{
|
2007-09-17 05:16:45 -07:00
|
|
|
if ((u32)vertex_id[i] >= AnimatedVertices_VertexID.size())
|
2007-12-30 17:28:38 -08:00
|
|
|
{
|
|
|
|
os::Printer::log("Illegal vertex index found", B3DFile->getFileName(), ELL_ERROR);
|
2007-09-17 05:16:45 -07:00
|
|
|
return false;
|
2007-12-30 17:28:38 -08:00
|
|
|
}
|
2007-09-17 05:16:45 -07:00
|
|
|
|
2007-09-08 01:57:43 -07:00
|
|
|
if (AnimatedVertices_VertexID[ vertex_id[i] ] != -1)
|
|
|
|
{
|
|
|
|
if ( AnimatedVertices_BufferID[ vertex_id[i] ] != (s32)MeshBufferID ) //If this vertex is linked in a different meshbuffer
|
|
|
|
{
|
|
|
|
AnimatedVertices_VertexID[ vertex_id[i] ] = -1;
|
|
|
|
AnimatedVertices_BufferID[ vertex_id[i] ] = -1;
|
|
|
|
showVertexWarning=true;
|
|
|
|
}
|
|
|
|
}
|
2007-09-04 11:51:42 -07:00
|
|
|
if (AnimatedVertices_VertexID[ vertex_id[i] ] == -1) //If this vertex is not in the meshbuffer
|
|
|
|
{
|
|
|
|
//Check for lightmapping:
|
2007-12-03 02:07:40 -08:00
|
|
|
if (BaseVertices[ vertex_id[i] ].TCoords2 != core::vector2df(0.f,0.f))
|
2007-09-04 11:51:42 -07:00
|
|
|
MeshBuffer->MoveTo_2TCoords(); //Will only affect the meshbuffer the first time this is called
|
|
|
|
|
|
|
|
//Add the vertex to the meshbuffer:
|
|
|
|
if (MeshBuffer->VertexType == video::EVT_STANDARD)
|
2007-10-15 05:27:19 -07:00
|
|
|
MeshBuffer->Vertices_Standard.push_back( BaseVertices[ vertex_id[i] ] );
|
2007-09-04 11:51:42 -07:00
|
|
|
else
|
2007-10-15 05:27:19 -07:00
|
|
|
MeshBuffer->Vertices_2TCoords.push_back(BaseVertices[ vertex_id[i] ] );
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
//create vertex id to meshbuffer index link:
|
|
|
|
AnimatedVertices_VertexID[ vertex_id[i] ] = MeshBuffer->getVertexCount()-1;
|
|
|
|
AnimatedVertices_BufferID[ vertex_id[i] ] = MeshBufferID;
|
|
|
|
|
|
|
|
if (B3dMaterial)
|
|
|
|
{
|
|
|
|
// Apply Material/Colour/etc...
|
2007-09-19 07:08:28 -07:00
|
|
|
video::S3DVertex *Vertex=MeshBuffer->getVertex(MeshBuffer->getVertexCount()-1);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
if (Vertex->Color.getAlpha() == 255)
|
2007-09-04 11:51:42 -07:00
|
|
|
Vertex->Color.setAlpha( (s32)(B3dMaterial->alpha * 255.0f) );
|
|
|
|
|
|
|
|
// Use texture's scale
|
|
|
|
if (B3dMaterial->Textures[0])
|
|
|
|
{
|
2007-12-03 02:07:40 -08:00
|
|
|
Vertex->TCoords.X *= B3dMaterial->Textures[0]->Xscale;
|
|
|
|
Vertex->TCoords.Y *= B3dMaterial->Textures[0]->Yscale;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
if (B3dMaterial->Textures[1])
|
|
|
|
{
|
|
|
|
Vertex->TCoords2.X *=B3dMaterial->Textures[1]->Xscale;
|
|
|
|
Vertex->TCoords2.Y *=B3dMaterial->Textures[1]->Yscale;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MeshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[0] ] );
|
|
|
|
MeshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[1] ] );
|
|
|
|
MeshBuffer->Indices.push_back( AnimatedVertices_VertexID[ vertex_id[2] ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
|
2007-09-08 01:57:43 -07:00
|
|
|
if (showVertexWarning)
|
|
|
|
os::Printer::log("B3dMeshLoader: Warning, different meshbuffers linking to the same vertex, this will cause problems with animated meshes");
|
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *InJoint)
|
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkBONE");
|
|
|
|
#endif
|
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
if (B3dStack.getLast().length > 8)
|
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
CSkinnedMesh::SWeight *weight=AnimatedMesh->createWeight(InJoint);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
u32 globalVertexID;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&globalVertexID, sizeof(globalVertexID));
|
|
|
|
B3DFile->read(&weight->strength, sizeof(weight->strength));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
globalVertexID = os::Byteswap::byteswap(globalVertexID);
|
|
|
|
weight->strength = os::Byteswap::byteswap(weight->strength);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
if (AnimatedVertices_VertexID[globalVertexID]==-1)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
os::Printer::log("B3dMeshLoader: Weight has bad vertex id (no link to meshbuffer index found)");
|
2007-12-30 17:28:38 -08:00
|
|
|
weight->vertex_id = weight->buffer_id = 0;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//Find the MeshBuffer and Vertex index from the Global Vertex ID:
|
2007-12-30 17:28:38 -08:00
|
|
|
weight->vertex_id = AnimatedVertices_VertexID[globalVertexID];
|
|
|
|
weight->buffer_id = AnimatedVertices_BufferID[globalVertexID];
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *InJoint)
|
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkKEYS");
|
|
|
|
#endif
|
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
s32 flags;
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&flags, sizeof(flags));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
flags = os::Byteswap::byteswap(flags);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
s32 frame;
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&frame, sizeof(frame));
|
2007-12-03 02:07:40 -08:00
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
frame = os::Byteswap::byteswap(frame);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
// Add key frames
|
2008-07-30 07:13:25 -07:00
|
|
|
f32 data[4];
|
2007-09-04 11:51:42 -07:00
|
|
|
if (flags & 1)
|
|
|
|
{
|
2008-07-30 07:13:25 -07:00
|
|
|
readFloats(data, 3);
|
2007-09-04 11:51:42 -07:00
|
|
|
CSkinnedMesh::SPositionKey *Key=AnimatedMesh->createPositionKey(InJoint);
|
|
|
|
Key->frame = (f32)frame;
|
2008-07-30 07:13:25 -07:00
|
|
|
Key->position.set(data[0], data[1], data[2]);
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
if (flags & 2)
|
|
|
|
{
|
2008-07-30 07:13:25 -07:00
|
|
|
readFloats(data, 3);
|
2007-09-04 11:51:42 -07:00
|
|
|
CSkinnedMesh::SScaleKey *Key=AnimatedMesh->createScaleKey(InJoint);
|
|
|
|
Key->frame = (f32)frame;
|
2008-07-30 07:13:25 -07:00
|
|
|
Key->scale.set(data[0], data[1], data[2]);
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
if (flags & 4)
|
|
|
|
{
|
2008-07-30 07:13:25 -07:00
|
|
|
readFloats(data, 4);
|
2007-09-04 11:51:42 -07:00
|
|
|
CSkinnedMesh::SRotationKey *Key=AnimatedMesh->createRotationKey(InJoint);
|
|
|
|
Key->frame = (f32)frame;
|
2008-07-30 07:13:25 -07:00
|
|
|
// meant to be in this order since b3d stores W first
|
|
|
|
Key->rotation.set(data[1], data[2], data[3], data[0]);
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-03 02:07:40 -08:00
|
|
|
bool CB3DMeshFileLoader::readChunkANIM()
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkANIM");
|
|
|
|
#endif
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
s32 animFlags; //not stored\used
|
|
|
|
s32 animFrames;//not stored\used
|
|
|
|
f32 animFPS; //not stored\used
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&animFlags, sizeof(s32));
|
|
|
|
B3DFile->read(&animFrames, sizeof(s32));
|
|
|
|
readFloats(&animFPS, 1);
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
#ifdef __BIG_ENDIAN__
|
2007-12-30 17:28:38 -08:00
|
|
|
animFlags = os::Byteswap::byteswap(animFlags);
|
|
|
|
animFrames = os::Byteswap::byteswap(animFrames);
|
2007-09-04 11:51:42 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
bool CB3DMeshFileLoader::readChunkTEXS()
|
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkTEXS");
|
|
|
|
#endif
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2008-08-10 08:26:45 -07:00
|
|
|
Textures.push_back(SB3dTexture());
|
|
|
|
SB3dTexture& B3dTexture = Textures.getLast();
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2008-08-10 08:26:45 -07:00
|
|
|
B3dTexture.TextureName=readString();
|
|
|
|
B3dTexture.TextureName=stripPathFromString(B3DFile->getFileName(),true) + stripPathFromString(B3dTexture.TextureName,false);
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read Texture", B3dTexture.TextureName.c_str());
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&B3dTexture.Flags, 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
|
2007-09-04 11:51:42 -07:00
|
|
|
readFloats(&B3dTexture.Xpos, 1);
|
|
|
|
readFloats(&B3dTexture.Ypos, 1);
|
|
|
|
readFloats(&B3dTexture.Xscale, 1);
|
|
|
|
readFloats(&B3dTexture.Yscale, 1);
|
|
|
|
readFloats(&B3dTexture.Angle, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-09-05 06:10:36 -07:00
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
bool CB3DMeshFileLoader::readChunkBRUS()
|
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read ChunkBRUS");
|
|
|
|
#endif
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
u32 n_texs;
|
|
|
|
B3DFile->read(&n_texs, sizeof(u32));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
n_texs = os::Byteswap::byteswap(n_texs);
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
// 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)
|
2008-01-06 07:57:23 -08:00
|
|
|
const u32 n_texs_offset = (num_textures<n_texs)?(n_texs-num_textures):0;
|
2007-12-03 02:07:40 -08:00
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
// This is what blitz basic calls a brush, like a Irrlicht Material
|
|
|
|
|
2008-10-01 06:11:50 -07:00
|
|
|
const core::stringc name = readString();
|
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("read Material", name.c_str());
|
|
|
|
#endif
|
2008-07-30 07:13:25 -07:00
|
|
|
Materials.push_back(SB3dMaterial());
|
|
|
|
SB3dMaterial& B3dMaterial=Materials.getLast();
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2007-12-03 02:07:40 -08:00
|
|
|
readFloats(&B3dMaterial.red, 1);
|
|
|
|
readFloats(&B3dMaterial.green, 1);
|
|
|
|
readFloats(&B3dMaterial.blue, 1);
|
|
|
|
readFloats(&B3dMaterial.alpha, 1);
|
|
|
|
readFloats(&B3dMaterial.shininess, 1);
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&B3dMaterial.blend, sizeof(B3dMaterial.blend));
|
|
|
|
B3DFile->read(&B3dMaterial.fx, sizeof(B3dMaterial.fx));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
B3dMaterial.blend = os::Byteswap::byteswap(B3dMaterial.blend);
|
|
|
|
B3dMaterial.fx = os::Byteswap::byteswap(B3dMaterial.fx);
|
|
|
|
#endif
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("Blend", core::stringc(B3dMaterial.blend).c_str());
|
|
|
|
os::Printer::log("FX", core::stringc(B3dMaterial.fx).c_str());
|
|
|
|
#endif
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2008-01-17 16:54:01 -08:00
|
|
|
u32 i;
|
|
|
|
for (i=0; i<num_textures; ++i)
|
2007-12-30 17:28:38 -08:00
|
|
|
{
|
|
|
|
s32 texture_id=-1;
|
|
|
|
B3DFile->read(&texture_id, sizeof(s32));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
texture_id = os::Byteswap::byteswap(texture_id);
|
|
|
|
#endif
|
|
|
|
//--- Get pointers to the texture, based on the IDs ---
|
2008-01-06 07:57:23 -08:00
|
|
|
if ((u32)texture_id < Textures.size())
|
2008-10-01 06:11:50 -07:00
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
B3dMaterial.Textures[i]=&Textures[texture_id];
|
2008-10-01 06:11:50 -07:00
|
|
|
#ifdef _B3D_READER_DEBUG
|
|
|
|
os::Printer::log("Layer", core::stringc(i).c_str());
|
|
|
|
os::Printer::log("using texture", Textures[texture_id].TextureName.c_str());
|
|
|
|
#endif
|
|
|
|
}
|
2007-12-30 17:28:38 -08:00
|
|
|
else
|
|
|
|
B3dMaterial.Textures[i]=0;
|
|
|
|
}
|
|
|
|
// skip other texture ids
|
2008-01-17 16:54:01 -08:00
|
|
|
for (i=0; i<n_texs_offset; ++i)
|
|
|
|
{
|
|
|
|
s32 texture_id=-1;
|
|
|
|
B3DFile->read(&texture_id, sizeof(s32));
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
texture_id = os::Byteswap::byteswap(texture_id);
|
|
|
|
#endif
|
|
|
|
if (ShowWarning && (texture_id != -1) && (n_texs>video::MATERIAL_MAX_TEXTURES))
|
|
|
|
{
|
|
|
|
os::Printer::log("Too many textures used in one material", B3DFile->getFileName(), ELL_WARNING);
|
|
|
|
ShowWarning = false;
|
|
|
|
}
|
|
|
|
}
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
//Fixes problems when the lightmap is on the first texture:
|
2007-12-30 17:28:38 -08:00
|
|
|
if (B3dMaterial.Textures[0] != 0)
|
2007-09-05 06:10:36 -07:00
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
if (B3dMaterial.Textures[0]->Flags & 65536) // 65536 = secondary UV
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
SB3dTexture *TmpTexture;
|
|
|
|
TmpTexture = B3dMaterial.Textures[1];
|
|
|
|
B3dMaterial.Textures[1] = B3dMaterial.Textures[0];
|
|
|
|
B3dMaterial.Textures[0] = TmpTexture;
|
|
|
|
}
|
2007-09-05 06:10:36 -07:00
|
|
|
}
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2008-10-01 06:11:50 -07:00
|
|
|
//If a preceeding texture slot is empty move the others down:
|
|
|
|
for (i=num_textures; i>0; --i)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2008-10-01 06:11:50 -07:00
|
|
|
for (u32 j=i-1; j<num_textures-1; ++j)
|
|
|
|
{
|
|
|
|
if (B3dMaterial.Textures[j+1] != 0 && B3dMaterial.Textures[j] == 0)
|
|
|
|
{
|
|
|
|
B3dMaterial.Textures[j] = B3dMaterial.Textures[j+1];
|
|
|
|
B3dMaterial.Textures[j+1] = 0;
|
|
|
|
}
|
|
|
|
}
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//------ Convert blitz flags/blend to irrlicht -------
|
|
|
|
|
|
|
|
//Two textures:
|
|
|
|
if (B3dMaterial.Textures[1])
|
|
|
|
{
|
2007-12-03 02:07:40 -08:00
|
|
|
if (B3dMaterial.alpha==1.f)
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2008-01-17 16:54:01 -08:00
|
|
|
if (B3dMaterial.Textures[1]->Blend == 5) //(Multiply 2)
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_LIGHTMAP_M2;
|
2007-09-04 11:51:42 -07:00
|
|
|
else
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_LIGHTMAP;
|
|
|
|
B3dMaterial.Material.Lighting = false;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
else
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
2007-09-05 06:10:36 -07:00
|
|
|
else if (B3dMaterial.Textures[0]) //One texture:
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2008-01-17 16:54:01 -08:00
|
|
|
// Flags & 0x1 is usual SOLID, 0x8 is mipmap (handled before)
|
|
|
|
if (B3dMaterial.Textures[0]->Flags & 0x2) //(Alpha mapped)
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
2008-01-17 16:54:01 -08:00
|
|
|
else if (B3dMaterial.Textures[0]->Flags & 0x4) //(Masked)
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; // TODO: create color key texture
|
2008-01-17 16:54:01 -08:00
|
|
|
else if (B3dMaterial.Textures[0]->Flags & 0x40)
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_SPHERE_MAP;
|
2008-01-17 16:54:01 -08:00
|
|
|
else if (B3dMaterial.Textures[0]->Flags & 0x80)
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_SPHERE_MAP; // TODO: Should be cube map
|
2007-12-03 02:07:40 -08:00
|
|
|
else if (B3dMaterial.alpha == 1.f)
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_SOLID;
|
2007-09-04 11:51:42 -07:00
|
|
|
else
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
2007-09-05 06:10:36 -07:00
|
|
|
else //No texture:
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
2007-12-03 02:07:40 -08:00
|
|
|
if (B3dMaterial.alpha == 1.f)
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_SOLID;
|
2007-09-04 11:51:42 -07:00
|
|
|
else
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.DiffuseColor = video::SColorf(B3dMaterial.red, B3dMaterial.green, B3dMaterial.blue, B3dMaterial.alpha).toSColor();
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
//------ Material fx ------
|
|
|
|
|
|
|
|
if (B3dMaterial.fx & 1) //full-bright
|
|
|
|
{
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.AmbientColor = video::SColor(255, 255, 255, 255);
|
|
|
|
B3dMaterial.Material.Lighting = false;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
2008-06-20 01:36:07 -07:00
|
|
|
else
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.AmbientColor = B3dMaterial.Material.DiffuseColor;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
//if (B3dMaterial.fx & 2) //use vertex colors instead of brush color
|
|
|
|
|
|
|
|
if (B3dMaterial.fx & 4) //flatshaded
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.GouraudShading = false;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
if (B3dMaterial.fx & 16) //disable backface culling
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.BackfaceCulling = false;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2008-01-17 16:54:01 -08:00
|
|
|
// if (B3dMaterial.fx & 32) //force vertex alpha-blending
|
2008-07-30 07:13:25 -07:00
|
|
|
// B3dMaterial.Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
2007-09-04 11:51:42 -07:00
|
|
|
|
2008-07-30 07:13:25 -07:00
|
|
|
B3dMaterial.Material.Shininess = B3dMaterial.shininess;
|
2007-09-04 11:51:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
B3dStack.erase(B3dStack.size()-1);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
|
2008-08-10 08:26:45 -07:00
|
|
|
void CB3DMeshFileLoader::loadTextures(SB3dMaterial& material) const
|
|
|
|
{
|
|
|
|
const bool previous32BitTextureFlag = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_ALWAYS_32_BIT);
|
|
|
|
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
|
|
|
|
|
|
|
|
// read texture from disk
|
|
|
|
// note that mipmaps might be disabled by Flags & 0x8
|
|
|
|
const bool doMipMaps = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
|
|
|
|
|
|
|
for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
|
|
|
|
{
|
|
|
|
SB3dTexture* B3dTexture = material.Textures[i];
|
2008-08-10 08:38:33 -07:00
|
|
|
if (B3dTexture && B3dTexture->TextureName.size() && !material.Material.getTexture(i))
|
2008-08-10 08:26:45 -07:00
|
|
|
{
|
|
|
|
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, (B3dTexture->Flags & 0x8) ? true:false);
|
|
|
|
material.Material.setTexture(i, SceneManager->getVideoDriver()->getTexture( B3dTexture->TextureName.c_str() ));
|
|
|
|
if (material.Textures[i]->Flags & 0x10) // Clamp U
|
|
|
|
material.Material.TextureLayer[i].TextureWrap=video::ETC_CLAMP;
|
2008-08-10 08:38:33 -07:00
|
|
|
if (material.Textures[i]->Flags & 0x20) // Clamp V
|
2008-08-10 08:26:45 -07:00
|
|
|
material.Material.TextureLayer[i].TextureWrap=video::ETC_CLAMP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, doMipMaps);
|
|
|
|
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, previous32BitTextureFlag);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-04 11:51:42 -07:00
|
|
|
core::stringc CB3DMeshFileLoader::readString()
|
|
|
|
{
|
|
|
|
core::stringc newstring;
|
2007-12-30 17:28:38 -08:00
|
|
|
while (B3DFile->getPos() <= B3DFile->getSize())
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
c8 character;
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(&character, sizeof(character));
|
2007-09-05 06:10:36 -07:00
|
|
|
if (character==0)
|
2007-12-30 17:28:38 -08:00
|
|
|
break;
|
2007-09-04 11:51:42 -07:00
|
|
|
newstring.append(character);
|
|
|
|
}
|
|
|
|
return newstring;
|
|
|
|
}
|
|
|
|
|
2007-12-30 17:28:38 -08:00
|
|
|
|
|
|
|
core::stringc CB3DMeshFileLoader::stripPathFromString(const core::stringc& string, bool returnPath) const
|
2007-09-04 11:51:42 -07:00
|
|
|
{
|
|
|
|
s32 slashIndex=string.findLast('/'); // forward slash
|
|
|
|
s32 backSlash=string.findLast('\\'); // back slash
|
|
|
|
|
|
|
|
if (backSlash>slashIndex) slashIndex=backSlash;
|
|
|
|
|
|
|
|
if (slashIndex==-1)//no slashes found
|
2007-12-08 05:11:39 -08:00
|
|
|
{
|
2007-09-04 11:51:42 -07:00
|
|
|
if (returnPath)
|
|
|
|
return core::stringc(); //no path to return
|
|
|
|
else
|
|
|
|
return string;
|
2007-12-08 05:11:39 -08:00
|
|
|
}
|
2007-09-04 11:51:42 -07:00
|
|
|
|
|
|
|
if (returnPath)
|
|
|
|
return string.subString(0, slashIndex + 1);
|
|
|
|
else
|
|
|
|
return string.subString(slashIndex+1, string.size() - (slashIndex+1));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CB3DMeshFileLoader::readFloats(f32* vec, u32 count)
|
|
|
|
{
|
2007-12-30 17:28:38 -08:00
|
|
|
B3DFile->read(vec, count*sizeof(f32));
|
2007-09-04 11:51:42 -07:00
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
for (u32 n=0; n<count; ++n)
|
|
|
|
vec[n] = os::Byteswap::byteswap(vec[n]);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end namespace scene
|
|
|
|
} // end namespace irr
|
|
|
|
|
|
|
|
|
|
|
|
#endif // _IRR_COMPILE_WITH_B3D_LOADER_
|
2007-09-05 06:10:36 -07:00
|
|
|
|