Added vertex color support to the DXF loader, fixed a minor bugs. Coordinate system issue still unsolved.
Modified GenVertexNormals to take always the cross product of the first and the last normal of a face as face normal. Material implementation for LWO - seems to work, but there are some issues with highly complex models. Added some LWO test models Cleaned up the ./test dir - converted some BMPs to JPG to save space, Finished the matrial property list in jAssimp, some other changes, too. The Java part of the API should be working now. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@156 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
0d5bb1c427
commit
3e46a0860e
20
CREDITS
20
CREDITS
|
@ -7,21 +7,29 @@ The following is the list of all constributors.
|
|||
Thanks for your help!
|
||||
|
||||
- Alexander Gessler,
|
||||
3DS-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL- and LWO-Loader,
|
||||
3DS-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF- and LWO-Loader,
|
||||
Configuration-Interface, AssImp-Viewer (Win32), Website (Admin and Design), admin.
|
||||
|
||||
-Thomas Schulze,
|
||||
X-Loader, Preprocessing framework.
|
||||
X-Loader, Preprocessing framework. Data structure & Interface design, documentation.
|
||||
|
||||
-R.Schmidt,
|
||||
Linux build, eclipse support.
|
||||
|
||||
- Kim Kulling:
|
||||
Obj-Loader, Logging, Scons-build enviroment.
|
||||
Obj-Loader, Logging, Scons-build environment.
|
||||
|
||||
- Matthias Gubisch,
|
||||
Assimp.net
|
||||
Visual Studio 9 support, bugfixes.
|
||||
|
||||
- Sebastian Hempel,
|
||||
PyAssimp
|
||||
Compile-Bugfixes for mingw, add enviroment for static library support in make.
|
||||
|
||||
- Jonathan Pokrass
|
||||
supplied a bugfix concerning the scaling in the md3 loader.
|
||||
|
||||
- Andrew Galante,
|
||||
submitted patches to make Assimp compile with GCC-4, a makefile and the xcode3 workspace.
|
||||
|
||||
|
@ -31,11 +39,5 @@ tested Assimp under Windows Vista 64 Bit.
|
|||
- Marius Schröder
|
||||
allowed us to use many of his models for screenshots and testing.
|
||||
|
||||
- Sebastian Hempel,
|
||||
Compile-Bugfixes for mingw, add enviroment for static library support in make.
|
||||
|
||||
- Jonathan Pokrass
|
||||
supplied a bugfix concerning the scaling in the md3 loader.
|
||||
|
||||
- Christian Schubert
|
||||
supplied various XFiles for testing purposes.
|
||||
|
|
|
@ -63,6 +63,31 @@ using namespace Assimp;
|
|||
#define AI_DXF_BINARY_IDENT_LEN (24)
|
||||
|
||||
|
||||
// color indices for DXF - 16 are supported
|
||||
static aiColor4D g_aclrDxfIndexColors[] =
|
||||
{
|
||||
aiColor4D (0.6f, 0.6f, 0.6f, 1.0f),
|
||||
aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red
|
||||
aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green
|
||||
aiColor4D (0.0f, 0.0f, 1.0f, 1.0f), // blue
|
||||
aiColor4D (0.3f, 1.0f, 0.3f, 1.0f), // light green
|
||||
aiColor4D (0.3f, 0.3f, 1.0f, 1.0f), // light blue
|
||||
aiColor4D (1.0f, 0.3f, 0.3f, 1.0f), // light red
|
||||
aiColor4D (1.0f, 0.0f, 1.0f, 1.0f), // pink
|
||||
aiColor4D (1.0f, 0.6f, 0.0f, 1.0f), // orange
|
||||
aiColor4D (0.6f, 0.3f, 0.0f, 1.0f), // dark orange
|
||||
aiColor4D (1.0f, 1.0f, 0.0f, 1.0f), // yellow
|
||||
aiColor4D (0.3f, 0.3f, 0.3f, 1.0f), // dark gray
|
||||
aiColor4D (0.8f, 0.8f, 0.8f, 1.0f), // light gray
|
||||
aiColor4D (0.0f, 00.f, 0.0f, 1.0f), // black
|
||||
aiColor4D (1.0f, 1.0f, 1.0f, 1.0f), // white
|
||||
aiColor4D (0.6f, 0.0f, 1.0f, 1.0f) // violet
|
||||
};
|
||||
#define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0]))
|
||||
|
||||
// invalid/unassigned color value
|
||||
aiColor4D g_clrInvalid = aiColor4D(std::numeric_limits<float>::quiet_NaN(),0.f,0.f,1.f);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
DXFImporter::DXFImporter()
|
||||
|
@ -157,7 +182,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
|
|||
{
|
||||
// ENTITIES and BLOCKS sections - skip the whole rest, no need to waste our time with them
|
||||
if (!::strcmp(cursor,"ENTITIES") || !::strcmp(cursor,"BLOCKS"))
|
||||
if (!ParseEntities())break;
|
||||
if (!ParseEntities())break; else bRepeat = true;
|
||||
|
||||
// other sections - skip them to make sure there will be no name conflicts
|
||||
else
|
||||
|
@ -200,6 +225,21 @@ void DXFImporter::InternReadFile( const std::string& pFile,
|
|||
// generate the output mesh
|
||||
aiMesh* pMesh = pScene->mMeshes[m++] = new aiMesh();
|
||||
const std::vector<aiVector3D>& vPositions = (*it).vPositions;
|
||||
const std::vector<aiColor4D>& vColors = (*it).vColors;
|
||||
|
||||
// check whether we need vertex colors here
|
||||
aiColor4D* clrOut;
|
||||
const aiColor4D* clr = NULL;
|
||||
for (std::vector<aiColor4D>::const_iterator it2 = (*it).vColors.begin(), end2 = (*it).vColors.end();
|
||||
it2 != end2; ++it2)
|
||||
{
|
||||
if (std::numeric_limits<float>::quiet_NaN() != (*it2).r)
|
||||
{
|
||||
clrOut = pMesh->mColors[0] = new aiColor4D[vPositions.size()];
|
||||
clr = &vColors[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pMesh->mNumFaces = (unsigned int)vPositions.size() / 4u;
|
||||
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
|
||||
|
@ -222,6 +262,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
|
|||
for (unsigned int a = 0; a < face.mNumIndices;++a)
|
||||
{
|
||||
*vpOut++ = vp[a];
|
||||
if (clr)*clrOut++ = clr[a];
|
||||
face.mIndices[a] = pMesh->mNumVertices++;
|
||||
}
|
||||
vp += 4;
|
||||
|
@ -333,6 +374,7 @@ bool DXFImporter::ParsePolyLine()
|
|||
LayerInfo* out = NULL;
|
||||
|
||||
std::vector<aiVector3D> positions;
|
||||
std::vector<aiColor4D> colors;
|
||||
std::vector<unsigned int> indices;
|
||||
unsigned int flags = 0;
|
||||
|
||||
|
@ -344,10 +386,14 @@ bool DXFImporter::ParsePolyLine()
|
|||
{
|
||||
if (!::strcmp(cursor,"VERTEX"))
|
||||
{
|
||||
aiVector3D v;
|
||||
aiVector3D v;aiColor4D clr(g_clrInvalid);
|
||||
unsigned int idx[4] = {0xffffffff,0xffffffff,0xffffffff,0xffffffff};
|
||||
ParsePolyLineVertex(v, idx);
|
||||
if (0xffffffff == idx[0])positions.push_back(v);
|
||||
ParsePolyLineVertex(v, clr, idx);
|
||||
if (0xffffffff == idx[0])
|
||||
{
|
||||
positions.push_back(v);
|
||||
colors.push_back(clr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// check whether we have a fourth coordinate
|
||||
|
@ -413,6 +459,10 @@ bool DXFImporter::ParsePolyLine()
|
|||
// use a default layer if necessary
|
||||
if (!out)SetDefaultLayer(out);
|
||||
|
||||
flags = (unsigned int)(out->vPositions.size()+indices.size());
|
||||
out->vPositions.reserve(flags);
|
||||
out->vColors.reserve(flags);
|
||||
|
||||
// generate unique vertices
|
||||
for (std::vector<unsigned int>::const_iterator it = indices.begin(), end = indices.end();
|
||||
it != end; ++it)
|
||||
|
@ -424,13 +474,14 @@ bool DXFImporter::ParsePolyLine()
|
|||
idx = (unsigned int) positions.size();
|
||||
}
|
||||
out->vPositions.push_back(positions[idx-1]); // indices are one-based.
|
||||
out->vColors.push_back(colors[idx-1]); // indices are one-based.
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,unsigned int* outIdx)
|
||||
bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,aiColor4D& clr, unsigned int* outIdx)
|
||||
{
|
||||
bool ret = false;
|
||||
while (GetNextToken())
|
||||
|
@ -455,6 +506,9 @@ bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,unsigned int* outIdx)
|
|||
case 72: outIdx[1] = strtol10(cursor);break;
|
||||
case 73: outIdx[2] = strtol10(cursor);break;
|
||||
case 74: outIdx[3] = strtol10(cursor);break;
|
||||
|
||||
// color
|
||||
case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break;
|
||||
};
|
||||
if (ret)break;
|
||||
}
|
||||
|
@ -468,6 +522,7 @@ bool DXFImporter::Parse3DFace()
|
|||
LayerInfo* out = NULL;
|
||||
|
||||
aiVector3D vip[4]; // -- vectors are initialized to zero
|
||||
aiColor4D clr(g_clrInvalid);
|
||||
while (GetNextToken())
|
||||
{
|
||||
switch (groupCode)
|
||||
|
@ -516,6 +571,9 @@ bool DXFImporter::Parse3DFace()
|
|||
|
||||
// z position of the fourth corner
|
||||
case 33: vip[3].z = fast_atof(cursor);break;
|
||||
|
||||
// color
|
||||
case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break;
|
||||
};
|
||||
if (ret)break;
|
||||
}
|
||||
|
@ -528,5 +586,8 @@ bool DXFImporter::Parse3DFace()
|
|||
out->vPositions.push_back(vip[1]);
|
||||
out->vPositions.push_back(vip[2]);
|
||||
out->vPositions.push_back(vip[3]); // might be equal to the third
|
||||
|
||||
for (unsigned int i = 0; i < 4;++i)
|
||||
out->vColors.push_back(clr);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ protected:
|
|||
|
||||
// face buffer - order is x,y,z,w v1,v2,v3 (w is equal to z if unused)
|
||||
std::vector<aiVector3D> vPositions;
|
||||
std::vector<aiColor4D> vColors;
|
||||
};
|
||||
|
||||
|
||||
|
@ -149,11 +150,13 @@ protected:
|
|||
// -------------------------------------------------------------------
|
||||
/** Parses a VERTEX element in a POLYLINE/POLYFACE
|
||||
* @param out Receives the output vertex.
|
||||
* @param clr Receives the output vertex color - won't be modified
|
||||
* if it is not existing.
|
||||
* @param outIdx Receives the output vertex indices, if present.
|
||||
* Wont't be modified otherwise. Size must be at least 4.
|
||||
* @return false if the end of the file was reached
|
||||
*/
|
||||
bool ParsePolyLineVertex(aiVector3D& out,unsigned int* outIdx);
|
||||
bool ParsePolyLineVertex(aiVector3D& out, aiColor4D& clr, unsigned int* outIdx);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -106,20 +106,11 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
|
|||
|
||||
aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[2]];
|
||||
|
||||
aiVector3D pDelta1 = *pV2 - *pV1;
|
||||
aiVector3D pDelta2 = *pV3 - *pV1;
|
||||
aiVector3D vNor = pDelta1 ^ pDelta2;
|
||||
vNor.Normalize();
|
||||
|
||||
//if (face.mIndices[1] > face.mIndices[2])
|
||||
// vNor *= -1.0f;
|
||||
aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
|
||||
aiVector3D vNor = (*pV2 - *pV1) ^ (*pV3 - *pV1).Normalize();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i)
|
||||
{
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -116,12 +116,8 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
|
|||
|
||||
aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
|
||||
aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
|
||||
aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[2]];
|
||||
|
||||
aiVector3D pDelta1 = *pV2 - *pV1;
|
||||
aiVector3D pDelta2 = *pV3 - *pV1;
|
||||
aiVector3D vNor = pDelta1 ^ pDelta2;
|
||||
vNor.Normalize();
|
||||
aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
|
||||
aiVector3D vNor = (*pV2 - *pV1) ^ (*pV3 - *pV1).Normalize();
|
||||
|
||||
for (unsigned int i = 0;i < face.mNumIndices;++i)
|
||||
pMesh->mNormals[face.mIndices[i]] = vNor;
|
||||
|
@ -146,7 +142,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
|
|||
SpatialSort vertexFinder( pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
|
||||
std::vector<unsigned int> verticesFound;
|
||||
|
||||
const float fLimit = cosf(this->configMaxAngle);
|
||||
const float fLimit = cos(this->configMaxAngle);
|
||||
|
||||
aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
||||
|
@ -157,7 +153,6 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
|
|||
vertexFinder.FindPositions( posThis, posEpsilon, verticesFound);
|
||||
|
||||
aiVector3D pcNor;
|
||||
//unsigned int div = 0;
|
||||
for (unsigned int a = 0; a < verticesFound.size(); ++a)
|
||||
{
|
||||
unsigned int vidx = verticesFound[a];
|
||||
|
@ -167,7 +162,6 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh)
|
|||
continue;
|
||||
|
||||
pcNor += pMesh->mNormals[vidx];
|
||||
//++div;
|
||||
}
|
||||
pcNor.Normalize();
|
||||
pcNew[i] = pcNor;
|
||||
|
|
61
code/IFF.h
61
code/IFF.h
|
@ -2,17 +2,21 @@
|
|||
|
||||
// Definitions for the Interchange File Format (IFF)
|
||||
// Alexander Gessler, 2006
|
||||
// Adapted for Assimp August 2008
|
||||
// Adapted to Assimp August 2008
|
||||
|
||||
#ifndef AI_IFF_H_INCLUDED
|
||||
#define AI_IFF_H_INCLUDED
|
||||
|
||||
#include "ByteSwap.h"
|
||||
|
||||
namespace Assimp {
|
||||
namespace IFF {
|
||||
namespace Assimp {
|
||||
namespace IFF {
|
||||
|
||||
#include "./../include/Compiler/pushpack1.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Describes an IFF chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
struct ChunkHeader
|
||||
{
|
||||
//! Type of the chunk header - FourCC
|
||||
|
@ -20,7 +24,22 @@ struct ChunkHeader
|
|||
|
||||
//! Length of the chunk data, in bytes
|
||||
uint32_t length;
|
||||
};
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Describes an IFF sub chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
struct SubChunkHeader
|
||||
{
|
||||
//! Type of the chunk header - FourCC
|
||||
uint32_t type;
|
||||
|
||||
//! Length of the chunk data, in bytes
|
||||
uint16_t length;
|
||||
} PACK_STRUCT;
|
||||
|
||||
#include "./../include/Compiler/poppack1.h"
|
||||
|
||||
|
||||
#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
|
||||
|
@ -30,6 +49,34 @@ struct ChunkHeader
|
|||
#define AI_IFF_FOURCC_FORM AI_IFF_FOURCC('F','O','R','M')
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Load a chunk header
|
||||
//! @param outFile Pointer to the file data - points to the chunk data afterwards
|
||||
//! @return Pointer to the chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline LE_NCONST ChunkHeader* LoadChunk(LE_NCONST uint8_t*& outFile)
|
||||
{
|
||||
LE_NCONST ChunkHeader* head = (LE_NCONST ChunkHeader*) outFile;
|
||||
AI_LSWAP4(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
outFile += sizeof(ChunkHeader);
|
||||
return head;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Load a sub chunk header
|
||||
//! @param outFile Pointer to the file data - points to the chunk data afterwards
|
||||
//! @return Pointer to the sub chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline LE_NCONST SubChunkHeader* LoadSubChunk(LE_NCONST uint8_t*& outFile)
|
||||
{
|
||||
LE_NCONST SubChunkHeader* head = (LE_NCONST SubChunkHeader*) outFile;
|
||||
AI_LSWAP2(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
outFile += sizeof(SubChunkHeader);
|
||||
return head;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Read the file header and return the type of the file and its size
|
||||
//! @param outFile Pointer to the file data. The buffer must at
|
||||
|
@ -37,11 +84,9 @@ struct ChunkHeader
|
|||
//! @param fileType Receives the type of the file
|
||||
//! @return 0 if everything was OK, otherwise an error message
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
inline const char* ReadHeader(const uint8_t* outFile,uint32_t& fileType)
|
||||
inline const char* ReadHeader(LE_NCONST uint8_t* outFile,uint32_t& fileType)
|
||||
{
|
||||
LE_NCONST ChunkHeader* head = (LE_NCONST ChunkHeader*) outFile;
|
||||
AI_LSWAP4(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
LE_NCONST ChunkHeader* head = LoadChunk(outFile);
|
||||
if(AI_IFF_FOURCC_FORM != head->type)
|
||||
{
|
||||
return "The file is not an IFF file: FORM chunk is missing";
|
||||
|
|
|
@ -63,14 +63,11 @@ void LWOImporter::LoadLWOBFile()
|
|||
while (true)
|
||||
{
|
||||
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
|
||||
LE_NCONST IFF::ChunkHeader* const head = (LE_NCONST IFF::ChunkHeader*)mFileBuffer;
|
||||
AI_LSWAP4(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
mFileBuffer += sizeof(IFF::ChunkHeader);
|
||||
LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
{
|
||||
throw new ImportErrorException("LWOB: Invalid file, the size attribute of "
|
||||
"a chunk points behind the end of the file");
|
||||
throw new ImportErrorException("LWOB: Invalid chunk length");
|
||||
break;
|
||||
}
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||
|
@ -204,104 +201,113 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
LWO::Surface& surf = mSurfaces->back();
|
||||
LWO::Texture* pTex = NULL;
|
||||
|
||||
ParseString(surf.mName,size);
|
||||
mFileBuffer+=surf.mName.length()+1;
|
||||
// skip one byte if the length of the surface name is odd
|
||||
if (!(surf.mName.length() & 1))++mFileBuffer;
|
||||
GetS0(surf.mName,size);
|
||||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 > end)break;
|
||||
|
||||
// no proper IFF header here - the chunk length is specified as int16
|
||||
uint32_t head_type = *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer+=4;
|
||||
uint16_t head_length = *((LE_NCONST uint16_t*)mFileBuffer);mFileBuffer+=2;
|
||||
AI_LSWAP4(head_type);
|
||||
AI_LSWAP2(head_length);
|
||||
if (mFileBuffer + head_length > end)
|
||||
{
|
||||
throw new ImportErrorException("LWOB: Invalid file, the size attribute of "
|
||||
"a surface sub chunk points behind the end of the file");
|
||||
}
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head_length;
|
||||
switch (head_type)
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
throw new ImportErrorException("LWOB: Invalid surface chunk length");
|
||||
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
{
|
||||
// diffuse color
|
||||
case AI_LWO_COLR:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,COLR,3);
|
||||
surf.mColor.r = *mFileBuffer++ / 255.0f;
|
||||
surf.mColor.g = *mFileBuffer++ / 255.0f;
|
||||
surf.mColor.b = *mFileBuffer / 255.0f;
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3);
|
||||
surf.mColor.r = GetU1() / 255.0f;
|
||||
surf.mColor.g = GetU1() / 255.0f;
|
||||
surf.mColor.b = GetU1() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// diffuse strength ...
|
||||
case AI_LWO_DIFF:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,DIFF,2);
|
||||
AI_LSWAP2P(mFileBuffer);
|
||||
surf.mDiffuseValue = *((int16_t*)mFileBuffer) / 255.0f;
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2);
|
||||
surf.mDiffuseValue = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// specular strength ...
|
||||
case AI_LWO_SPEC:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,SPEC,2);
|
||||
AI_LSWAP2P(mFileBuffer);
|
||||
surf.mSpecularValue = *((int16_t*)mFileBuffer) / 255.0f;
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2);
|
||||
surf.mSpecularValue = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// luminosity ...
|
||||
case AI_LWO_LUMI:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,LUMI,2);
|
||||
AI_LSWAP2P(mFileBuffer);
|
||||
surf.mLuminosity = *((int16_t*)mFileBuffer) / 255.0f;
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2);
|
||||
surf.mLuminosity = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// transparency
|
||||
case AI_LWO_TRAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TRAN,2);
|
||||
AI_LSWAP2P(mFileBuffer);
|
||||
surf.mTransparency = *((int16_t*)mFileBuffer) / 255.0f;
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2);
|
||||
surf.mTransparency = GetU2() / 255.0f;
|
||||
break;
|
||||
}
|
||||
// surface flags
|
||||
case AI_LWO_FLAG:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2);
|
||||
uint16_t flag = GetU2();
|
||||
if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
|
||||
if (flag & 0x8 ) surf.mColorHighlights = 1.f;
|
||||
if (flag & 0x100) surf.bDoubleSided = true;
|
||||
break;
|
||||
}
|
||||
// maximum smoothing angle
|
||||
case AI_LWO_SMAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
|
||||
surf.mMaximumSmoothAngle = GetF4();
|
||||
break;
|
||||
}
|
||||
// glossiness
|
||||
case AI_LWO_GLOS:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,GLOS,2);
|
||||
AI_LSWAP2P(mFileBuffer);
|
||||
surf.mGlossiness = float(*((int16_t*)mFileBuffer));
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2);
|
||||
surf.mGlossiness = (float)GetU2();
|
||||
break;
|
||||
}
|
||||
// color texture
|
||||
case AI_LWO_CTEX:
|
||||
{
|
||||
pTex = &surf.mColorTexture;
|
||||
surf.mColorTextures.push_back(Texture());
|
||||
pTex = &surf.mColorTextures.back();
|
||||
break;
|
||||
}
|
||||
// diffuse texture
|
||||
case AI_LWO_DTEX:
|
||||
{
|
||||
pTex = &surf.mDiffuseTexture;
|
||||
surf.mDiffuseTextures.push_back(Texture());
|
||||
pTex = &surf.mDiffuseTextures.back();
|
||||
break;
|
||||
}
|
||||
// specular texture
|
||||
case AI_LWO_STEX:
|
||||
{
|
||||
pTex = &surf.mSpecularTexture;
|
||||
surf.mSpecularTextures.push_back(Texture());
|
||||
pTex = &surf.mSpecularTextures.back();
|
||||
break;
|
||||
}
|
||||
// bump texture
|
||||
case AI_LWO_BTEX:
|
||||
{
|
||||
pTex = &surf.mBumpTexture;
|
||||
surf.mBumpTextures.push_back(Texture());
|
||||
pTex = &surf.mBumpTextures.back();
|
||||
break;
|
||||
}
|
||||
// transparency texture
|
||||
case AI_LWO_TTEX:
|
||||
{
|
||||
pTex = &surf.mTransparencyTexture;
|
||||
surf.mOpacityTextures.push_back(Texture());
|
||||
pTex = &surf.mOpacityTextures.back();
|
||||
break;
|
||||
}
|
||||
// texture path
|
||||
|
@ -309,9 +315,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
{
|
||||
if (pTex)
|
||||
{
|
||||
ParseString(pTex->mFileName,head_length);
|
||||
AdjustTexturePath(pTex->mFileName);
|
||||
mFileBuffer += pTex->mFileName.length();
|
||||
GetS0(pTex->mFileName,head->length);
|
||||
}
|
||||
else DefaultLogger::get()->warn("LWOB: TIMG tag was encuntered although "
|
||||
"there was no xTEX tag before");
|
||||
|
@ -320,8 +324,8 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// texture strength
|
||||
case AI_LWO_TVAL:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TVAL,1);
|
||||
if (pTex)pTex->mStrength = *mFileBuffer / 255.0f;
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1);
|
||||
if (pTex)pTex->mStrength = (float)GetU1()/ 255.f;
|
||||
else DefaultLogger::get()->warn("LWOB: TVAL tag was encuntered "
|
||||
"although there was no xTEX tag before");
|
||||
break;
|
||||
|
|
|
@ -40,9 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
/** @file Defines chunk constants used by the LWO file format
|
||||
|
||||
The chunks are taken from LWO2.h, found in the sourcecode of
|
||||
a project called Nxabega (http://www.sourceforge.net/projects/nxabega).
|
||||
I assume they are from the official LightWave SDK headers.
|
||||
The chunks are taken from the official LightWave SDK headers.
|
||||
Original copyright notice: "Ernie Wright 17 Sep 00"
|
||||
|
||||
*/
|
||||
|
@ -253,12 +251,25 @@ namespace LWO {
|
|||
struct Face : public aiFace
|
||||
{
|
||||
Face()
|
||||
: surfaceIndex(0)
|
||||
, smoothGroup(0)
|
||||
: surfaceIndex (0)
|
||||
, smoothGroup (0)
|
||||
{}
|
||||
|
||||
Face(const Face& f)
|
||||
{
|
||||
*this = f;
|
||||
}
|
||||
|
||||
unsigned int surfaceIndex;
|
||||
unsigned int smoothGroup;
|
||||
|
||||
Face& operator=(const LWO::Face& f)
|
||||
{
|
||||
aiFace::operator =(f);
|
||||
surfaceIndex = f.surfaceIndex;
|
||||
smoothGroup = f.smoothGroup;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -271,11 +282,24 @@ struct VMapEntry
|
|||
: dims(_dims)
|
||||
{}
|
||||
|
||||
~VMapEntry() {delete[] rawData;}
|
||||
virtual ~VMapEntry() {}
|
||||
|
||||
//! allocates memory for the vertex map
|
||||
virtual void Allocate(unsigned int num)
|
||||
{
|
||||
if (!rawData.empty())return; // return if already allocated
|
||||
|
||||
register unsigned int m = num*dims;
|
||||
rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
|
||||
rawData.resize(m,0.f);
|
||||
abAssigned.resize(num,false);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
float* rawData;
|
||||
unsigned int dims;
|
||||
std::vector<float> rawData;
|
||||
|
||||
std::vector<bool> abAssigned;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -283,16 +307,29 @@ struct VMapEntry
|
|||
*/
|
||||
struct VColorChannel : public VMapEntry
|
||||
{
|
||||
VColorChannel(unsigned int num)
|
||||
VColorChannel()
|
||||
: VMapEntry(4)
|
||||
{
|
||||
data = new aiColor4D[num];
|
||||
for (unsigned int i = 0; i < num;++i)
|
||||
data[i].a = 1.0f;
|
||||
rawData = (float*)data;
|
||||
}
|
||||
{}
|
||||
|
||||
aiColor4D* data;
|
||||
//! need to overwrite this function - the alpha channel must
|
||||
//! be initialized to 1.0 by default
|
||||
virtual void Allocate(unsigned int num)
|
||||
{
|
||||
if (!rawData.empty())return; // return if already allocated
|
||||
|
||||
register unsigned int m = num*dims;
|
||||
rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs
|
||||
rawData.resize(m,0.f);
|
||||
|
||||
for (std::vector<float>::iterator it = rawData.begin(), end = rawData.end();
|
||||
it != end;++it )
|
||||
{
|
||||
for (unsigned int i = 0; i< 3;++i,++it)
|
||||
*it = 0.f;
|
||||
*it = 1.f;
|
||||
}
|
||||
abAssigned.resize(num,false);
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -300,14 +337,9 @@ struct VColorChannel : public VMapEntry
|
|||
*/
|
||||
struct UVChannel : public VMapEntry
|
||||
{
|
||||
UVChannel(unsigned int num)
|
||||
: VMapEntry(3)
|
||||
{
|
||||
data = new aiVector3D[num]; // to make the final copying easier
|
||||
rawData = (float*)data;
|
||||
}
|
||||
|
||||
aiVector3D* data;
|
||||
UVChannel()
|
||||
: VMapEntry(2)
|
||||
{}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -315,13 +347,9 @@ struct UVChannel : public VMapEntry
|
|||
*/
|
||||
struct WeightChannel : public VMapEntry
|
||||
{
|
||||
WeightChannel(unsigned int num)
|
||||
WeightChannel()
|
||||
: VMapEntry(1)
|
||||
{
|
||||
rawData = new float[num];
|
||||
for (unsigned int m = 0; m < num;++m)
|
||||
rawData[m] = 0.f;
|
||||
}
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
|
@ -330,10 +358,59 @@ struct WeightChannel : public VMapEntry
|
|||
*/
|
||||
struct Texture
|
||||
{
|
||||
// we write the enum values out here to make debugging easier ...
|
||||
enum BlendType
|
||||
{
|
||||
Normal = 0,
|
||||
Subtractive = 1,
|
||||
Difference = 2,
|
||||
Multiply = 3,
|
||||
Divide = 4,
|
||||
Alpha = 5,
|
||||
TextureDispl = 6,
|
||||
Additive = 7
|
||||
};
|
||||
|
||||
enum MappingMode
|
||||
{
|
||||
Planar = 0,
|
||||
Cylindrical = 1,
|
||||
Spherical = 2,
|
||||
Cubic = 3,
|
||||
FrontProjection = 4,
|
||||
UV = 5
|
||||
};
|
||||
|
||||
enum Axes
|
||||
{
|
||||
AXIS_X = 0,
|
||||
AXIS_Y = 1,
|
||||
AXIS_Z = 2
|
||||
};
|
||||
|
||||
enum Wrap
|
||||
{
|
||||
RESET = 0,
|
||||
REPEAT = 1,
|
||||
MIRROR = 2,
|
||||
EDGE = 3
|
||||
};
|
||||
|
||||
Texture()
|
||||
: mClipIdx(0xffffffff)
|
||||
, mStrength (1.0f)
|
||||
, mUVChannelIndex ("unknown")
|
||||
, mRealUVIndex (0xffffffff)
|
||||
, enabled (true)
|
||||
, blendType (Additive)
|
||||
, bCanUse (true)
|
||||
, mapMode (UV)
|
||||
, majorAxis (AXIS_X)
|
||||
, wrapAmountH (1.0f)
|
||||
, wrapAmountW (1.0f)
|
||||
, wrapModeWidth (REPEAT)
|
||||
, wrapModeHeight (REPEAT)
|
||||
, ordinal ("\x00")
|
||||
{}
|
||||
|
||||
//! File name of the texture
|
||||
|
@ -342,15 +419,38 @@ struct Texture
|
|||
//! Clip index
|
||||
unsigned int mClipIdx;
|
||||
|
||||
//! Strength of the texture
|
||||
//! Strength of the texture - blend factor
|
||||
float mStrength;
|
||||
|
||||
|
||||
/*************** SPECIFIC TO LWO2 *********************/
|
||||
uint32_t type; // type of the texture
|
||||
|
||||
//! Name of the corresponding UV channel
|
||||
std::string mUVChannelIndex;
|
||||
unsigned int mRealUVIndex;
|
||||
|
||||
//! is the texture enabled?
|
||||
bool enabled;
|
||||
|
||||
//! blend type
|
||||
BlendType blendType;
|
||||
|
||||
//! are we able to use the texture?
|
||||
bool bCanUse;
|
||||
|
||||
//! mapping mode
|
||||
MappingMode mapMode;
|
||||
|
||||
//! major axis for planar, cylindrical, spherical projections
|
||||
Axes majorAxis;
|
||||
|
||||
//! wrap amount for cylindrical and spherical projections
|
||||
float wrapAmountH,wrapAmountW;
|
||||
|
||||
//! wrapping mode for the texture
|
||||
Wrap wrapModeWidth,wrapModeHeight;
|
||||
|
||||
//! ordinal string of the texture
|
||||
std::string ordinal;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -358,23 +458,66 @@ struct Texture
|
|||
*/
|
||||
struct Clip
|
||||
{
|
||||
//! path to the base texture
|
||||
enum Type
|
||||
{
|
||||
STILL, SEQ, REF, UNSUPPORTED
|
||||
} type;
|
||||
|
||||
Clip()
|
||||
: type (UNSUPPORTED)
|
||||
, idx (0)
|
||||
{}
|
||||
|
||||
//! path to the base texture -
|
||||
std::string path;
|
||||
|
||||
//! reference to another CLIP
|
||||
unsigned int clipRef;
|
||||
|
||||
//! index of the clip
|
||||
unsigned int idx;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO file shader
|
||||
*
|
||||
* Later
|
||||
*/
|
||||
struct Shader
|
||||
{
|
||||
Shader()
|
||||
: ordinal ("\x00")
|
||||
, functionName ("unknown")
|
||||
, enabled (true)
|
||||
{}
|
||||
|
||||
std::string ordinal;
|
||||
std::string functionName;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
typedef std::list < Texture > TextureList;
|
||||
typedef std::list < Shader > ShaderList;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Data structure for a LWO file surface (= material)
|
||||
*/
|
||||
struct Surface
|
||||
{
|
||||
Surface()
|
||||
: bDoubleSided (false)
|
||||
, mDiffuseValue (1.0f)
|
||||
, mSpecularValue (1.0f)
|
||||
, mTransparency (0.0f)
|
||||
, mGlossiness (0.0f)
|
||||
, mLuminosity (0.0f)
|
||||
, mMaximumSmoothAngle (0.0f) // 0 == not specified
|
||||
: mColor (0.78431f,0.78431f,0.78431f)
|
||||
, bDoubleSided (false)
|
||||
, mDiffuseValue (1.f)
|
||||
, mSpecularValue (0.f)
|
||||
, mTransparency (0.f)
|
||||
, mGlossiness (0.4f)
|
||||
, mLuminosity (0.f)
|
||||
, mColorHighlights (0.f)
|
||||
, mMaximumSmoothAngle (0.f) // 0 == not specified, no smoothing
|
||||
, mVCMap ("")
|
||||
, mIOR (1.f) // vakuum
|
||||
, mBumpIntensity (1.f)
|
||||
{}
|
||||
|
||||
//! Name of the surface
|
||||
|
@ -387,23 +530,38 @@ struct Surface
|
|||
bool bDoubleSided;
|
||||
|
||||
//! Various material parameters
|
||||
float mDiffuseValue,mSpecularValue,mTransparency,mGlossiness,mLuminosity;
|
||||
float mDiffuseValue,mSpecularValue,mTransparency,mGlossiness,mLuminosity,mColorHighlights;
|
||||
|
||||
//! Maximum angle between two adjacent triangles
|
||||
//! that they can be smoothed - in degrees
|
||||
float mMaximumSmoothAngle;
|
||||
|
||||
//! Textures
|
||||
Texture mColorTexture,mDiffuseTexture,mSpecularTexture,
|
||||
mBumpTexture,mTransparencyTexture;
|
||||
//! Vertex color map to be used to color the surface
|
||||
std::string mVCMap;
|
||||
|
||||
//! Names of the special shaders to be applied to the surface
|
||||
ShaderList mShaders;
|
||||
|
||||
//! Textures - the first entry in the list is evaluated first
|
||||
TextureList mColorTextures, // color textures are added to both diffuse and specular texture stacks
|
||||
mDiffuseTextures,
|
||||
mSpecularTextures,
|
||||
mOpacityTextures,
|
||||
mBumpTextures,
|
||||
mGlossinessTextures;
|
||||
|
||||
//! Index of refraction
|
||||
float mIOR;
|
||||
|
||||
//! Bump intensity scaling
|
||||
float mBumpIntensity;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
#define AI_LWO_VALIDATE_CHUNK_LENGTH(length,name,size) \
|
||||
if (length < size) \
|
||||
{ \
|
||||
DefaultLogger::get()->warn("LWO: "#name" chunk is too small"); \
|
||||
break; \
|
||||
throw new ImportErrorException("LWO: "#name" chunk is too small"); \
|
||||
} \
|
||||
|
||||
|
||||
|
@ -413,6 +571,7 @@ typedef std::vector < LWO::Face > FaceList;
|
|||
typedef std::vector < LWO::Surface > SurfaceList;
|
||||
typedef std::vector < std::string > TagList;
|
||||
typedef std::vector < unsigned int > TagMappingTable;
|
||||
typedef std::vector < unsigned int > ReferrerList;
|
||||
typedef std::vector < WeightChannel > WeightChannelList;
|
||||
typedef std::vector < VColorChannel > VColorChannelList;
|
||||
typedef std::vector < UVChannel > UVChannelList;
|
||||
|
@ -433,6 +592,11 @@ struct Layer
|
|||
/** Temporary point list from the file */
|
||||
PointList mTempPoints;
|
||||
|
||||
/** Lists for every point the index of another point
|
||||
that has been copied from *this* point or 0xffffffff if
|
||||
no copy of the point has been made */
|
||||
ReferrerList mPointReferrers;
|
||||
|
||||
/** Weight channel list from the file */
|
||||
WeightChannelList mWeightChannels;
|
||||
|
||||
|
@ -456,6 +620,9 @@ struct Layer
|
|||
|
||||
/** Name of the layer */
|
||||
std::string mName;
|
||||
|
||||
/** Pivot point of the layer */
|
||||
aiVector3D mPivot;
|
||||
};
|
||||
|
||||
typedef std::list<LWO::Layer> LayerList;
|
||||
|
|
|
@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "LWOLoader.h"
|
||||
#include "MaterialSystem.h"
|
||||
#include "StringComparison.h"
|
||||
#include "SGSpatialSort.h"
|
||||
#include "ByteSwap.h"
|
||||
|
||||
// public assimp headers
|
||||
|
@ -52,11 +53,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "../include/IOSystem.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/aiAssert.h"
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/assimp.hpp"
|
||||
|
||||
// boost headers
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -91,12 +93,14 @@ bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties
|
||||
void LWOImporter::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
// -- no configuration options at the moment
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void LWOImporter::InternReadFile( const std::string& pFile,
|
||||
|
@ -166,7 +170,10 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
szBuff[3] = (char)(fileType);
|
||||
throw new ImportErrorException(std::string("Unknown LWO sub format: ") + szBuff);
|
||||
}
|
||||
|
||||
// now, as we have loaded all data, we can resolve cross-referenced tags and clips
|
||||
ResolveTags();
|
||||
ResolveClips();
|
||||
|
||||
// now process all layers and build meshes and nodes
|
||||
std::vector<aiMesh*> apcMeshes;
|
||||
|
@ -176,10 +183,10 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
|
||||
unsigned int iDefaultSurface = 0xffffffff; // index of the default surface
|
||||
for (LayerList::const_iterator lit = mLayers->begin(), lend = mLayers->end();
|
||||
for (LayerList::iterator lit = mLayers->begin(), lend = mLayers->end();
|
||||
lit != lend;++lit)
|
||||
{
|
||||
const LWO::Layer& layer = *lit;
|
||||
LWO::Layer& layer = *lit;
|
||||
|
||||
// I don't know whether there could be dummy layers, but it would be possible
|
||||
const unsigned int meshStart = (unsigned int)apcMeshes.size();
|
||||
|
@ -190,7 +197,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
std::vector<SortedRep> pSorted(mSurfaces->size()+1);
|
||||
|
||||
unsigned int i = 0;
|
||||
for (FaceList::const_iterator it = layer.mFaces.begin(), end = layer.mFaces.end();
|
||||
for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end();
|
||||
it != end;++it,++i)
|
||||
{
|
||||
unsigned int idx = (*it).surfaceIndex;
|
||||
|
@ -232,8 +239,9 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
apcMeshes.push_back(mesh);
|
||||
mesh->mNumFaces = (unsigned int)sorted.size();
|
||||
|
||||
for (SortedRep::const_iterator it = sorted.begin(), end = sorted.end();
|
||||
it != end;++it)
|
||||
// count the number of vertices
|
||||
SortedRep::const_iterator it = sorted.begin(), end = sorted.end();
|
||||
for (;it != end;++it)
|
||||
{
|
||||
mesh->mNumVertices += layer.mFaces[*it].mNumIndices;
|
||||
}
|
||||
|
@ -275,31 +283,45 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
pvVC[mui] = mesh->mColors[mui] = new aiColor4D[mesh->mNumVertices];
|
||||
}
|
||||
|
||||
// we would not need this extra array, but the code is much cleaner if we use it
|
||||
// FIX: we can use the referrer ID array here. invalidate its contents
|
||||
// before we resize it to avoid a unnecessary memcpy
|
||||
std::vector<unsigned int>& smoothingGroups = layer.mPointReferrers;
|
||||
smoothingGroups.erase (smoothingGroups.begin(),smoothingGroups.end());
|
||||
smoothingGroups.resize(mesh->mNumFaces,0);
|
||||
|
||||
// now convert all faces
|
||||
unsigned int vert = 0;
|
||||
for (SortedRep::const_iterator it = sorted.begin(), end = sorted.end();
|
||||
it != end;++it)
|
||||
std::vector<unsigned int>::iterator outIt = smoothingGroups.begin();
|
||||
for (it = sorted.begin(); it != end;++it,++outIt)
|
||||
{
|
||||
const LWO::Face& face = layer.mFaces[*it];
|
||||
*outIt = face.smoothGroup;
|
||||
|
||||
// copy all vertices
|
||||
for (unsigned int q = 0; q < face.mNumIndices;++q)
|
||||
{
|
||||
register unsigned int idx = face.mIndices[q];
|
||||
*pv++ = layer.mTempPoints[idx];
|
||||
*pv = layer.mTempPoints[idx] + layer.mPivot;
|
||||
pv->z *= -1.0f; // DX to OGL
|
||||
pv++;
|
||||
|
||||
// process UV coordinates
|
||||
for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS;++w)
|
||||
{
|
||||
if (0xffffffff == vUVChannelIndices[w])break;
|
||||
*(pvUV[w])++ = layer.mUVChannels[vUVChannelIndices[w]].data[idx];
|
||||
aiVector3D*& pp = pvUV[w];
|
||||
const aiVector2D& src = ((aiVector2D*)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx];
|
||||
pp->x = src.x;
|
||||
pp->y = 1.0f - src.y; // DX to OGL
|
||||
pp++;
|
||||
}
|
||||
|
||||
// process vertex colors
|
||||
for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w)
|
||||
{
|
||||
if (0xffffffff == vVColorIndices[w])break;
|
||||
*(pvVC[w])++ = layer.mVColorChannels[vVColorIndices[w]].data[idx];
|
||||
*(pvVC[w])++ = ((aiColor4D*)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx];
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -308,14 +330,20 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
{
|
||||
}
|
||||
#endif
|
||||
face.mIndices[q] = vert++;
|
||||
face.mIndices[q] = vert + (face.mNumIndices-q-1);
|
||||
}
|
||||
vert += face.mNumIndices;
|
||||
|
||||
pf->mIndices = face.mIndices;
|
||||
pf->mNumIndices = face.mNumIndices;
|
||||
unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // make sure it won't be deleted
|
||||
pf++;
|
||||
}
|
||||
|
||||
// compute normal vectors for the mesh - we can't use our GenSmoothNormal-Step here
|
||||
// since it wouldn't handle smoothing groups correctly
|
||||
ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]);
|
||||
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
@ -352,11 +380,103 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
|||
GenerateNodeGraph(apcNodes);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups,
|
||||
const LWO::Surface& surface)
|
||||
{
|
||||
// allocate output storage
|
||||
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
||||
|
||||
// First generate per-face normals
|
||||
aiVector3D* out;
|
||||
std::vector<aiVector3D> faceNormals;
|
||||
|
||||
if (!surface.mMaximumSmoothAngle)
|
||||
out = mesh->mNormals;
|
||||
else
|
||||
{
|
||||
faceNormals.resize(mesh->mNumVertices);
|
||||
out = &faceNormals[0];
|
||||
}
|
||||
|
||||
aiFace* begin = mesh->mFaces, *const end = mesh->mFaces+mesh->mNumFaces;
|
||||
for (; begin != end; ++begin)
|
||||
{
|
||||
aiFace& face = *begin;
|
||||
|
||||
// LWO doc: "the normal is defined as the cross product of the first and last edges"
|
||||
aiVector3D* pV1 = mesh->mVertices + face.mIndices[0];
|
||||
aiVector3D* pV2 = mesh->mVertices + face.mIndices[1];
|
||||
aiVector3D* pV3 = mesh->mVertices + face.mIndices[face.mNumIndices-1];
|
||||
|
||||
aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||
out[face.mIndices[i]] = vNor;
|
||||
}
|
||||
if (!surface.mMaximumSmoothAngle)return;
|
||||
|
||||
// calculate the position bounds so we have a reliable epsilon to
|
||||
// check position differences against
|
||||
aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f);
|
||||
for( unsigned int a = 0; a < mesh->mNumVertices; a++)
|
||||
{
|
||||
minVec.x = std::min( minVec.x, mesh->mVertices[a].x);
|
||||
minVec.y = std::min( minVec.y, mesh->mVertices[a].y);
|
||||
minVec.z = std::min( minVec.z, mesh->mVertices[a].z);
|
||||
maxVec.x = std::max( maxVec.x, mesh->mVertices[a].x);
|
||||
maxVec.y = std::max( maxVec.y, mesh->mVertices[a].y);
|
||||
maxVec.z = std::max( maxVec.z, mesh->mVertices[a].z);
|
||||
}
|
||||
const float posEpsilon = (maxVec - minVec).Length() * 1e-5f;
|
||||
|
||||
// now generate the spatial sort tree
|
||||
SGSpatialSort sSort;
|
||||
std::vector<unsigned int>::const_iterator it = smoothingGroups.begin();
|
||||
for( begin = mesh->mFaces; begin != end; ++begin, ++it)
|
||||
{
|
||||
aiFace& face = *begin;
|
||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||
{
|
||||
register unsigned int tt = face.mIndices[i];
|
||||
sSort.Add(mesh->mVertices[tt],tt,*it);
|
||||
}
|
||||
}
|
||||
// sort everything - this takes O(logn) time
|
||||
sSort.Prepare();
|
||||
std::vector<unsigned int> poResult;poResult.reserve(20);
|
||||
|
||||
const float fLimit = cos(surface.mMaximumSmoothAngle);
|
||||
|
||||
// generate vertex normals. We have O(logn) for the binary lookup, which we need
|
||||
// for n elements, thus the EXPECTED complexity is O(nlogn)
|
||||
for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it)
|
||||
{
|
||||
register unsigned int sg = *it;
|
||||
|
||||
aiFace& face = *begin;
|
||||
unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
|
||||
for (; beginIdx != endIdx; ++beginIdx)
|
||||
{
|
||||
sSort.FindPositions(mesh->mVertices[*beginIdx],sg,posEpsilon,poResult,true);
|
||||
|
||||
aiVector3D vNormals;
|
||||
for (std::vector<unsigned int>::const_iterator
|
||||
a = poResult.begin(), end = poResult.end();
|
||||
a != end;++a)
|
||||
{
|
||||
const aiVector3D& v = faceNormals[*a];
|
||||
if (v * faceNormals[*beginIdx] < fLimit)continue;
|
||||
vNormals += v;
|
||||
}
|
||||
vNormals.Normalize();
|
||||
mesh->mNormals[*beginIdx] = vNormals;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::AddChildren(aiNode* node, uintptr_t parent, std::vector<aiNode*>& apcNodes)
|
||||
{
|
||||
unsigned int numChilds = 0;
|
||||
|
||||
for (uintptr_t i = 0; i < (uintptr_t)apcNodes.size();++i)
|
||||
{
|
||||
if (i == parent)continue;
|
||||
|
@ -454,57 +574,50 @@ void LWOImporter::ResolveTags()
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::ParseString(std::string& out,unsigned int max)
|
||||
void LWOImporter::ResolveClips()
|
||||
{
|
||||
// --- this function is used for both LWO2 and LWOB
|
||||
unsigned int iCursor = 0;
|
||||
const char* in = (const char*)mFileBuffer,*sz = in;
|
||||
while (*in)
|
||||
for( unsigned int i = 0; i < mClips.size();++i)
|
||||
{
|
||||
if (++iCursor > max)
|
||||
Clip& clip = mClips[i];
|
||||
if (Clip::REF == clip.type)
|
||||
{
|
||||
DefaultLogger::get()->warn("LWOB: Invalid file, string is is too long");
|
||||
break;
|
||||
if (clip.clipRef >= mClips.size())
|
||||
{
|
||||
DefaultLogger::get()->error("LWO2: Clip referrer index is out of range");
|
||||
clip.clipRef = 0;
|
||||
}
|
||||
Clip& dest = mClips[clip.clipRef];
|
||||
if (Clip::REF == dest.type)
|
||||
{
|
||||
DefaultLogger::get()->error("LWO2: Clip references another clip reference");
|
||||
clip.type = Clip::UNSUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
clip.path = dest.path;
|
||||
clip.type = dest.type;
|
||||
}
|
||||
}
|
||||
++in;
|
||||
}
|
||||
unsigned int len = (unsigned int) (in-sz);
|
||||
out = std::string(sz,len);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::AdjustTexturePath(std::string& out)
|
||||
{
|
||||
// --- this function is used for both LWO2 and LWOB
|
||||
if (::strstr(out.c_str(), "(sequence)"))
|
||||
if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)"))
|
||||
{
|
||||
// remove the (sequence) and append 000
|
||||
DefaultLogger::get()->info("LWO: Sequence of animated texture found. It will be ignored");
|
||||
DefaultLogger::get()->info("LWOB: Sequence of animated texture found. It will be ignored");
|
||||
out = out.substr(0,out.length()-10) + "000";
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int LWOImporter::ReadVSizedIntLWO2(uint8_t*& inout)
|
||||
{
|
||||
int i;
|
||||
int c = *inout;inout++;
|
||||
if(c != 0xFF)
|
||||
// format: drive:path/file - we need to insert a slash after the drive
|
||||
std::string::size_type n = out.find_first_of(':');
|
||||
if (std::string::npos != n)
|
||||
{
|
||||
i = c << 8;
|
||||
c = *inout;inout++;
|
||||
i |= c;
|
||||
out.insert(n+1,"/");
|
||||
}
|
||||
else
|
||||
{
|
||||
c = *inout;inout++;
|
||||
i = c << 16;
|
||||
c = *inout;inout++;
|
||||
i |= c << 8;
|
||||
c = *inout;inout++;
|
||||
i |= c;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -530,8 +643,20 @@ void LWOImporter::LoadLWOTags(unsigned int size)
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWOPoints(unsigned int length)
|
||||
{
|
||||
// --- this function is used for both LWO2 and LWOB
|
||||
mCurLayer->mTempPoints.resize( length / 12 );
|
||||
// --- this function is used for both LWO2 and LWOB but for
|
||||
// LWO2 we need to allocate 25% more storage - it could be we'll
|
||||
// need to duplicate some points later.
|
||||
register unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12;
|
||||
if (mIsLWO2)
|
||||
{
|
||||
mCurLayer->mTempPoints.reserve ( regularSize + (regularSize>>2u) );
|
||||
mCurLayer->mTempPoints.resize ( regularSize );
|
||||
|
||||
// initialize all point referrers with the default values
|
||||
mCurLayer->mPointReferrers.reserve ( regularSize + (regularSize>>2u) );
|
||||
mCurLayer->mPointReferrers.resize ( regularSize, 0xffffffff );
|
||||
}
|
||||
else mCurLayer->mTempPoints.resize( regularSize );
|
||||
|
||||
// perform endianess conversions
|
||||
#ifndef AI_BUILD_BIG_ENDIAN
|
||||
|
@ -544,17 +669,16 @@ void LWOImporter::LoadLWOPoints(unsigned int length)
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2Polygons(unsigned int length)
|
||||
{
|
||||
uint32_t type = *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer += 4;length-=4;
|
||||
AI_LSWAP4(type);
|
||||
LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
|
||||
uint32_t type = GetU4();
|
||||
|
||||
if (type != AI_LWO_FACE)
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: Only POLS.FACE chunsk are supported.");
|
||||
DefaultLogger::get()->warn("LWO2: Only POLS.FACE chunks are supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
// first find out how many faces and vertices we'll finally need
|
||||
LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
|
||||
LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
|
||||
|
||||
unsigned int iNumFaces = 0,iNumVertices = 0;
|
||||
|
@ -616,21 +740,22 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
|
||||
{
|
||||
uint32_t type = *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer+=4;
|
||||
AI_LSWAP4(type);
|
||||
LE_NCONST uint8_t* const end = mFileBuffer+length;
|
||||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(length,PTAG,4);
|
||||
uint32_t type = GetU4();
|
||||
|
||||
if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
|
||||
return;
|
||||
|
||||
LE_NCONST uint8_t* const end = mFileBuffer+length;
|
||||
while (mFileBuffer <= end)
|
||||
while (mFileBuffer < end)
|
||||
{
|
||||
unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
|
||||
unsigned int j = ReadVSizedIntLWO2(mFileBuffer);
|
||||
unsigned int j = GetU2();
|
||||
|
||||
if (i >= mCurLayer->mFaces.size())
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: face index in ptag list is out of range");
|
||||
DefaultLogger::get()->warn("LWO2: face index in PTAG is out of range");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -646,14 +771,88 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPoly)
|
||||
{
|
||||
for (typename std::vector< T >::iterator it = list.begin(), end = list.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
if ((*it).name == name)
|
||||
{
|
||||
if (!perPoly)
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: Found two VMAP sections with equal names");
|
||||
}
|
||||
return &(*it);
|
||||
}
|
||||
}
|
||||
list.push_back( T() );
|
||||
VMapEntry* p = &list.back();
|
||||
p->name = name;
|
||||
return p;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx)
|
||||
{
|
||||
for (typename std::vector< T >::iterator
|
||||
it = list.begin(), end = list.end();
|
||||
it != end;++it)
|
||||
{
|
||||
T& chan = *it;
|
||||
for (unsigned int a = 0; a < chan.dims;++a)
|
||||
{
|
||||
chan.rawData.push_back(chan.rawData[srcIdx*chan.dims+a]);
|
||||
chan.abAssigned[srcIdx] = true;
|
||||
chan.abAssigned.resize(chan.abAssigned.size()+1,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
|
||||
unsigned int idx, float* data)
|
||||
{
|
||||
ai_assert(NULL != data);
|
||||
LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
|
||||
unsigned int i;
|
||||
|
||||
base->abAssigned[idx] = true;
|
||||
for (i = 0; i < numRead;++i)
|
||||
base->rawData[idx*base->dims+i]= data[i];
|
||||
|
||||
if (0xffffffff != (i = refList[idx]))
|
||||
DoRecursiveVMAPAssignment(base,numRead,i,data);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, unsigned int destIdx)
|
||||
{
|
||||
if(0xffffffff == refList[srcIdx])
|
||||
{
|
||||
refList[srcIdx] = destIdx;
|
||||
return;
|
||||
}
|
||||
AddToSingleLinkedList(refList,refList[srcIdx],destIdx);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
|
||||
{
|
||||
unsigned int type = *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer+=4;
|
||||
unsigned int dims = *((LE_NCONST uint16_t*)mFileBuffer);mFileBuffer+=2;
|
||||
LE_NCONST uint8_t* const end = mFileBuffer+length;
|
||||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(length,VMAP,6);
|
||||
unsigned int type = GetU4();
|
||||
unsigned int dims = GetU2();
|
||||
|
||||
VMapEntry* base;
|
||||
|
||||
// read the name of the vertex map
|
||||
std::string name;
|
||||
GetS0(name,length);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AI_LWO_TXUV:
|
||||
|
@ -661,51 +860,139 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
|
|||
{
|
||||
DefaultLogger::get()->warn("LWO2: Found UV channel with != 2 components");
|
||||
}
|
||||
mCurLayer->mUVChannels.push_back(UVChannel((unsigned int)mCurLayer->mTempPoints.size()));
|
||||
base = &mCurLayer->mUVChannels.back();
|
||||
base = FindEntry(mCurLayer->mUVChannels,name,perPoly);
|
||||
break;
|
||||
case AI_LWO_WGHT:
|
||||
if (dims != 1)
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: found vertex weight map with != 1 components");
|
||||
}
|
||||
mCurLayer->mWeightChannels.push_back(WeightChannel((unsigned int)mCurLayer->mTempPoints.size()));
|
||||
base = &mCurLayer->mWeightChannels.back();
|
||||
base = FindEntry(mCurLayer->mWeightChannels,name,perPoly);
|
||||
break;
|
||||
case AI_LWO_RGB:
|
||||
case AI_LWO_RGBA:
|
||||
if (dims != 3 && dims != 4)
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: found vertex color map with != 3&4 components");
|
||||
}
|
||||
mCurLayer->mVColorChannels.push_back(VColorChannel((unsigned int)mCurLayer->mTempPoints.size()));
|
||||
base = &mCurLayer->mVColorChannels.back();
|
||||
base = FindEntry(mCurLayer->mVColorChannels,name,perPoly);
|
||||
break;
|
||||
default: return;
|
||||
};
|
||||
|
||||
// read the name of the vertex map
|
||||
ParseString(base->name,length);
|
||||
base->Allocate((unsigned int)mCurLayer->mTempPoints.size());
|
||||
|
||||
// now read all entries in the map
|
||||
type = std::min(dims,base->dims);
|
||||
const unsigned int diff = (dims - type)<<2;
|
||||
|
||||
LE_NCONST uint8_t* const end = mFileBuffer+length;
|
||||
LWO::FaceList& list = mCurLayer->mFaces;
|
||||
LWO::PointList& pointList = mCurLayer->mTempPoints;
|
||||
LWO::ReferrerList& refList = mCurLayer->mPointReferrers;
|
||||
|
||||
float temp[4];
|
||||
|
||||
while (mFileBuffer < end)
|
||||
{
|
||||
unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs;
|
||||
if (idx > mCurLayer->mTempPoints.size())
|
||||
if (idx >= pointList.size())
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: vertex index in vmap/vmad is out of range");
|
||||
continue;
|
||||
mFileBuffer += base->dims*4;continue;
|
||||
}
|
||||
for (unsigned int i = 0; i < type;++i)
|
||||
if (perPoly)
|
||||
{
|
||||
base->rawData[idx*dims+i]= *((float*)mFileBuffer);
|
||||
mFileBuffer += 4;
|
||||
unsigned int polyIdx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
|
||||
if (base->abAssigned[idx])
|
||||
{
|
||||
// we have already a VMAP entry for this vertex - thus
|
||||
// we need to duplicate the corresponding polygon.
|
||||
if (polyIdx >= list.size())
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: VMAD polygon index is out of range");
|
||||
mFileBuffer += base->dims*4;continue;
|
||||
}
|
||||
|
||||
LWO::Face& src = list[polyIdx];
|
||||
|
||||
// generate new vertex positions
|
||||
for (unsigned int i = 0; i < src.mNumIndices;++i)
|
||||
{
|
||||
register unsigned int srcIdx = src.mIndices[i];
|
||||
|
||||
// store the index of the new vertex in the old vertex
|
||||
// so we get a single linked list we can traverse in
|
||||
// only one direction
|
||||
refList.push_back(0xffffffff);
|
||||
AddToSingleLinkedList(refList,srcIdx,(src.mIndices[i] = (unsigned int)pointList.size()));
|
||||
pointList.push_back(pointList[srcIdx]);
|
||||
|
||||
CreateNewEntry(mCurLayer->mVColorChannels, srcIdx );
|
||||
CreateNewEntry(mCurLayer->mUVChannels, srcIdx );
|
||||
CreateNewEntry(mCurLayer->mWeightChannels, srcIdx );
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned int l = 0; l < type;++l)
|
||||
temp[l] = GetF4();
|
||||
|
||||
DoRecursiveVMAPAssignment(base,type,idx, temp);
|
||||
mFileBuffer += diff;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2Clip(unsigned int length)
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(length,CLIP,10);
|
||||
|
||||
mClips.push_back(LWO::Clip());
|
||||
LWO::Clip& clip = mClips.back();
|
||||
|
||||
// first - get the index of the clip
|
||||
clip.idx = GetU4();
|
||||
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
switch (head->type)
|
||||
{
|
||||
case AI_LWO_STIL:
|
||||
GetS0(clip.path,head->length);
|
||||
clip.type = Clip::STILL;
|
||||
break;
|
||||
|
||||
case AI_LWO_ISEQ:
|
||||
{
|
||||
uint8_t digits = GetU1(); mFileBuffer++;
|
||||
int16_t offset = GetU2(); mFileBuffer+=4;
|
||||
int16_t start = GetU2(); mFileBuffer+=4;
|
||||
|
||||
std::string s;std::stringstream ss;
|
||||
GetS0(s,head->length);head->length -= (unsigned int)s.length()+1;
|
||||
ss << s;
|
||||
ss << std::setw(digits) << offset + start;
|
||||
GetS0(s,head->length);
|
||||
ss << s;
|
||||
clip.path = ss.str();
|
||||
clip.type = Clip::SEQ;
|
||||
}
|
||||
break;
|
||||
|
||||
case AI_LWO_STCC:
|
||||
DefaultLogger::get()->warn("LWO2: Color shifted images are not supported");
|
||||
break;
|
||||
|
||||
case AI_LWO_ANIM:
|
||||
DefaultLogger::get()->warn("LWO2: Animated textures are not supported");
|
||||
break;
|
||||
|
||||
case AI_LWO_XREF:
|
||||
clip.type = Clip::REF;
|
||||
clip.clipRef = GetU4();
|
||||
break;
|
||||
|
||||
default:
|
||||
DefaultLogger::get()->warn("LWO2: Encountered unknown CLIP subchunk");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2File()
|
||||
|
@ -714,14 +1001,11 @@ void LWOImporter::LoadLWO2File()
|
|||
while (true)
|
||||
{
|
||||
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
|
||||
LE_NCONST IFF::ChunkHeader* const head = (LE_NCONST IFF::ChunkHeader*)mFileBuffer;
|
||||
AI_LSWAP4(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
mFileBuffer += sizeof(IFF::ChunkHeader);
|
||||
LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
{
|
||||
throw new ImportErrorException("LWOB: Invalid file, the size attribute of "
|
||||
"a chunk points behind the end of the file");
|
||||
throw new ImportErrorException("LWO2: Chunk length points behind the file");
|
||||
break;
|
||||
}
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||
|
@ -738,9 +1022,13 @@ void LWOImporter::LoadLWO2File()
|
|||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16);
|
||||
|
||||
// and parse its properties
|
||||
mFileBuffer += 16;
|
||||
ParseString(layer.mName,head->length-16);
|
||||
// and parse its properties, e.g. the pivot point
|
||||
mFileBuffer += 2;
|
||||
mCurLayer->mPivot.x = GetF4();
|
||||
mCurLayer->mPivot.y = GetF4();
|
||||
mCurLayer->mPivot.z = GetF4();
|
||||
mFileBuffer += 2;
|
||||
GetS0(layer.mName,head->length-16);
|
||||
|
||||
// if the name is empty, generate a default name
|
||||
if (layer.mName.empty())
|
||||
|
@ -751,7 +1039,7 @@ void LWOImporter::LoadLWO2File()
|
|||
}
|
||||
|
||||
if (mFileBuffer + 2 <= next)
|
||||
layer.mParent = *((uint16_t*)mFileBuffer);
|
||||
layer.mParent = GetU2();
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -765,11 +1053,17 @@ void LWOImporter::LoadLWO2File()
|
|||
break;
|
||||
}
|
||||
// vertex tags
|
||||
//case AI_LWO_VMAD:
|
||||
case AI_LWO_VMAD:
|
||||
if (mCurLayer->mFaces.empty())
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: Unexpected VMAD chunk");
|
||||
break;
|
||||
}
|
||||
// --- intentionally no break here
|
||||
case AI_LWO_VMAP:
|
||||
{
|
||||
if (mCurLayer->mTempPoints.empty())
|
||||
DefaultLogger::get()->warn("LWO2: Unexpected VMAD/VMAP chunk");
|
||||
DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
|
||||
else LoadLWO2VertexMap(head->length,head->type == AI_LWO_VMAD);
|
||||
break;
|
||||
}
|
||||
|
@ -804,6 +1098,13 @@ void LWOImporter::LoadLWO2File()
|
|||
LoadLWO2Surface(head->length);
|
||||
break;
|
||||
}
|
||||
|
||||
// clip chunk
|
||||
case AI_LWO_CLIP:
|
||||
{
|
||||
LoadLWO2Clip(head->length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
|
|
159
code/LWOLoader.h
159
code/LWOLoader.h
|
@ -43,9 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define AI_LWOLOADER_H_INCLUDED
|
||||
|
||||
#include "../include/aiTypes.h"
|
||||
#include "../include/DefaultLogger.h"
|
||||
|
||||
#include "BaseImporter.h"
|
||||
#include "LWOFileData.h"
|
||||
#include "BaseImporter.h"
|
||||
#include "MaterialSystem.h"
|
||||
|
||||
struct aiTexture;
|
||||
|
@ -63,6 +64,7 @@ using namespace LWO;
|
|||
* Methods named "xxx" are used to preprocess the loaded data -
|
||||
* they aren't specific to one format version, either
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
class LWOImporter : public BaseImporter
|
||||
{
|
||||
friend class Importer;
|
||||
|
@ -120,6 +122,17 @@ private:
|
|||
*/
|
||||
void LoadLWO2File();
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parsing functions used for all file format versions
|
||||
*/
|
||||
inline void GetS0(std::string& out,unsigned int max);
|
||||
inline float GetF4();
|
||||
inline uint32_t GetU4();
|
||||
inline uint16_t GetU2();
|
||||
inline uint8_t GetU1();
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a surface chunk from an LWOB file
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
|
@ -135,9 +148,18 @@ private:
|
|||
// -------------------------------------------------------------------
|
||||
/** Loads a texture block from a LWO2 file.
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
* @param type Type of the texture block - PROC, GRAD or IMAP
|
||||
* @param head Header of the SUF.BLOK header
|
||||
*/
|
||||
void LoadLWO2TextureBlock(uint32_t type, unsigned int size );
|
||||
void LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head,
|
||||
unsigned int size );
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads a shader block from a LWO2 file.
|
||||
* @param size Maximum size to be read, in bytes.
|
||||
* @param head Header of the SUF.BLOK header
|
||||
*/
|
||||
void LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head,
|
||||
unsigned int size );
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Loads an image map from a LWO2 file
|
||||
|
@ -183,6 +205,12 @@ private:
|
|||
*/
|
||||
void LoadLWOPoints(unsigned int length);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Load a clip from a CLIP chunk
|
||||
* @param length Size of the chunk
|
||||
*/
|
||||
void LoadLWO2Clip(unsigned int length);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Count vertices and faces in a LWOB/LWO2 file
|
||||
|
@ -206,6 +234,7 @@ private:
|
|||
LE_NCONST uint16_t*& cursor,
|
||||
const uint16_t* const end);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void CopyFaceIndicesLWOB(LWO::FaceList::iterator& it,
|
||||
LE_NCONST uint16_t*& cursor,
|
||||
const uint16_t* const end,
|
||||
|
@ -213,14 +242,27 @@ private:
|
|||
|
||||
// -------------------------------------------------------------------
|
||||
/** Resolve the tag and surface lists that have been loaded.
|
||||
* Generates the mMapping table.
|
||||
* Generates the mMapping table.
|
||||
*/
|
||||
void ResolveTags();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a string from the current file position
|
||||
/** Resolve the clip list that has been loaded.
|
||||
* Replaces clip references with real clips.
|
||||
*/
|
||||
void ParseString(std::string& out,unsigned int max);
|
||||
void ResolveClips();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Add a texture list to an output material description.
|
||||
*
|
||||
* @param pcMat Output material
|
||||
* @param in Input texture list
|
||||
* @param type Type identifier of the texture list. This is the string
|
||||
* that appears in the middle of all material keys - e.g. "diffuse",
|
||||
* "shininess", "glossiness" or "specular".
|
||||
*/
|
||||
bool HandleTextures(MaterialHelper* pcMat, const TextureList& in,
|
||||
const char* type);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Adjust a texture path
|
||||
|
@ -241,10 +283,15 @@ private:
|
|||
* @param out Output list. The members are indices into the
|
||||
* UV/VC channel lists of the layer
|
||||
*/
|
||||
void FindUVChannels(const LWO::Surface& surf,
|
||||
const LWO::Layer& layer,
|
||||
void FindUVChannels(/*const*/ LWO::Surface& surf,
|
||||
/*const*/ LWO::Layer& layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void FindUVChannels(LWO::TextureList& list, LWO::Layer& layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS], unsigned int& next);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
void FindVCChannels(const LWO::Surface& surf,
|
||||
const LWO::Layer& layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]);
|
||||
|
@ -271,6 +318,27 @@ private:
|
|||
*/
|
||||
int ReadVSizedIntLWO2(uint8_t*& inout);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Assign a value from a VMAP to a vertex and all vertices
|
||||
* attached to it.
|
||||
* @param base VMAP destination data
|
||||
* @param numRead Number of float's to be read
|
||||
* @param idx Absolute index of the first vertex
|
||||
* @param data Value of the VMAP to be assigned - read numRead
|
||||
* floats from this array.
|
||||
*/
|
||||
void DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
|
||||
unsigned int idx, float* data);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Compute normal vectors for a mesh
|
||||
* @param mesh Input mesh
|
||||
* @param smoothingGroups Smoothing-groups-per-face array
|
||||
* @param surface Surface for the mesh
|
||||
*/
|
||||
void ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups,
|
||||
const LWO::Surface& surface);
|
||||
|
||||
protected:
|
||||
|
||||
/** true if the file is a LWO2 file*/
|
||||
|
@ -305,6 +373,81 @@ protected:
|
|||
aiScene* pScene;
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline float LWOImporter::GetF4()
|
||||
{
|
||||
float f = *((float*)mFileBuffer);mFileBuffer += 4;
|
||||
AI_LSWAP4(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline uint32_t LWOImporter::GetU4()
|
||||
{
|
||||
uint32_t f = *((uint32_t*)mFileBuffer);mFileBuffer += 4;
|
||||
AI_LSWAP4(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline uint16_t LWOImporter::GetU2()
|
||||
{
|
||||
uint16_t f = *((uint16_t*)mFileBuffer);mFileBuffer += 2;
|
||||
AI_LSWAP2(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline uint8_t LWOImporter::GetU1()
|
||||
{
|
||||
return *mFileBuffer++;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline int LWOImporter::ReadVSizedIntLWO2(uint8_t*& inout)
|
||||
{
|
||||
int i;
|
||||
int c = *inout;inout++;
|
||||
if(c != 0xFF)
|
||||
{
|
||||
i = c << 8;
|
||||
c = *inout;inout++;
|
||||
i |= c;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = *inout;inout++;
|
||||
i = c << 16;
|
||||
c = *inout;inout++;
|
||||
i |= c << 8;
|
||||
c = *inout;inout++;
|
||||
i |= c;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline void LWOImporter::GetS0(std::string& out,unsigned int max)
|
||||
{
|
||||
unsigned int iCursor = 0;
|
||||
const char*sz = (const char*)mFileBuffer;
|
||||
while (*mFileBuffer)
|
||||
{
|
||||
if (++iCursor > max)
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO: Invalid file, string is is too long");
|
||||
break;
|
||||
}
|
||||
++mFileBuffer;
|
||||
}
|
||||
unsigned int len = (unsigned int) ((const char*)mFileBuffer-sz);
|
||||
out = std::string(sz,len);
|
||||
mFileBuffer += (len&0x1 ? 1 : 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_LWOIMPORTER_H_INCLUDED
|
||||
|
|
|
@ -58,6 +58,142 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
template <class T>
|
||||
T lerp(const T& one, const T& two, float val)
|
||||
{
|
||||
return one + (two-one)*val;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
|
||||
{
|
||||
switch (in)
|
||||
{
|
||||
case LWO::Texture::REPEAT:
|
||||
return aiTextureMapMode_Wrap;
|
||||
case LWO::Texture::MIRROR:
|
||||
return aiTextureMapMode_Mirror;
|
||||
case LWO::Texture::RESET:
|
||||
DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
|
||||
case LWO::Texture::EDGE:
|
||||
return aiTextureMapMode_Clamp;
|
||||
}
|
||||
return (aiTextureMapMode)0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, const char* type)
|
||||
{
|
||||
ai_assert(NULL != pcMat && NULL != type);
|
||||
|
||||
unsigned int cur = 0, temp = 0;
|
||||
char buffer[512];
|
||||
aiString s;
|
||||
bool ret = false;
|
||||
|
||||
for (TextureList::const_iterator it = in.begin(), end = in.end();
|
||||
it != end;++it)
|
||||
{
|
||||
if (!(*it).enabled || !(*it).bCanUse || 0xffffffff == (*it).mRealUVIndex)continue;
|
||||
ret = true;
|
||||
|
||||
// add the path to the texture
|
||||
sprintf(buffer,"$tex.file.%s[%i]",type,cur);
|
||||
|
||||
// The older LWOB format does not use indirect references to clips.
|
||||
// The file name of a texture is directly specified in the tex chunk.
|
||||
if (mIsLWO2)
|
||||
{
|
||||
// find the corresponding clip
|
||||
ClipList::iterator clip = mClips.begin();
|
||||
temp = (*it).mClipIdx;
|
||||
for (ClipList::iterator end = mClips.end(); clip != end; ++clip)
|
||||
{
|
||||
if ((*clip).idx == temp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mClips.end() == clip)
|
||||
{
|
||||
DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
|
||||
temp = 0;
|
||||
}
|
||||
if (Clip::UNSUPPORTED == (*clip).type)
|
||||
{
|
||||
DefaultLogger::get()->error("LWO2: Clip type is not supported");
|
||||
continue;
|
||||
}
|
||||
AdjustTexturePath((*clip).path);
|
||||
s.Set((*clip).path);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string ss = (*it).mFileName;
|
||||
if (!ss.length())
|
||||
{
|
||||
DefaultLogger::get()->error("LWOB: Empty file name");
|
||||
continue;
|
||||
}
|
||||
AdjustTexturePath(ss);
|
||||
s.Set(ss);
|
||||
}
|
||||
pcMat->AddProperty(&s,buffer);
|
||||
|
||||
// add the blend factor
|
||||
sprintf(buffer,"$tex.blend.%s[%i]",type,cur);
|
||||
pcMat->AddProperty(&(*it).mStrength,1,buffer);
|
||||
|
||||
// add the blend operation
|
||||
sprintf(buffer,"$tex.op.%s[%i]",type,cur);
|
||||
switch ((*it).blendType)
|
||||
{
|
||||
case LWO::Texture::Normal:
|
||||
case LWO::Texture::Multiply:
|
||||
temp = (unsigned int)aiTextureOp_Multiply;
|
||||
break;
|
||||
|
||||
case LWO::Texture::Subtractive:
|
||||
case LWO::Texture::Difference:
|
||||
temp = (unsigned int)aiTextureOp_Subtract;
|
||||
break;
|
||||
|
||||
case LWO::Texture::Divide:
|
||||
temp = (unsigned int)aiTextureOp_Divide;
|
||||
break;
|
||||
|
||||
case LWO::Texture::Additive:
|
||||
temp = (unsigned int)aiTextureOp_Add;
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = (unsigned int)aiTextureOp_Multiply;
|
||||
DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
|
||||
|
||||
}
|
||||
pcMat->AddProperty<int>((int*)&temp,1,buffer);
|
||||
|
||||
// add the UV source index
|
||||
sprintf(buffer,"$tex.uvw.%s[%i]",type,cur);
|
||||
temp = (*it).mRealUVIndex;
|
||||
pcMat->AddProperty<int>((int*)&temp,1,buffer);
|
||||
|
||||
// add the u-wrapping
|
||||
sprintf(buffer,"$tex.mapmodeu.%s[%i]",type,cur);
|
||||
temp = (unsigned int)GetMapMode((*it).wrapModeWidth);
|
||||
pcMat->AddProperty<int>((int*)&temp,1,buffer);
|
||||
|
||||
// add the v-wrapping
|
||||
sprintf(buffer,"$tex.mapmodev.%s[%i]",type,cur);
|
||||
temp = (unsigned int)GetMapMode((*it).wrapModeHeight);
|
||||
pcMat->AddProperty<int>((int*)&temp,1,buffer);
|
||||
|
||||
++cur;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat)
|
||||
{
|
||||
|
@ -68,13 +204,19 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
|
|||
|
||||
int i = surf.bDoubleSided ? 1 : 0;
|
||||
pcMat->AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
|
||||
|
||||
// add the refraction index and the bump intensity
|
||||
pcMat->AddProperty<float>(&surf.mIOR,1,AI_MATKEY_REFRACTI);
|
||||
pcMat->AddProperty<float>(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING);
|
||||
|
||||
aiShadingMode m;
|
||||
if (surf.mSpecularValue && surf.mGlossiness)
|
||||
{
|
||||
// this is only an assumption, needs to be confirmed.
|
||||
// the values have been tweaked by hand and seem to be correct.
|
||||
float fGloss;
|
||||
if (mIsLWO2)fGloss = surf.mGlossiness * 50.0f;
|
||||
if (mIsLWO2)
|
||||
{
|
||||
fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (16.0f >= surf.mGlossiness)fGloss = 6.0f;
|
||||
|
@ -85,18 +227,14 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
|
|||
|
||||
pcMat->AddProperty<float>(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
|
||||
pcMat->AddProperty<float>(&fGloss,1,AI_MATKEY_SHININESS);
|
||||
m = aiShadingMode_Phong;
|
||||
}
|
||||
|
||||
// (the diffuse value is just a scaling factor)
|
||||
aiColor3D clr = surf.mColor;
|
||||
clr.r *= surf.mDiffuseValue;
|
||||
clr.g *= surf.mDiffuseValue;
|
||||
clr.b *= surf.mDiffuseValue;
|
||||
pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||
else m = aiShadingMode_Gouraud;
|
||||
|
||||
// specular color
|
||||
clr.b = clr.g = clr.r = surf.mSpecularValue;
|
||||
aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights );
|
||||
pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_SPECULAR);
|
||||
pcMat->AddProperty<float>(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
|
||||
|
||||
// emissive color
|
||||
// (luminosity is not really the same but it affects the surface in
|
||||
|
@ -108,15 +246,113 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
|
|||
float f = 1.0f-surf.mTransparency;
|
||||
pcMat->AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
|
||||
|
||||
// now handle all textures ...
|
||||
// TODO
|
||||
// ADD TEXTURES to the material
|
||||
// TODO: find out how we can handle COLOR textures correctly...
|
||||
bool b = HandleTextures(pcMat,surf.mColorTextures,"diffuse");
|
||||
b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,"diffuse"));
|
||||
HandleTextures(pcMat,surf.mSpecularTextures,"specular");
|
||||
HandleTextures(pcMat,surf.mGlossinessTextures,"shininess");
|
||||
HandleTextures(pcMat,surf.mBumpTextures,"height");
|
||||
HandleTextures(pcMat,surf.mOpacityTextures,"opacity");
|
||||
|
||||
// now we need to know which shader we must use
|
||||
// iterate through the shader list of the surface and
|
||||
// search for a name we know
|
||||
for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();
|
||||
it != end;++it)
|
||||
{
|
||||
if (!(*it).enabled)continue;
|
||||
if ((*it).functionName == "LW_SuperCelShader" ||
|
||||
(*it).functionName == "AH_CelShader")
|
||||
{
|
||||
m = aiShadingMode_Toon;
|
||||
break;
|
||||
}
|
||||
else if ((*it).functionName == "LW_RealFresnel" ||
|
||||
(*it).functionName == "LW_FastFresnel")
|
||||
{
|
||||
m = aiShadingMode_Fresnel;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + (*it).functionName);
|
||||
}
|
||||
}
|
||||
if (surf.mMaximumSmoothAngle <= 0.0f)m = aiShadingMode_Flat;
|
||||
pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
|
||||
|
||||
// (the diffuse value is just a scaling factor)
|
||||
// If a diffuse texture is set, we set this value to 1.0
|
||||
clr = (b ? aiColor3D(1.f,1.f,1.f) : surf.mColor);
|
||||
clr.r *= surf.mDiffuseValue;
|
||||
clr.g *= surf.mDiffuseValue;
|
||||
clr.b *= surf.mDiffuseValue;
|
||||
pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::FindUVChannels(const LWO::Surface& surf, const LWO::Layer& layer,
|
||||
void LWOImporter::FindUVChannels(LWO::TextureList& list, LWO::Layer& layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS], unsigned int& next)
|
||||
{
|
||||
for (TextureList::iterator it = list.begin(), end = list.end();
|
||||
it != end;++it)
|
||||
{
|
||||
if (!(*it).enabled || !(*it).bCanUse || 0xffffffff != (*it).mRealUVIndex)continue;
|
||||
switch ((*it).mapMode)
|
||||
{
|
||||
// TODO: implement these special mappings ...
|
||||
case LWO::Texture::Spherical:
|
||||
case LWO::Texture::Cylindrical:
|
||||
case LWO::Texture::Cubic:
|
||||
case LWO::Texture::Planar:
|
||||
case LWO::Texture::FrontProjection:
|
||||
|
||||
DefaultLogger::get()->warn("LWO2: Only UV mapping is currently supported.");
|
||||
continue;
|
||||
|
||||
default: ;
|
||||
}
|
||||
for (unsigned int i = 0; i < layer.mUVChannels.size();++i)
|
||||
{
|
||||
if ((*it).mUVChannelIndex == layer.mUVChannels[i].name)
|
||||
{
|
||||
// check whether we have this channel already
|
||||
for (unsigned int m = 0; m < next;++m)
|
||||
{
|
||||
if (i == out[m])
|
||||
{
|
||||
(*it).mRealUVIndex = m;
|
||||
}
|
||||
}
|
||||
if (0xffffffff == (*it).mRealUVIndex)
|
||||
{
|
||||
(*it).mRealUVIndex = next;
|
||||
out[next++] = i;
|
||||
if (AI_MAX_NUMBER_OF_TEXTURECOORDS != next)
|
||||
out[next] = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0xffffffff == (*it).mRealUVIndex)
|
||||
DefaultLogger::get()->error("LWO2: Unable to find matching UV channel for a texture");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::FindUVChannels(LWO::Surface& surf, LWO::Layer& layer,
|
||||
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
|
||||
{
|
||||
out[0] = 0xffffffff;
|
||||
unsigned int next = 0;
|
||||
|
||||
FindUVChannels(surf.mColorTextures,layer,out,next);
|
||||
FindUVChannels(surf.mDiffuseTextures,layer,out,next);
|
||||
FindUVChannels(surf.mSpecularTextures,layer,out,next);
|
||||
FindUVChannels(surf.mGlossinessTextures,layer,out,next);
|
||||
FindUVChannels(surf.mOpacityTextures,layer,out,next);
|
||||
FindUVChannels(surf.mBumpTextures,layer,out,next);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -124,41 +360,240 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, const LWO::Layer& lay
|
|||
unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
|
||||
{
|
||||
out[0] = 0xffffffff;
|
||||
if (surf.mVCMap.length())
|
||||
{
|
||||
for (unsigned int i = 0; i < layer.mVColorChannels.size();++i)
|
||||
{
|
||||
if (surf.mVCMap == layer.mVColorChannels[i].name)
|
||||
{
|
||||
out[0] = i;
|
||||
out[1] = 0xffffffff;
|
||||
return;
|
||||
}
|
||||
}
|
||||
DefaultLogger::get()->warn("LWO2: Unable to find vertex color channel: " + surf.mVCMap);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
||||
{
|
||||
//LE_NCONST uint8_t* const end = mFileBuffer + size;
|
||||
LE_NCONST uint8_t* const end = mFileBuffer + size;
|
||||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
throw new ImportErrorException("LWO2: Invalid SURF.BLOCK chunk length");
|
||||
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
{
|
||||
case AI_LWO_PROJ:
|
||||
tex.wrapModeWidth = (Texture::Wrap)GetU2();
|
||||
tex.wrapModeHeight = (Texture::Wrap)GetU2();
|
||||
break;
|
||||
case AI_LWO_AXIS:
|
||||
tex.majorAxis = (Texture::Axes)GetU2();
|
||||
break;
|
||||
case AI_LWO_IMAG:
|
||||
tex.mClipIdx = GetU2();
|
||||
break;
|
||||
case AI_LWO_VMAP:
|
||||
GetS0(tex.mUVChannelIndex,head->length);
|
||||
break;
|
||||
case AI_LWO_WRPH:
|
||||
tex.wrapAmountH = GetF4();
|
||||
break;
|
||||
case AI_LWO_WRPW:
|
||||
tex.wrapAmountW = GetF4();
|
||||
break;
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2Procedural(unsigned int size, LWO::Texture& tex )
|
||||
{
|
||||
// --- not supported at the moment
|
||||
DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported");
|
||||
tex.bCanUse = false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2Gradient(unsigned int size, LWO::Texture& tex )
|
||||
{
|
||||
// --- not supported at the moment
|
||||
DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported");
|
||||
tex.bCanUse = false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
|
||||
{
|
||||
//LE_NCONST uint8_t* const end = mFileBuffer + size;
|
||||
LE_NCONST uint8_t* const end = mFileBuffer + size;
|
||||
|
||||
// get the ordinal string
|
||||
GetS0( tex.ordinal, size);
|
||||
|
||||
// we could crash later if this is an empty string ...
|
||||
if (!tex.ordinal.length())
|
||||
{
|
||||
DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
|
||||
tex.ordinal = "\x00";
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
throw new ImportErrorException("LWO2: Invalid texture header chunk length");
|
||||
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
{
|
||||
case AI_LWO_CHAN:
|
||||
tex.type = GetU4();
|
||||
break;
|
||||
case AI_LWO_ENAB:
|
||||
tex.enabled = GetU2() ? true : false;
|
||||
break;
|
||||
case AI_LWO_OPAC:
|
||||
tex.blendType = (Texture::BlendType)GetU2();
|
||||
tex.mStrength = GetF4();
|
||||
break;
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2TextureBlock(uint32_t type, unsigned int size )
|
||||
void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
|
||||
{
|
||||
//LE_NCONST uint8_t* const end = mFileBuffer + size;
|
||||
ai_assert(!mSurfaces->empty());
|
||||
LWO::Surface& surf = mSurfaces->back();
|
||||
LWO::Texture tex;
|
||||
|
||||
//LWO::Surface& surf = mSurfaces->back();
|
||||
//LWO::Texture tex;
|
||||
// load the texture header
|
||||
LoadLWO2TextureHeader(head->length,tex);
|
||||
size -= head->length + 6;
|
||||
|
||||
// now get the exact type of the texture
|
||||
switch (head->type)
|
||||
{
|
||||
case AI_LWO_PROC:
|
||||
LoadLWO2Procedural(size,tex);
|
||||
break;
|
||||
case AI_LWO_GRAD:
|
||||
LoadLWO2Gradient(size,tex);
|
||||
break;
|
||||
case AI_LWO_IMAP:
|
||||
LoadLWO2ImageMap(size,tex);
|
||||
}
|
||||
|
||||
// get the destination channel
|
||||
TextureList* listRef = NULL;
|
||||
switch (tex.type)
|
||||
{
|
||||
case AI_LWO_COLR:
|
||||
listRef = &surf.mColorTextures;break;
|
||||
case AI_LWO_DIFF:
|
||||
listRef = &surf.mDiffuseTextures;break;
|
||||
case AI_LWO_SPEC:
|
||||
listRef = &surf.mSpecularTextures;break;
|
||||
case AI_LWO_GLOS:
|
||||
listRef = &surf.mGlossinessTextures;break;
|
||||
case AI_LWO_BUMP:
|
||||
listRef = &surf.mBumpTextures;break;
|
||||
case AI_LWO_TRAN:
|
||||
listRef = &surf.mOpacityTextures;break;
|
||||
default:
|
||||
DefaultLogger::get()->warn("LWO2: Encountered unknown texture type");
|
||||
return;
|
||||
}
|
||||
|
||||
// now attach the texture to the parent surface - sort by ordinal string
|
||||
for (TextureList::iterator it = listRef->begin();
|
||||
it != listRef->end(); ++it)
|
||||
{
|
||||
if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0)
|
||||
{
|
||||
listRef->insert(it,tex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
listRef->push_back(tex);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
|
||||
{
|
||||
LE_NCONST uint8_t* const end = mFileBuffer + size;
|
||||
|
||||
ai_assert(!mSurfaces->empty());
|
||||
LWO::Surface& surf = mSurfaces->back();
|
||||
LWO::Shader shader;
|
||||
|
||||
// get the ordinal string
|
||||
GetS0( shader.ordinal, size);
|
||||
|
||||
// we could crash later if this is an empty string ...
|
||||
if (!shader.ordinal.length())
|
||||
{
|
||||
DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
|
||||
shader.ordinal = "\x00";
|
||||
}
|
||||
|
||||
// read the header
|
||||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
throw new ImportErrorException("LWO2: Invalid shader header chunk length");
|
||||
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
{
|
||||
case AI_LWO_ENAB:
|
||||
shader.enabled = GetU2() ? true : false;
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
|
||||
// process other subchunks ...
|
||||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
if (mFileBuffer + head->length > end)
|
||||
throw new ImportErrorException("LWO2: Invalid shader data chunk length");
|
||||
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
{
|
||||
case AI_LWO_FUNC:
|
||||
GetS0( shader.functionName, head->length );
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
|
||||
// now attach the shader to the parent surface - sort by ordinal string
|
||||
for (ShaderList::iterator it = surf.mShaders.begin();
|
||||
it != surf.mShaders.end(); ++it)
|
||||
{
|
||||
if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0)
|
||||
{
|
||||
surf.mShaders.insert(it,shader);
|
||||
return;
|
||||
}
|
||||
}
|
||||
surf.mShaders.push_back(shader);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -169,88 +604,131 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
mSurfaces->push_back( LWO::Surface () );
|
||||
LWO::Surface& surf = mSurfaces->back();
|
||||
|
||||
ParseString(surf.mName,size);
|
||||
mFileBuffer+=surf.mName.length()+1;
|
||||
// skip one byte if the length of the surface name is odd
|
||||
if (!(surf.mName.length() & 1))++mFileBuffer;
|
||||
mFileBuffer += 2;
|
||||
GetS0(surf.mName,size);
|
||||
|
||||
// check whether this surface was derived from any other surface
|
||||
std::string derived;
|
||||
GetS0(derived,(unsigned int)(end - mFileBuffer));
|
||||
if (derived.length())
|
||||
{
|
||||
|
||||
// yes, find this surface
|
||||
for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1;
|
||||
it != end; ++it)
|
||||
{
|
||||
if ((*it).mName == derived)
|
||||
{
|
||||
// we have it ...
|
||||
surf = *it;
|
||||
derived.clear();
|
||||
}
|
||||
}
|
||||
if (!derived.size())
|
||||
DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (mFileBuffer + 6 >= end)break;
|
||||
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
// no proper IFF header here - the chunk length is specified as int16
|
||||
uint32_t head_type = *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer+=4;
|
||||
uint16_t head_length = *((LE_NCONST uint16_t*)mFileBuffer);mFileBuffer+=2;
|
||||
AI_LSWAP4(head_type);
|
||||
AI_LSWAP2(head_length);
|
||||
if (mFileBuffer + head_length > end)
|
||||
{
|
||||
throw new ImportErrorException("LWO2: Invalid file, the size attribute of "
|
||||
"a surface sub chunk points behind the end of the file");
|
||||
}
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head_length;
|
||||
switch (head_type)
|
||||
if (mFileBuffer + head->length > end)
|
||||
throw new ImportErrorException("LWO2: Invalid surface chunk length");
|
||||
|
||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
{
|
||||
// diffuse color
|
||||
case AI_LWO_COLR:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,COLR,12);
|
||||
surf.mColor.r = ((float*)mFileBuffer)[0];
|
||||
surf.mColor.g = ((float*)mFileBuffer)[1];
|
||||
surf.mColor.b = ((float*)mFileBuffer)[2];
|
||||
AI_LSWAP4(surf.mColor.r);
|
||||
AI_LSWAP4(surf.mColor.g);
|
||||
AI_LSWAP4(surf.mColor.b);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12);
|
||||
surf.mColor.r = GetF4();
|
||||
surf.mColor.g = GetF4();
|
||||
surf.mColor.b = GetF4();
|
||||
break;
|
||||
}
|
||||
// diffuse strength ... hopefully
|
||||
case AI_LWO_DIFF:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,DIFF,4);
|
||||
surf.mDiffuseValue = *((float*)mFileBuffer);
|
||||
AI_LSWAP4(surf.mDiffuseValue);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4);
|
||||
surf.mDiffuseValue = GetF4();
|
||||
break;
|
||||
}
|
||||
// specular strength ... hopefully
|
||||
case AI_LWO_SPEC:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,SPEC,4);
|
||||
surf.mSpecularValue = *((float*)mFileBuffer);
|
||||
AI_LSWAP4(surf.mSpecularValue);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4);
|
||||
surf.mSpecularValue = GetF4();
|
||||
break;
|
||||
}
|
||||
// transparency
|
||||
case AI_LWO_TRAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TRAN,4);
|
||||
surf.mTransparency = *((float*)mFileBuffer);
|
||||
AI_LSWAP4(surf.mTransparency);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
|
||||
surf.mTransparency = GetF4();
|
||||
break;
|
||||
}
|
||||
// glossiness
|
||||
case AI_LWO_GLOS:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,GLOS,4);
|
||||
surf.mGlossiness = *((float*)mFileBuffer);
|
||||
AI_LSWAP4(surf.mGlossiness);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4);
|
||||
surf.mGlossiness = GetF4();
|
||||
break;
|
||||
}
|
||||
// bump intensity
|
||||
case AI_LWO_BUMP:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4);
|
||||
surf.mBumpIntensity = GetF4();
|
||||
break;
|
||||
}
|
||||
// color highlights
|
||||
case AI_LWO_CLRH:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4);
|
||||
surf.mColorHighlights = GetF4();
|
||||
break;
|
||||
}
|
||||
// index of refraction
|
||||
case AI_LWO_RIND:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4);
|
||||
surf.mIOR = GetF4();
|
||||
break;
|
||||
}
|
||||
// polygon sidedness
|
||||
case AI_LWO_SIDE:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2);
|
||||
surf.bDoubleSided = (3 == GetU2());
|
||||
break;
|
||||
}
|
||||
// maximum smoothing angle
|
||||
case AI_LWO_SMAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
|
||||
surf.mMaximumSmoothAngle = GetF4();
|
||||
break;
|
||||
}
|
||||
// surface bock entry
|
||||
case AI_LWO_BLOK:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,BLOK,4);
|
||||
uint32_t type = *((uint32_t*)mFileBuffer);
|
||||
AI_LSWAP4(type);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4);
|
||||
LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
switch (type)
|
||||
switch (head2->type)
|
||||
{
|
||||
case AI_LWO_IMAP:
|
||||
case AI_LWO_PROC:
|
||||
break;
|
||||
case AI_LWO_GRAD:
|
||||
mFileBuffer+=4;
|
||||
LoadLWO2TextureBlock(type,head_length-4);
|
||||
case AI_LWO_IMAP:
|
||||
LoadLWO2TextureBlock(head2, head->length);
|
||||
break;
|
||||
case AI_LWO_SHDR:
|
||||
LoadLWO2ShaderBlock(head2, head->length);
|
||||
break;
|
||||
|
||||
default:
|
||||
DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK");
|
||||
};
|
||||
|
||||
break;
|
||||
|
|
|
@ -226,7 +226,7 @@ void MDRImporter::InternReadFile(
|
|||
file->Read( &mBuffer2[0], 1, fileSize);
|
||||
mBuffer = &mBuffer2[0];
|
||||
|
||||
// validate the file header
|
||||
// validate the file header and do BigEndian byte swapping for all sub headers
|
||||
this->pcHeader = (BE_NCONST MDR::Header*)this->mBuffer;
|
||||
this->ValidateHeader();
|
||||
}
|
|
@ -83,9 +83,10 @@ void SGSpatialSort::Prepare()
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns an iterator for all positions close to the given position.
|
||||
void SGSpatialSort::FindPositions( const aiVector3D& pPosition,
|
||||
uint32_t pSG,
|
||||
float pRadius,
|
||||
std::vector<unsigned int>& poResults) const
|
||||
uint32_t pSG,
|
||||
float pRadius,
|
||||
std::vector<unsigned int>& poResults,
|
||||
bool exactMatch /*= false*/) const
|
||||
{
|
||||
float dist = pPosition * mPlaneNormal;
|
||||
float minDist = dist - pRadius, maxDist = dist + pRadius;
|
||||
|
@ -126,17 +127,44 @@ void SGSpatialSort::FindPositions( const aiVector3D& pPosition,
|
|||
// Add all positions inside the distance range within the given radius to the result aray
|
||||
|
||||
float squareEpsilon = pRadius * pRadius;
|
||||
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
|
||||
while( it->mDistance < maxDist)
|
||||
std::vector<Entry>::const_iterator it = mPositions.begin() + index;
|
||||
std::vector<Entry>::const_iterator end = mPositions.end();
|
||||
|
||||
if (exactMatch)
|
||||
{
|
||||
if((it->mPosition - pPosition).SquareLength() < squareEpsilon &&
|
||||
(it->mSmoothGroups & pSG || 0 == it->mSmoothGroups || 0 == pSG))
|
||||
while( it->mDistance < maxDist)
|
||||
{
|
||||
poResults.push_back( it->mIndex);
|
||||
if((it->mPosition - pPosition).SquareLength() < squareEpsilon && it->mSmoothGroups == pSG)
|
||||
{
|
||||
poResults.push_back( it->mIndex);
|
||||
}
|
||||
++it;
|
||||
if( end == it )break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the given smoothing group is 0, we'll return all surrounding vertices
|
||||
if (!pSG)
|
||||
{
|
||||
while( it->mDistance < maxDist)
|
||||
{
|
||||
if((it->mPosition - pPosition).SquareLength() < squareEpsilon)
|
||||
poResults.push_back( it->mIndex);
|
||||
++it;
|
||||
if( end == it)break;
|
||||
}
|
||||
}
|
||||
else while( it->mDistance < maxDist)
|
||||
{
|
||||
if((it->mPosition - pPosition).SquareLength() < squareEpsilon &&
|
||||
(it->mSmoothGroups & pSG || !it->mSmoothGroups))
|
||||
{
|
||||
poResults.push_back( it->mIndex);
|
||||
}
|
||||
++it;
|
||||
if( end == it)break;
|
||||
}
|
||||
++it;
|
||||
if( it == mPositions.end())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,13 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <vector>
|
||||
#include "../include/aiTypes.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Assimp {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------
|
||||
/** Specialized version of SpatialSort to support smoothing groups
|
||||
* This is used in the .3ds loader
|
||||
* This is used in by the 3DS, ASE and LWO loaders. 3DS and ASE share their
|
||||
* normal computation code in SmoothingGroups.inl, the LWO loader has its own
|
||||
* implementation to handle all details of its file format correctly.
|
||||
*/
|
||||
// ----------------------------------------------------------------------------------
|
||||
class SGSpatialSort
|
||||
{
|
||||
public:
|
||||
|
@ -60,7 +62,8 @@ public:
|
|||
SGSpatialSort();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Construction from a given face array, handling smoothing groups properly
|
||||
/** Construction from a given face array, handling smoothing groups
|
||||
* properly
|
||||
*/
|
||||
SGSpatialSort(const std::vector<aiVector3D>& vPositions);
|
||||
|
||||
|
@ -74,7 +77,7 @@ public:
|
|||
unsigned int smoothingGroup);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Prepare the spatial sorter for use
|
||||
/** Prepare the spatial sorter for use. This step runs in O(logn)
|
||||
*/
|
||||
void Prepare();
|
||||
|
||||
|
@ -85,27 +88,35 @@ public:
|
|||
/** Returns an iterator for all positions close to the given position.
|
||||
* @param pPosition The position to look for vertices.
|
||||
* @param pSG Only included vertices with at least one shared smooth group
|
||||
* @param pRadius Maximal distance from the position a vertex may have to be counted in.
|
||||
* @param poResults The container to store the indices of the found positions. Will be emptied
|
||||
* by the call so it may contain anything.
|
||||
* @param pRadius Maximal distance from the position a vertex may have
|
||||
* to be counted in.
|
||||
* @param poResults The container to store the indices of the found
|
||||
* positions. Will be emptied by the call so it may contain anything.
|
||||
* @param exactMatch Specifies whether smoothing groups are bit masks
|
||||
* (false) or integral values (true). In the latter case, a vertex
|
||||
* cannot belong to more than one smoothing group.
|
||||
* @return An iterator to iterate over all vertices in the given area.
|
||||
*/
|
||||
// -------------------------------------------------------------------
|
||||
void FindPositions( const aiVector3D& pPosition, uint32_t pSG,
|
||||
float pRadius, std::vector<unsigned int>& poResults) const;
|
||||
float pRadius, std::vector<unsigned int>& poResults,
|
||||
bool exactMatch = false) const;
|
||||
|
||||
protected:
|
||||
/** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
|
||||
aiVector3D mPlaneNormal;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** An entry in a spatially sorted position array. Consists of a vertex index,
|
||||
* its position and its precalculated distance from the reference plane */
|
||||
/** An entry in a spatially sorted position array. Consists of a
|
||||
* vertex index, its position and its precalculated distance from
|
||||
* the reference plane */
|
||||
// -------------------------------------------------------------------
|
||||
struct Entry
|
||||
{
|
||||
unsigned int mIndex; ///< The vertex referred by this entry
|
||||
aiVector3D mPosition; ///< Position
|
||||
unsigned int mIndex; ///< The vertex referred by this entry
|
||||
aiVector3D mPosition; ///< Position
|
||||
uint32_t mSmoothGroups;
|
||||
float mDistance; ///< Distance of this vertex to the sorting plane
|
||||
float mDistance; ///< Distance of this vertex to the sorting plane
|
||||
|
||||
Entry() { /** intentionally not initialized.*/ }
|
||||
Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance,uint32_t pSG)
|
||||
|
|
|
@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace Assimp {
|
||||
|
||||
// note - flip the face ordering
|
||||
// note - flip the face order
|
||||
#define ADD_TRIANGLE(n0,n1,n2) \
|
||||
positions.push_back(n2); \
|
||||
positions.push_back(n1); \
|
||||
|
@ -291,12 +291,13 @@ void StandardShapes::MakeCone(
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void StandardShapes::MakeCircle(
|
||||
aiVector3D& center,
|
||||
aiVector3D& normal,
|
||||
float radius,
|
||||
unsigned int tess,
|
||||
const aiVector3D& center,
|
||||
const aiVector3D& normal,
|
||||
float radius,
|
||||
unsigned int tess,
|
||||
std::vector<aiVector3D>& positions)
|
||||
{
|
||||
//aiVector3D current = aiVector3D ( normal.x,
|
||||
}
|
||||
|
||||
} // ! Assimp
|
||||
|
|
|
@ -146,7 +146,7 @@ public:
|
|||
* @param tess Number of triangles
|
||||
* @param positions Receives output triangles.
|
||||
*/
|
||||
static void MakeCircle(aiVector3D& center, aiVector3D& normal,
|
||||
static void MakeCircle(const aiVector3D& center, const aiVector3D& normal,
|
||||
float radius, unsigned int tess,
|
||||
std::vector<aiVector3D>& positions);
|
||||
|
||||
|
|
|
@ -197,7 +197,11 @@ enum aiShadingMode
|
|||
|
||||
/** No shading at all
|
||||
*/
|
||||
aiShadingMode_NoShading = 0x8
|
||||
aiShadingMode_NoShading = 0x9,
|
||||
|
||||
/** Fresnel shading
|
||||
*/
|
||||
aiShadingMode_Fresnel = 0xa
|
||||
};
|
||||
|
||||
|
||||
|
@ -242,6 +246,7 @@ struct aiMaterialProperty
|
|||
} // need to end extern C block to allow template member functions
|
||||
#endif
|
||||
|
||||
// supported texture types
|
||||
#define AI_TEXTYPE_OPACITY 0x0
|
||||
#define AI_TEXTYPE_SPECULAR 0x1
|
||||
#define AI_TEXTYPE_AMBIENT 0x2
|
||||
|
@ -250,6 +255,7 @@ struct aiMaterialProperty
|
|||
#define AI_TEXTYPE_NORMALS 0x5
|
||||
#define AI_TEXTYPE_SHININESS 0x6
|
||||
#define AI_TEXTYPE_DIFFUSE 0x7
|
||||
#define AI_TEXTYPE_GLOSSINESS 0x8
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Data structure for a material
|
||||
|
@ -339,7 +345,7 @@ extern "C" {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @def AI_BUILD_KEY
|
||||
* Builds a material texture key with a dynamic index.
|
||||
* Build a material texture key from an index that is not a compile-time constant.
|
||||
* Applications <b>could</b> do this (C-example):
|
||||
* @code
|
||||
* int i;
|
||||
|
@ -352,10 +358,10 @@ extern "C" {
|
|||
* @endcode
|
||||
* However, this is wrong because AI_MATKEY_TEXTURE_DIFFUSE() builds the key
|
||||
* string at <b>compile time</b>. <br>
|
||||
* Therefore, the dynamic indexing results in a
|
||||
* Therefore, the indexing results in a
|
||||
* material key like this : "$tex.file.diffuse[i]" - and it is not very
|
||||
* propable that there is a key with this name ... (except the programmer
|
||||
* of an ASSIMP loader has made the same mistake :-) ).<br>
|
||||
* of an ASSIMP loader has made the same fault :-) ).<br>
|
||||
* This is the right way:
|
||||
* @code
|
||||
* int i;
|
||||
|
@ -369,8 +375,8 @@ extern "C" {
|
|||
* }
|
||||
* @endcode
|
||||
* @param base Base material key. This is the same key you'd have used
|
||||
* normally with an underscore as suffix (e.g. AI_MATKEY_TEXTURE_DIFFUSE_)
|
||||
* @param index Index to be used. Here you may pass a variable!
|
||||
* normally with an extra underscore as suffix (e.g. AI_MATKEY_TEXTURE_DIFFUSE_)
|
||||
* @param index Index to be used.
|
||||
* @param out Array of chars to receive the output value. It must be
|
||||
* sufficiently large. This will be checked via a static assertion for
|
||||
* C++0x. For MSVC8 and later versions the security enhanced version of
|
||||
|
@ -469,6 +475,16 @@ extern "C" {
|
|||
*/
|
||||
#define AI_MATKEY_SHININESS_STRENGTH "$mat.shinpercent"
|
||||
|
||||
/** @def AI_MATKEY_REFRACTI
|
||||
* Index of refraction of the material. This is used by some shading models,
|
||||
* e.g. Cook-Torrance. The value is the ratio of the speed of light in a
|
||||
* vacuum to the speed of light in the material (always >= 1.0 in the real world).
|
||||
* <br>
|
||||
* <b>Type:</b> float<br>
|
||||
* <b>Default value:</b> 1.0f <br>
|
||||
*/
|
||||
#define AI_MATKEY_REFRACTI "$mat.refracti"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** @def AI_MATKEY_COLOR_DIFFUSE
|
||||
* Defines the diffuse base color of the material
|
||||
|
@ -586,8 +602,12 @@ extern "C" {
|
|||
#define AI_MATKEY_TEXTURE_HEIGHT_ "$tex.file.height"
|
||||
|
||||
/** @def AI_MATKEY_TEXTURE_SHININESS
|
||||
* Defines a specific shininess texture channel of the material
|
||||
* <br>
|
||||
* Defines a specific shininess texture channel of the material.
|
||||
* The shininess corresponds to the specular exponent used in the
|
||||
* phong lighting equation. However, it is undefined how the exponent
|
||||
* is encoded in the texture. A possible way would be the following:
|
||||
* pixel value c € (0,1), n = 2^(10c+2).
|
||||
* <br>
|
||||
* <b>Type:</b> string (aiString)<br>
|
||||
* <b>Default value:</b> none <br>
|
||||
* @note The key string is built at compile time, therefore it is not
|
||||
|
@ -598,6 +618,7 @@ extern "C" {
|
|||
#define AI_MATKEY_TEXTURE_SHININESS(N) "$tex.file.shininess["#N"]"
|
||||
#define AI_MATKEY_TEXTURE_SHININESS_ "$tex.file.shininess"
|
||||
|
||||
|
||||
/** @def AI_MATKEY_TEXTURE_OPACITY
|
||||
* Defines a specific opacity texture channel of the material
|
||||
* <br>
|
||||
|
@ -626,6 +647,7 @@ extern "C" {
|
|||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
#define AI_MATKEY_TEXOP_DIFFUSE(N) "$tex.op.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_TEXOP_DIFFUSE */
|
||||
#define AI_MATKEY_TEXOP_AMBIENT(N) "$tex.op.ambient["#N"]"
|
||||
|
@ -663,6 +685,7 @@ extern "C" {
|
|||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
#define AI_MATKEY_UVWSRC_DIFFUSE(N) "$tex.uvw.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_UVWSRC_DIFFUSE */
|
||||
#define AI_MATKEY_UVWSRC_AMBIENT(N) "$tex.uvw.ambient["#N"]"
|
||||
|
@ -700,6 +723,7 @@ extern "C" {
|
|||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
#define AI_MATKEY_TEXBLEND_DIFFUSE(N) "$tex.blend.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_TEXBLEND_DIFFUSE */
|
||||
#define AI_MATKEY_TEXBLEND_AMBIENT(N) "$tex.blend.ambient["#N"]"
|
||||
|
@ -738,6 +762,7 @@ extern "C" {
|
|||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
#define AI_MATKEY_MAPPINGMODE_U_DIFFUSE(N) "$tex.mapmodeu.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_MAPPINGMODE_U_DIFFUSE */
|
||||
#define AI_MATKEY_MAPPINGMODE_U_AMBIENT(N) "$tex.mapmodeu.ambient["#N"]"
|
||||
|
@ -776,6 +801,7 @@ extern "C" {
|
|||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
#define AI_MATKEY_MAPPINGMODE_V_DIFFUSE(N) "$tex.mapmodev.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_MAPPINGMODE_V_DIFFUSE */
|
||||
#define AI_MATKEY_MAPPINGMODE_V_AMBIENT(N) "$tex.mapmodev.ambient["#N"]"
|
||||
|
@ -814,6 +840,7 @@ extern "C" {
|
|||
* use the macro suffixed with '_' to build the key dynamically. The
|
||||
* AI_BUILD_KEY()-macro can be used to do this.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
#define AI_MATKEY_MAPPINGMODE_W_DIFFUSE(N) "$tex.mapmodew.diffuse["#N"]"
|
||||
/** @see AI_MATKEY_MAPPINGMODE_W_DIFFUSE */
|
||||
#define AI_MATKEY_MAPPINGMODE_W_AMBIENT(N) "$tex.mapmodew.ambient["#N"]"
|
||||
|
@ -841,7 +868,6 @@ extern "C" {
|
|||
|
||||
#define AI_MATKEY_ORENNAYAR_ROUGHNESS "$shading.orennayar.roughness"
|
||||
#define AI_MATKEY_MINNAERT_DARKNESS "$shading.minnaert.darkness"
|
||||
#define AI_MATKEY_COOK_TORRANCE_REFRACTI "$shading.cookt.refracti"
|
||||
#define AI_MATKEY_COOK_TORRANCE_PARAM "$shading.cookt.param"
|
||||
|
||||
/** @def AI_MATKEY_GLOBAL_BACKGROUND_IMAGE
|
||||
|
|
|
@ -107,6 +107,16 @@ struct aiColor3D
|
|||
bool operator != (const aiColor3D& other) const
|
||||
{return r != other.r || g != other.g || b != other.b;}
|
||||
|
||||
aiColor3D operator+(const aiColor3D& c) const
|
||||
{return aiColor3D(r+c.r,g+c.g,b+c.b);}
|
||||
aiColor3D operator-(const aiColor3D& c) const
|
||||
{return aiColor3D(r+c.r,g+c.g,b+c.b);}
|
||||
aiColor3D operator*(const aiColor3D& c) const
|
||||
{return aiColor3D(r*c.r,g*c.g,b*c.b);}
|
||||
|
||||
aiColor3D operator*(float f)
|
||||
{return aiColor3D(r*f,g*f,b*f);}
|
||||
|
||||
#endif // !__cplusplus
|
||||
|
||||
//! Red, green and blue color values
|
||||
|
|
|
@ -211,7 +211,7 @@ void JNIEnvironment::_assimp::_Mesh::Fill(jobject obj,const aiMesh* pcSrc)
|
|||
}
|
||||
|
||||
// copy bones
|
||||
if (0 < pcSrc->mNumBones)
|
||||
if (pcSrc->mNumBones)
|
||||
{
|
||||
// allocate the array
|
||||
jobjectArray jarr = pc->NewObjectArray(pcSrc->mNumBones,
|
||||
|
|
|
@ -71,17 +71,17 @@ public class BoneAnim {
|
|||
/**
|
||||
* Rotation keyframes
|
||||
*/
|
||||
private KeyFrame<Quaternion>[] mQuatKeys;
|
||||
private KeyFrame<Quaternion>[] mQuatKeys = null;
|
||||
|
||||
/**
|
||||
* Position keyframes. Component ordering is x,y,z
|
||||
* Position keyframes. Component order is x,y,z
|
||||
*/
|
||||
private KeyFrame<float[]>[] mPosKeys;
|
||||
private KeyFrame<float[]>[] mPosKeys = null;
|
||||
|
||||
/**
|
||||
* scaling keyframes. Component ordering is x,y,z
|
||||
* scaling keyframes. Component order is x,y,z
|
||||
*/
|
||||
private KeyFrame<float[]>[] mScalingKeys;
|
||||
private KeyFrame<float[]>[] mScalingKeys = null;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -196,8 +196,8 @@ public class Importer {
|
|||
* List of config properties for all supported types: int, float and string
|
||||
*/
|
||||
private PropertyList<Integer> properties = new PropertyList<Integer>();
|
||||
private PropertyList<Float> propertiesFloat = new PropertyList<Float>();
|
||||
private PropertyList<String> propertiesString = new PropertyList<String>();
|
||||
private PropertyList<Float> propertiesFloat = new PropertyList<Float>();
|
||||
private PropertyList<String> propertiesString = new PropertyList<String>();
|
||||
|
||||
|
||||
/**
|
||||
|
@ -221,7 +221,7 @@ public class Importer {
|
|||
* @param iVersion Version of the JNI interface to be used.
|
||||
* @throws NativeException Thrown if the jassimp library could not be loaded
|
||||
* or if the entry point to the module wasn't found. if this exception
|
||||
* is not thrown, you can assume that jAssimp is fully available.
|
||||
* is not thrown you can assume that jAssimp is fully available.
|
||||
*/
|
||||
public Importer(int iVersion) throws NativeException {
|
||||
|
||||
|
@ -390,12 +390,30 @@ public class Importer {
|
|||
throw new NativeException("Failed to load the mesh");
|
||||
}
|
||||
if (null == this.scene) {
|
||||
throw new NativeException("Failed to copy the data into the Java VM");
|
||||
throw new NativeException("Failed to copy the data to Java");
|
||||
}
|
||||
return this.scene;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current scene or <code>null</code> if none is loaded
|
||||
* @return Hello Amanda, I want to play a game ...
|
||||
*/
|
||||
public final Scene getScene() {
|
||||
return scene;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the source path of the current scene or <code>null</code> if none is loaded
|
||||
* @return Game Over.
|
||||
*/
|
||||
public final String getScenePath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of <code>java.lang.Object.equals()</code>
|
||||
*
|
||||
|
@ -555,6 +573,10 @@ public class Importer {
|
|||
}
|
||||
|
||||
|
||||
// *********************************************************************************
|
||||
// JNI INTERNALS
|
||||
// *********************************************************************************
|
||||
|
||||
/**
|
||||
* JNI bridge call. For internal use only
|
||||
* The method initializes the ASSIMP-JNI bridge for use. No native
|
||||
|
|
|
@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
package assimp;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class to wrap materials. Materials are represented in ASSIMP as a list of
|
||||
* key/value pairs, the key being a <code>String</code> and the value being
|
||||
|
@ -80,7 +79,8 @@ public class Material {
|
|||
|
||||
/**
|
||||
* Constructs a new exception
|
||||
* @param message Error message
|
||||
*
|
||||
* @param message Error message
|
||||
* @param property_key Name of the property that wasn't found
|
||||
*/
|
||||
public PropertyNotFoundException(String message, String property_key) {
|
||||
|
@ -92,27 +92,29 @@ public class Material {
|
|||
|
||||
/**
|
||||
* Get a property with a specific name as generic <code>Object</code>
|
||||
*
|
||||
* @param key MATKEY_XXX key constant
|
||||
* @return null if the property wasn't there or hasn't
|
||||
* the desired output type. The returned <code>Object</code> can be
|
||||
* casted to the expected data type for the property. Primitive
|
||||
* types are represented by their boxed variants.
|
||||
* @return null if the property wasn't there or hasn't
|
||||
* the desired output type. The returned <code>Object</code> can be
|
||||
* casted to the expected data type for the property. Primitive
|
||||
* types are represented by their boxed variants.
|
||||
*/
|
||||
public Object getProperty(String key) throws PropertyNotFoundException {
|
||||
|
||||
for (Property prop : properties) {
|
||||
if (prop.key.equals(key)){
|
||||
for (Property prop : properties) {
|
||||
if (prop.key.equals(key)) {
|
||||
return prop.value;
|
||||
}
|
||||
}
|
||||
throw new PropertyNotFoundException("Unable to find material property: ",key);
|
||||
throw new PropertyNotFoundException("Unable to find material property: ", key);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Get a material property as float array
|
||||
*
|
||||
* @param key MATKEY_XXX key constant
|
||||
* @throws PropertyNotFoundException - if the property can't be found
|
||||
* or if it has the wrong data type.
|
||||
* @throws PropertyNotFoundException - if the property can't be found
|
||||
* or if it has the wrong data type.
|
||||
*/
|
||||
public float[] getPropertyAsFloatArray(String key) throws PropertyNotFoundException {
|
||||
|
||||
|
@ -121,18 +123,19 @@ public class Material {
|
|||
return (float[]) obj;
|
||||
}
|
||||
String msg = "The data type requested (float[]) doesn't match the " +
|
||||
"real data type of the material property";
|
||||
"real data type of the material property";
|
||||
DefaultLogger.get().error(msg);
|
||||
throw new PropertyNotFoundException(msg,key);
|
||||
throw new PropertyNotFoundException(msg, key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Get a floating-point material property
|
||||
*
|
||||
* @param key MATKEY_XXX key constant
|
||||
* @return The value of the property.
|
||||
* @throws PropertyNotFoundException - if the property can't be found
|
||||
* or if it has the wrong data type.
|
||||
* @throws PropertyNotFoundException - if the property can't be found
|
||||
* or if it has the wrong data type.
|
||||
*/
|
||||
public float getPropertyAsFloat(String key) throws PropertyNotFoundException {
|
||||
|
||||
|
@ -141,18 +144,19 @@ public class Material {
|
|||
return (Float) obj;
|
||||
}
|
||||
String msg = "The data type requested (Float) doesn't match the " +
|
||||
"real data type of the material property";
|
||||
"real data type of the material property";
|
||||
DefaultLogger.get().error(msg);
|
||||
throw new PropertyNotFoundException(msg,key);
|
||||
throw new PropertyNotFoundException(msg, key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an integer material property
|
||||
*
|
||||
* @param key MATKEY_XXX key constant
|
||||
* @return The value of the property.
|
||||
* @throws PropertyNotFoundException - if the property can't be found
|
||||
* or if it has the wrong data type.
|
||||
* @throws PropertyNotFoundException - if the property can't be found
|
||||
* or if it has the wrong data type.
|
||||
*/
|
||||
public int getPropertyAsInt(String key) throws PropertyNotFoundException {
|
||||
|
||||
|
@ -161,18 +165,19 @@ public class Material {
|
|||
return (Integer) obj;
|
||||
}
|
||||
String msg = "The data type requested (Integer) doesn't match the " +
|
||||
"real data type of the material property";
|
||||
"real data type of the material property";
|
||||
DefaultLogger.get().error(msg);
|
||||
throw new PropertyNotFoundException(msg,key);
|
||||
throw new PropertyNotFoundException(msg, key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a material property string
|
||||
*
|
||||
* @param key MATKEY_XXX key constant
|
||||
* @return The value of the property.
|
||||
* @throws PropertyNotFoundException - if the property can't be found
|
||||
* or if it has the wrong data type.
|
||||
* @throws PropertyNotFoundException - if the property can't be found
|
||||
* or if it has the wrong data type.
|
||||
*/
|
||||
public String getPropertyAsString(String key) throws PropertyNotFoundException {
|
||||
|
||||
|
@ -181,9 +186,9 @@ public class Material {
|
|||
return (String) obj;
|
||||
}
|
||||
String msg = "The data type requested (java.lang.String) doesn't match the " +
|
||||
"real data type of the material property";
|
||||
"real data type of the material property";
|
||||
DefaultLogger.get().error(msg);
|
||||
throw new PropertyNotFoundException(msg,key);
|
||||
throw new PropertyNotFoundException(msg, key);
|
||||
}
|
||||
|
||||
|
||||
|
@ -228,7 +233,9 @@ public class Material {
|
|||
* <br>
|
||||
* <b>Type:</b> int (TextureOp)<br>
|
||||
* <b>Default value:</b> 0<br>
|
||||
* <b>Requires:</b> MATKEY_TEXTURE_DIFFUSE(0)<br>
|
||||
* <b>Requires:</b> MATKEY_TEXTURE_DIFFUSE(N)<br>
|
||||
*
|
||||
* @param N Index of the texture
|
||||
*/
|
||||
public static String MATKEY_TEXOP_DIFFUSE(int N) {
|
||||
return "$tex.op.diffuse[" + N + "]";
|
||||
|
@ -284,5 +291,320 @@ public class Material {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the blend factor to be multiplied with the value of
|
||||
* the n'th texture layer before it is combined with the previous
|
||||
* layer using a specific blend operation.
|
||||
* <p/>
|
||||
* <br>
|
||||
* <b>Type:</b> float<br>
|
||||
* <b>Default value:</b> 1.0f<br>
|
||||
* <b>Requires:</b> MATKEY_TEXTURE_DIFFUSE(N)<br>
|
||||
*
|
||||
* @param N Index of the texture
|
||||
*/
|
||||
public static String MATKEY_TEXBLEND_DIFFUSE(int N) {
|
||||
return "$tex.blend.diffuse[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_TEXBLEND_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_TEXBLEND_SPECULAR(int N) {
|
||||
return "$tex.blend.specular[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_TEXBLEND_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_TEXBLEND_AMBIENT(int N) {
|
||||
return "$tex.blend.ambient[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_TEXBLEND_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_TEXBLEND_EMISSIVE(int N) {
|
||||
return "$tex.blend.emissive[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_TEXBLEND_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_TEXBLEND_SHININESS(int N) {
|
||||
return "$tex.blend.shininess[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_TEXBLEND_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_TEXBLEND_OPACITY(int N) {
|
||||
return "$tex.blend.opacity[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_TEXBLEND_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_TEXBLEND_HEIGHT(int N) {
|
||||
return "$tex.blend.height[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_TEXBLEND_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_TEXBLEND_NORMALS(int N) {
|
||||
return "$tex.blend.normals[" + N + "]";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the index of the UV channel to be used for a texture
|
||||
* <br>
|
||||
* <b>Type:</b>int<br>
|
||||
* <b>Default value:</b>0<br>
|
||||
* <b>Requires:</b> MATKEY_TEXTURE_DIFFUSE(N)<br>
|
||||
*
|
||||
* @param N Index of the texture
|
||||
*/
|
||||
public static String MATKEY_UVWSRC_DIFFUSE(int N) {
|
||||
return "$tex.uvw.diffuse[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_UVWSRC_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_UVWSRC_SPECULAR(int N) {
|
||||
return "$tex.uvw.specular[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_UVWSRC_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_UVWSRC_AMBIENT(int N) {
|
||||
return "$tex.uvw.ambient[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_UVWSRC_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_UVWSRC_EMISSIVE(int N) {
|
||||
return "$tex.uvw.emissive[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_UVWSRC_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_UVWSRC_SHININESS(int N) {
|
||||
return "$tex.uvw.shininess[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_UVWSRC_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_UVWSRC_OPACITY(int N) {
|
||||
return "$tex.uvw.opacity[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_UVWSRC_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_UVWSRC_HEIGHT(int N) {
|
||||
return "$tex.uvw.height[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_UVWSRC_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_UVWSRC_NORMALS(int N) {
|
||||
return "$tex.uvw.normals[" + N + "]";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the texture mapping mode in the v (y) direction.
|
||||
* <br>
|
||||
* <b>Type:</b>int<br>
|
||||
* <b>Default value:</b>TextureMapMode.Wrap<br>
|
||||
* <b>Requires:</b> MATKEY_TEXTURE_DIFFUSE(N)<br>
|
||||
*
|
||||
* @param N Index of the texture
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_U_DIFFUSE(int N) {
|
||||
return "$tex.mapmodeu.diffuse[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_U_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_U_SPECULAR(int N) {
|
||||
return "$tex.mapmodeu.specular[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_U_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_U_AMBIENT(int N) {
|
||||
return "$tex.mapmodeu.ambient[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_U_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_U_EMISSIVE(int N) {
|
||||
return "$tex.mapmodeu.emissive[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_U_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_U_SHININESS(int N) {
|
||||
return "$tex.mapmodeu.shininess[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_U_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_U_OPACITY(int N) {
|
||||
return "$tex.mapmodeu.opacity[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_U_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_U_HEIGHT(int N) {
|
||||
return "$tex.mapmodeu.height[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_U_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_U_NORMALS(int N) {
|
||||
return "$tex.mapmodeu.normals[" + N + "]";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the texture mapping mode in the v (y) direction.
|
||||
* <br>
|
||||
* <b>Type:</b>int<br>
|
||||
* <b>Default value:</b>TextureMapMode.Wrap<br>
|
||||
* <b>Requires:</b> MATKEY_TEXTURE_DIFFUSE(N)<br>
|
||||
*
|
||||
* @param N Index of the texture
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_V_DIFFUSE(int N) {
|
||||
return "$tex.mapmodev.diffuse[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_V_SPECULAR(int N) {
|
||||
return "$tex.mapmodev.specular[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_V_AMBIENT(int N) {
|
||||
return "$tex.mapmodev.ambient[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_V_EMISSIVE(int N) {
|
||||
return "$tex.mapmodev.emissive[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_V_SHININESS(int N) {
|
||||
return "$tex.mapmodev.shininess[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_V_OPACITY(int N) {
|
||||
return "$tex.mapmodev.opacity[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_V_HEIGHT(int N) {
|
||||
return "$tex.mapmodev.height[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_V_NORMALS(int N) {
|
||||
return "$tex.mapmodev.normals[" + N + "]";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the texture mapping mode in the w (z) direction.
|
||||
* <br>
|
||||
* <b>Type:</b>int<br>
|
||||
* <b>Default value:</b>TextureMapMode.Wrap<br>
|
||||
* <b>Requires:</b> MATKEY_TEXTURE_DIFFUSE(N)<br>
|
||||
*
|
||||
* @param N Index of the texture
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_W_DIFFUSE(int N) {
|
||||
return "$tex.mapmodew.diffuse[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_W_SPECULAR(int N) {
|
||||
return "$tex.mapmodew.specular[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_W_AMBIENT(int N) {
|
||||
return "$tex.mapmodew.ambient[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_W_EMISSIVE(int N) {
|
||||
return "$tex.mapmodew.emissive[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_W_SHININESS(int N) {
|
||||
return "$tex.mapmodew.shininess[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_W_OPACITY(int N) {
|
||||
return "$tex.mapmodew.opacity[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_W_HEIGHT(int N) {
|
||||
return "$tex.mapmodew.height[" + N + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <code>MATKEY_MAPPINGMODE_V_DIFFUSE</code>
|
||||
*/
|
||||
public static String MATKEY_MAPPINGMODE_W_NORMALS(int N) {
|
||||
return "$tex.mapmodew.normals[" + N + "]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ package assimp;
|
|||
/**
|
||||
* Enumeration class that defines postprocess steps that can be executed on a model
|
||||
* after it has been loaded. All PPSteps are implemented in C++, so their performance
|
||||
* is awesome. Most steps are O(n * log(n)). ;-)
|
||||
* is awesome :-) (*duck*)
|
||||
*
|
||||
* @author Aramis (Alexander Gessler)
|
||||
* @version 1.0
|
||||
|
@ -186,54 +186,58 @@ public class PostProcessStep {
|
|||
new PostProcessStep("ValidateDataStructure");
|
||||
|
||||
|
||||
/** Reorders triangles for vertex cache locality and thus better performance.
|
||||
* The step tries to improve the ACMR (average post-transform vertex cache
|
||||
* miss ratio) for all meshes. The step runs in O(n) and is roughly
|
||||
* basing on the algorithm described in this paper:
|
||||
* <url>http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf</url>
|
||||
*/
|
||||
public static final PostProcessStep ImproveVertexLocality =
|
||||
/**
|
||||
* Reorders triangles for vertex cache locality and thus better performance.
|
||||
* The step tries to improve the ACMR (average post-transform vertex cache
|
||||
* miss ratio) for all meshes. The step runs in O(n) and is roughly
|
||||
* basing on the algorithm described in this paper:
|
||||
* <url>http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf</url>
|
||||
*/
|
||||
public static final PostProcessStep ImproveVertexLocality =
|
||||
new PostProcessStep("ImproveVertexLocality");
|
||||
|
||||
|
||||
/** Searches for redundant materials and removes them.
|
||||
*
|
||||
* This is especially useful in combination with the PretransformVertices
|
||||
* and OptimizeGraph steps. Both steps join small meshes, but they
|
||||
* can't do that if two meshes have different materials.
|
||||
*/
|
||||
public static final PostProcessStep RemoveRedundantMaterials =
|
||||
/**
|
||||
* Searches for redundant materials and removes them.
|
||||
* <p/>
|
||||
* This is especially useful in combination with the PretransformVertices
|
||||
* and OptimizeGraph steps. Both steps join small meshes, but they
|
||||
* can't do that if two meshes have different materials.
|
||||
*/
|
||||
public static final PostProcessStep RemoveRedundantMaterials =
|
||||
new PostProcessStep("RemoveRedundantMaterials");
|
||||
|
||||
/** This step tries to determine which meshes have normal vectors
|
||||
* that are facing inwards. The algorithm is simple but effective:
|
||||
* the bounding box of all vertices + their normals is compared against
|
||||
* the volume of the bounding box of all vertices without their normals.
|
||||
* This works well for most objects, problems might occur with planar
|
||||
* surfaces. However, the step tries to filter such cases.
|
||||
* The step inverts all infacing normals. Generally it is recommended
|
||||
* to enable this step, although the result is not always correct.
|
||||
*/
|
||||
public static final PostProcessStep FixInfacingNormals =
|
||||
/**
|
||||
* This step tries to determine which meshes have normal vectors
|
||||
* that are facing inwards. The algorithm is simple but effective:
|
||||
* the bounding box of all vertices + their normals is compared against
|
||||
* the volume of the bounding box of all vertices without their normals.
|
||||
* This works well for most objects, problems might occur with planar
|
||||
* surfaces. However, the step tries to filter such cases.
|
||||
* The step inverts all infacing normals. Generally it is recommended
|
||||
* to enable this step, although the result is not always correct.
|
||||
*/
|
||||
public static final PostProcessStep FixInfacingNormals =
|
||||
new PostProcessStep("FixInfacingNormals");
|
||||
|
||||
/** This step performs some optimizations on the node graph.
|
||||
*
|
||||
* It is incompatible to the PreTransformVertices-Step. Some configuration
|
||||
* options exist, see aiConfig.h for more details.
|
||||
* Generally, two actions are available:<br>
|
||||
* 1. Remove animation nodes and data from the scene. This allows other
|
||||
* steps for further optimizations.<br>
|
||||
* 2. Combine very small meshes to larger ones. Only if the meshes
|
||||
* are used by the same node or by nodes on the same hierarchy (with
|
||||
* equal local transformations). Unlike PreTransformVertices, the
|
||||
* OptimizeGraph-step doesn't transform vertices from one space
|
||||
* another.<br>
|
||||
* 3. Remove hierarchy levels<br>
|
||||
*
|
||||
* It is recommended to have this step run with the default configuration.
|
||||
*/
|
||||
public static final PostProcessStep OptimizeGraph =
|
||||
/**
|
||||
* This step performs some optimizations on the node graph.
|
||||
* <p/>
|
||||
* It is incompatible to the PreTransformVertices-Step. Some configuration
|
||||
* options exist, see aiConfig.h for more details.
|
||||
* Generally, two actions are available:<br>
|
||||
* 1. Remove animation nodes and data from the scene. This allows other
|
||||
* steps for further optimizations.<br>
|
||||
* 2. Combine very small meshes to larger ones. Only if the meshes
|
||||
* are used by the same node or by nodes on the same hierarchy (with
|
||||
* equal local transformations). Unlike PreTransformVertices, the
|
||||
* OptimizeGraph-step doesn't transform vertices from one space
|
||||
* another.<br>
|
||||
* 3. Remove hierarchy levels<br>
|
||||
* <p/>
|
||||
* It is recommended to have this step run with the default configuration.
|
||||
*/
|
||||
public static final PostProcessStep OptimizeGraph =
|
||||
new PostProcessStep("OptimizeGraph");
|
||||
|
||||
private final String myName; // for debug only
|
||||
|
|
|
@ -42,11 +42,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
package assimp;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Alex
|
||||
* Date: 08.06.2008
|
||||
* Time: 17:27:11
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* Defines how texture coordinates ! ElemOf [0 ... 1] are handled.
|
||||
*
|
||||
* This corresponds to the native <code>aiTextureMapMode</code> enum.
|
||||
*
|
||||
* @author Alexander Gessler (Aramis)
|
||||
*/
|
||||
public class TextureMapMode {
|
||||
|
||||
/** A texture coordinate u|v is translated to u%1|v%1
|
||||
*/
|
||||
public static final int Wrap = 0x0;
|
||||
|
||||
/** Texture coordinates outside the area formed by 1|1 and 0|0
|
||||
* are clamped to the nearest valid value on an axis
|
||||
*/
|
||||
public static final int Clamp = 0x1;
|
||||
|
||||
/** A texture coordinate u|v becomes u%1|v%1 if (u-(u%1))%2 is zero and
|
||||
* 1-(u%1)|1-(v%1) otherwise
|
||||
*/
|
||||
public static final int Mirror = 0x2;
|
||||
}
|
||||
|
|
|
@ -45,8 +45,14 @@ package assimp.test;
|
|||
import assimp.*;
|
||||
|
||||
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -115,10 +121,34 @@ public class DumpToFile {
|
|||
*
|
||||
* @param texture Texture to be exported
|
||||
* @param path Output path
|
||||
* @throws IOException yes ... sometimes ... :-)
|
||||
*/
|
||||
public static void SaveTextureToTGA(Texture texture, String path) throws IOException {
|
||||
public static void SaveTextureToTGA(Texture texture, String path) {
|
||||
BufferedImage bImg = texture.convertToImage();
|
||||
|
||||
Iterator writers = ImageIO.getImageWritersBySuffix("tga");
|
||||
if (!(writers.hasNext())) {
|
||||
System.out.println("No writer for TGA file format available");
|
||||
return;
|
||||
}
|
||||
ImageWriter w = (ImageWriter) (writers.next());
|
||||
if (w == null) {
|
||||
System.out.println("No writer for TGA file format available");
|
||||
return;
|
||||
}
|
||||
File fo = new File(path);
|
||||
|
||||
try {
|
||||
|
||||
ImageOutputStream ios = ImageIO.createImageOutputStream(fo);
|
||||
w.setOutput(ios);
|
||||
w.write(bImg);
|
||||
|
||||
}
|
||||
catch (IOException ex) {
|
||||
System.out.println("Failed to write " + path);
|
||||
return;
|
||||
}
|
||||
System.out.println(path + " has been written");
|
||||
}
|
||||
|
||||
|
||||
|
@ -390,7 +420,7 @@ public class DumpToFile {
|
|||
|
||||
String path = arguments[1].substring(0, arguments[1].length() - 4) + "_tex" + i++ + ".tga";
|
||||
stream.write("Emb. Texture\n" +
|
||||
"\tExportPath: " + path + "\n\n");
|
||||
"\tExportPath: " + path + "\n\n");
|
||||
|
||||
SaveTextureToTGA(texture, path);
|
||||
}
|
||||
|
@ -399,7 +429,6 @@ public class DumpToFile {
|
|||
/* Now print all materials
|
||||
*/
|
||||
|
||||
|
||||
// close the stream again
|
||||
stream.close();
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 469 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -36,9 +36,9 @@
|
|||
<entry_points />
|
||||
</component>
|
||||
<component name="ExportToHTMLSettings">
|
||||
<option name="PRINT_LINE_NUMBERS" value="false" />
|
||||
<option name="OPEN_IN_BROWSER" value="false" />
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
<option name="PRINT_LINE_NUMBERS" value="true" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
<option name="OUTPUT_DIRECTORY" value="J:\Programmieren\ASSIMP\assimp3\trunk\workspaces\jidea5.1\exportToHTML" />
|
||||
</component>
|
||||
<component name="GUI Designer component loader factory" />
|
||||
<component name="JavacSettings">
|
||||
|
@ -49,7 +49,7 @@
|
|||
<option name="MAXIMUM_HEAP_SIZE" value="128" />
|
||||
</component>
|
||||
<component name="JavadocGenerationManager">
|
||||
<option name="OUTPUT_DIRECTORY" value="J:/Programmieren/ASSIMP3/assimp/doc/javadoc" />
|
||||
<option name="OUTPUT_DIRECTORY" value="J:/Programmieren/ASSIMP/assimp3/doc/javadoc" />
|
||||
<option name="OPTION_SCOPE" value="protected" />
|
||||
<option name="OPTION_HIERARCHY" value="true" />
|
||||
<option name="OPTION_NAVIGATOR" value="true" />
|
||||
|
|
|
@ -1132,6 +1132,10 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="AC"
|
||||
>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
@ -1468,6 +1472,10 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="AC"
|
||||
>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
|
Loading…
Reference in New Issue