Next WIP version of the LWO loader. LWO2 is still unfinished and crashes every time.
Added NFF test model. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@123 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
d38e83766b
commit
af18307f95
|
@ -0,0 +1,308 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (ASSIMP)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2008, ASSIMP Development Team
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the following
|
||||||
|
conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the ASSIMP team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the ASSIMP Development Team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file Implementation of the LWO importer class for the older LWOB
|
||||||
|
file formats, including materials */
|
||||||
|
|
||||||
|
// internal headers
|
||||||
|
#include "LWOLoader.h"
|
||||||
|
#include "MaterialSystem.h"
|
||||||
|
#include "ByteSwap.h"
|
||||||
|
|
||||||
|
// public assimp headers
|
||||||
|
#include "../include/aiScene.h"
|
||||||
|
#include "../include/aiAssert.h"
|
||||||
|
#include "../include/DefaultLogger.h"
|
||||||
|
#include "../include/assimp.hpp"
|
||||||
|
|
||||||
|
using namespace Assimp;
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::LoadLWOBFile()
|
||||||
|
{
|
||||||
|
LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
|
||||||
|
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);
|
||||||
|
if (mFileBuffer + head->length > end)
|
||||||
|
{
|
||||||
|
throw new ImportErrorException("LWOB: Invalid file, the size attribute of "
|
||||||
|
"a chunk points behind the end of the file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
||||||
|
switch (head->type)
|
||||||
|
{
|
||||||
|
// vertex list
|
||||||
|
case AI_LWO_PNTS:
|
||||||
|
{
|
||||||
|
if (!mCurLayer->mTempPoints.empty())
|
||||||
|
DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
|
||||||
|
else LoadLWOPoints(head->length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// face list
|
||||||
|
case AI_LWO_POLS:
|
||||||
|
{
|
||||||
|
if (!mCurLayer->mFaces.empty())
|
||||||
|
DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
|
||||||
|
else LoadLWOPolygons(head->length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// list of tags
|
||||||
|
case AI_LWO_SRFS:
|
||||||
|
{
|
||||||
|
if (!mTags->empty())
|
||||||
|
DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
|
||||||
|
else LoadLWOTags(head->length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// surface chunk
|
||||||
|
case AI_LWO_SURF:
|
||||||
|
{
|
||||||
|
if (!mSurfaces->empty())
|
||||||
|
DefaultLogger::get()->warn("LWO: SURF chunk encountered twice");
|
||||||
|
else LoadLWOBSurface(head->length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mFileBuffer = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces,
|
||||||
|
LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
|
||||||
|
{
|
||||||
|
while (cursor < end && max--)
|
||||||
|
{
|
||||||
|
uint16_t numIndices = *cursor++;
|
||||||
|
verts += numIndices;faces++;
|
||||||
|
cursor += numIndices;
|
||||||
|
int16_t surface = *cursor++;
|
||||||
|
if (surface < 0)
|
||||||
|
{
|
||||||
|
// there are detail polygons
|
||||||
|
numIndices = *cursor++;
|
||||||
|
CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
|
||||||
|
LE_NCONST uint16_t*& cursor,
|
||||||
|
const uint16_t* const end,
|
||||||
|
unsigned int max)
|
||||||
|
{
|
||||||
|
while (cursor < end && max--)
|
||||||
|
{
|
||||||
|
LWO::Face& face = *it;++it;
|
||||||
|
if(face.mNumIndices = *cursor++)
|
||||||
|
{
|
||||||
|
if (cursor + face.mNumIndices >= end)break;
|
||||||
|
face.mIndices = new unsigned int[face.mNumIndices];
|
||||||
|
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
||||||
|
{
|
||||||
|
unsigned int & mi = face.mIndices[i] = *cursor++;
|
||||||
|
if (mi > mCurLayer->mTempPoints.size())
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("LWOB: face index is out of range");
|
||||||
|
mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
|
||||||
|
int16_t surface = *cursor++;
|
||||||
|
if (surface < 0)
|
||||||
|
{
|
||||||
|
surface = -surface;
|
||||||
|
|
||||||
|
// there are detail polygons
|
||||||
|
uint16_t numPolygons = *cursor++;
|
||||||
|
if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
|
||||||
|
}
|
||||||
|
face.surfaceIndex = surface-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::LoadLWOBSurface(unsigned int size)
|
||||||
|
{
|
||||||
|
LE_NCONST uint8_t* const end = mFileBuffer + size;
|
||||||
|
|
||||||
|
uint32_t iCursor = 0;
|
||||||
|
mSurfaces->push_back( LWO::Surface () );
|
||||||
|
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;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// glossiness
|
||||||
|
case AI_LWO_GLOS:
|
||||||
|
{
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,GLOS,2);
|
||||||
|
AI_LSWAP2P(mFileBuffer);
|
||||||
|
surf.mGlossiness = float(*((int16_t*)mFileBuffer));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// color texture
|
||||||
|
case AI_LWO_CTEX:
|
||||||
|
{
|
||||||
|
pTex = &surf.mColorTexture;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// diffuse texture
|
||||||
|
case AI_LWO_DTEX:
|
||||||
|
{
|
||||||
|
pTex = &surf.mDiffuseTexture;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// specular texture
|
||||||
|
case AI_LWO_STEX:
|
||||||
|
{
|
||||||
|
pTex = &surf.mSpecularTexture;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// bump texture
|
||||||
|
case AI_LWO_BTEX:
|
||||||
|
{
|
||||||
|
pTex = &surf.mBumpTexture;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// transparency texture
|
||||||
|
case AI_LWO_TTEX:
|
||||||
|
{
|
||||||
|
pTex = &surf.mTransparencyTexture;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// texture path
|
||||||
|
case AI_LWO_TIMG:
|
||||||
|
{
|
||||||
|
if (pTex)
|
||||||
|
{
|
||||||
|
ParseString(pTex->mFileName,head_length);
|
||||||
|
AdjustTexturePath(pTex->mFileName);
|
||||||
|
mFileBuffer += pTex->mFileName.length();
|
||||||
|
}
|
||||||
|
else DefaultLogger::get()->warn("LWOB: TIMG tag was encuntered although "
|
||||||
|
"there was no xTEX tag before");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// texture strength
|
||||||
|
case AI_LWO_TVAL:
|
||||||
|
{
|
||||||
|
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TVAL,1);
|
||||||
|
if (pTex)pTex->mStrength = *mFileBuffer / 255.0f;
|
||||||
|
else DefaultLogger::get()->warn("LWOB: TVAL tag was encuntered "
|
||||||
|
"although there was no xTEX tag before");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mFileBuffer = next;
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,12 +49,17 @@ Original copyright notice: "Ernie Wright 17 Sep 00"
|
||||||
#ifndef AI_LWO_FILEDATA_INCLUDED
|
#ifndef AI_LWO_FILEDATA_INCLUDED
|
||||||
#define AI_LWO_FILEDATA_INCLUDED
|
#define AI_LWO_FILEDATA_INCLUDED
|
||||||
|
|
||||||
|
// STL headers
|
||||||
#include "IFF.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
// public ASSIMP headers
|
||||||
#include "../include/aiMesh.h"
|
#include "../include/aiMesh.h"
|
||||||
|
|
||||||
|
// internal headers
|
||||||
|
#include "IFF.h"
|
||||||
|
#include "SmoothingGroups.h"
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace LWO {
|
namespace LWO {
|
||||||
|
|
||||||
|
@ -232,15 +237,94 @@ namespace LWO {
|
||||||
#define AI_LWO_DATA AI_IFF_FOURCC('D','A','T','A')
|
#define AI_LWO_DATA AI_IFF_FOURCC('D','A','T','A')
|
||||||
|
|
||||||
|
|
||||||
|
/* VMAP types */
|
||||||
|
#define AI_LWO_TXUV AI_IFF_FOURCC('T','X','U','V')
|
||||||
|
#define AI_LWO_RGB AI_IFF_FOURCC(' ','R','G','B')
|
||||||
|
#define AI_LWO_RGBA AI_IFF_FOURCC('R','G','B','A')
|
||||||
|
#define AI_LWO_WGHT AI_IFF_FOURCC('W','G','H','T')
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** \brief Data structure for a face in a LWO file
|
/** \brief Data structure for a face in a LWO file
|
||||||
|
*
|
||||||
|
* \note We can't use the code in SmoothingGroups.inl here - the mesh
|
||||||
|
* structures of 3DS/ASE and LWO are too different.
|
||||||
*/
|
*/
|
||||||
struct Face : public aiFace
|
struct Face : public aiFace
|
||||||
{
|
{
|
||||||
Face() : surfaceIndex(0) {}
|
Face()
|
||||||
|
: surfaceIndex(0)
|
||||||
|
, smoothGroup(0)
|
||||||
|
{}
|
||||||
|
|
||||||
unsigned int surfaceIndex;
|
unsigned int surfaceIndex;
|
||||||
|
unsigned int smoothGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** \brief Base structure for all vertex map representations
|
||||||
|
*/
|
||||||
|
struct VMapEntry
|
||||||
|
{
|
||||||
|
VMapEntry(unsigned int _dims)
|
||||||
|
: dims(_dims)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~VMapEntry() {delete[] rawData;}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
float* rawData;
|
||||||
|
unsigned int dims;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** \brief Represents an extra vertex color channel
|
||||||
|
*/
|
||||||
|
struct VColorChannel : public VMapEntry
|
||||||
|
{
|
||||||
|
VColorChannel(unsigned int num)
|
||||||
|
: VMapEntry(4)
|
||||||
|
{
|
||||||
|
data = new aiColor4D[num];
|
||||||
|
for (unsigned int i = 0; i < num;++i)
|
||||||
|
data[i].a = 1.0f;
|
||||||
|
rawData = (float*)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
aiColor4D* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** \brief Represents an extra vertex UV channel
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/** \brief Represents a weight map
|
||||||
|
*/
|
||||||
|
struct WeightChannel : public VMapEntry
|
||||||
|
{
|
||||||
|
WeightChannel(unsigned int num)
|
||||||
|
: VMapEntry(1)
|
||||||
|
{
|
||||||
|
rawData = new float[num];
|
||||||
|
for (unsigned int m = 0; m < num;++m)
|
||||||
|
rawData[m] = 0.f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** \brief LWO2 gradient keyframe
|
/** \brief LWO2 gradient keyframe
|
||||||
*/
|
*/
|
||||||
|
@ -272,7 +356,8 @@ struct GradientInfo
|
||||||
struct Texture
|
struct Texture
|
||||||
{
|
{
|
||||||
Texture()
|
Texture()
|
||||||
: mStrength(1.0f)
|
: mStrength (1.0f)
|
||||||
|
, iUVChannelIndex (0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
//! File name of the texture
|
//! File name of the texture
|
||||||
|
@ -285,6 +370,8 @@ struct Texture
|
||||||
/*************** SPECIFIC TO LWO2 *********************/
|
/*************** SPECIFIC TO LWO2 *********************/
|
||||||
uint32_t type; // type of the texture
|
uint32_t type; // type of the texture
|
||||||
|
|
||||||
|
//! Index of the corresponding UV channel
|
||||||
|
unsigned int iUVChannelIndex;
|
||||||
|
|
||||||
GradientInfo mGradient;
|
GradientInfo mGradient;
|
||||||
// todo ... maybe support for procedurals?
|
// todo ... maybe support for procedurals?
|
||||||
|
@ -336,11 +423,15 @@ struct Surface
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
typedef std::vector<aiVector3D> PointList;
|
// some typedefs ... to make life with loader monsters like this easier
|
||||||
typedef std::vector<LWO::Face> FaceList;
|
typedef std::vector < aiVector3D > PointList;
|
||||||
typedef std::vector<LWO::Surface> SurfaceList;
|
typedef std::vector < LWO::Face > FaceList;
|
||||||
typedef std::vector<std::string> TagList;
|
typedef std::vector < LWO::Surface > SurfaceList;
|
||||||
typedef std::vector<unsigned int> TagMappingTable;
|
typedef std::vector < std::string > TagList;
|
||||||
|
typedef std::vector < unsigned int > TagMappingTable;
|
||||||
|
typedef std::vector < WeightChannel > WeightChannelList;
|
||||||
|
typedef std::vector < VColorChannel > VColorChannelList;
|
||||||
|
typedef std::vector < UVChannel > UVChannelList;
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -350,14 +441,31 @@ struct Layer
|
||||||
{
|
{
|
||||||
Layer()
|
Layer()
|
||||||
: mParent (0xffff)
|
: mParent (0xffff)
|
||||||
|
, mFaceIDXOfs(0)
|
||||||
|
, mPointIDXOfs(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/** Temporary point list from the file */
|
/** Temporary point list from the file */
|
||||||
PointList mTempPoints;
|
PointList mTempPoints;
|
||||||
|
|
||||||
|
/** Weight channel list from the file */
|
||||||
|
WeightChannelList mWeightChannels;
|
||||||
|
|
||||||
|
/** Vertex color list from the file */
|
||||||
|
VColorChannelList mVColorChannels;
|
||||||
|
|
||||||
|
/** UV channel list from the file */
|
||||||
|
UVChannelList mUVChannels;
|
||||||
|
|
||||||
/** Temporary face list from the file*/
|
/** Temporary face list from the file*/
|
||||||
FaceList mFaces;
|
FaceList mFaces;
|
||||||
|
|
||||||
|
/** Current face indexing offset from the beginning of the buffers*/
|
||||||
|
unsigned int mFaceIDXOfs;
|
||||||
|
|
||||||
|
/** Current point indexing offset from the beginning of the buffers*/
|
||||||
|
unsigned int mPointIDXOfs;
|
||||||
|
|
||||||
/** Parent index */
|
/** Parent index */
|
||||||
uint16_t mParent;
|
uint16_t mParent;
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,6 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
||||||
// new lightwave format
|
// new lightwave format
|
||||||
else if (AI_LWO_FOURCC_LWO2 == fileType)
|
else if (AI_LWO_FOURCC_LWO2 == fileType)
|
||||||
{
|
{
|
||||||
throw new ImportErrorException("LWO2 is under development and currently disabled.");
|
|
||||||
mIsLWO2 = true;
|
mIsLWO2 = true;
|
||||||
this->LoadLWO2File();
|
this->LoadLWO2File();
|
||||||
}
|
}
|
||||||
|
@ -252,6 +251,39 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
||||||
aiFace* pf = mesh->mFaces = new aiFace[mesh->mNumFaces];
|
aiFace* pf = mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||||
mesh->mMaterialIndex = i;
|
mesh->mMaterialIndex = i;
|
||||||
|
|
||||||
|
// find out which vertex color channels and which texture coordinate
|
||||||
|
// channels are really required by the material attached to this mesh
|
||||||
|
unsigned int vUVChannelIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||||
|
unsigned int vVColorIndices[AI_MAX_NUMBER_OF_COLOR_SETS];
|
||||||
|
|
||||||
|
#if _DEBUG
|
||||||
|
for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui )
|
||||||
|
vUVChannelIndices[mui] = 0xffffffff;
|
||||||
|
for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui )
|
||||||
|
vVColorIndices[mui] = 0xffffffff;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FindUVChannels(_mSurfaces[i],layer,vUVChannelIndices);
|
||||||
|
FindVCChannels(_mSurfaces[i],layer,vVColorIndices);
|
||||||
|
|
||||||
|
// allocate storage for UV and CV channels
|
||||||
|
aiVector3D* pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||||
|
for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui )
|
||||||
|
{
|
||||||
|
if (0xffffffff == vUVChannelIndices[mui])break;
|
||||||
|
pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices];
|
||||||
|
|
||||||
|
// LightWave doesn't support more than 2 UV components
|
||||||
|
mesh->mNumUVComponents[0] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS];
|
||||||
|
for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui)
|
||||||
|
{
|
||||||
|
if (0xffffffff == vVColorIndices[mui])break;
|
||||||
|
pvVC[mui] = mesh->mColors[mui] = new aiColor4D[mesh->mNumVertices];
|
||||||
|
}
|
||||||
|
|
||||||
// now convert all faces
|
// now convert all faces
|
||||||
unsigned int vert = 0;
|
unsigned int vert = 0;
|
||||||
for (SortedRep::const_iterator it = sorted.begin(), end = sorted.end();
|
for (SortedRep::const_iterator it = sorted.begin(), end = sorted.end();
|
||||||
|
@ -262,7 +294,29 @@ void LWOImporter::InternReadFile( const std::string& pFile,
|
||||||
// copy all vertices
|
// copy all vertices
|
||||||
for (unsigned int q = 0; q < face.mNumIndices;++q)
|
for (unsigned int q = 0; q < face.mNumIndices;++q)
|
||||||
{
|
{
|
||||||
*pv++ = layer.mTempPoints[face.mIndices[q]];
|
register unsigned int idx = face.mIndices[q];
|
||||||
|
*pv++ = layer.mTempPoints[idx];
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// process vertex weights - not yet supported
|
||||||
|
for (unsigned int w = 0; w < layer.mWeightChannels.size();++w)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
face.mIndices[q] = vert++;
|
face.mIndices[q] = vert++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,65 +430,10 @@ void LWOImporter::GenerateNodeGraph(std::vector<aiNode*>& apcNodes)
|
||||||
if (!pScene->mRootNode)throw new ImportErrorException("LWO: Unable to build a valid node graph");
|
if (!pScene->mRootNode)throw new ImportErrorException("LWO: Unable to build a valid node graph");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
void LWOImporter::CountVertsAndFaces(unsigned int& verts, unsigned int& faces,
|
|
||||||
LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
|
|
||||||
{
|
|
||||||
while (cursor < end && max--)
|
|
||||||
{
|
|
||||||
uint16_t numIndices = *cursor++;
|
|
||||||
verts += numIndices;faces++;
|
|
||||||
cursor += numIndices;
|
|
||||||
int16_t surface = *cursor++;
|
|
||||||
if (surface < 0)
|
|
||||||
{
|
|
||||||
// there are detail polygons
|
|
||||||
numIndices = *cursor++;
|
|
||||||
CountVertsAndFaces(verts,faces,cursor,end,numIndices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
void LWOImporter::CopyFaceIndices(FaceList::iterator& it,
|
|
||||||
LE_NCONST uint16_t*& cursor,
|
|
||||||
const uint16_t* const end,
|
|
||||||
unsigned int max)
|
|
||||||
{
|
|
||||||
while (cursor < end && max--)
|
|
||||||
{
|
|
||||||
LWO::Face& face = *it;++it;
|
|
||||||
if(face.mNumIndices = *cursor++)
|
|
||||||
{
|
|
||||||
if (cursor + face.mNumIndices >= end)break;
|
|
||||||
face.mIndices = new unsigned int[face.mNumIndices];
|
|
||||||
for (unsigned int i = 0; i < face.mNumIndices;++i)
|
|
||||||
{
|
|
||||||
unsigned int & mi = face.mIndices[i] = *cursor++;
|
|
||||||
if (mi > mCurLayer->mTempPoints.size())
|
|
||||||
{
|
|
||||||
DefaultLogger::get()->warn("LWO: face index is out of range");
|
|
||||||
mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else DefaultLogger::get()->warn("LWO: Face has 0 indices");
|
|
||||||
int16_t surface = *cursor++;
|
|
||||||
if (surface < 0)
|
|
||||||
{
|
|
||||||
surface = -surface;
|
|
||||||
|
|
||||||
// there are detail polygons
|
|
||||||
uint16_t numPolygons = *cursor++;
|
|
||||||
if (cursor < end)CopyFaceIndices(it,cursor,end,numPolygons);
|
|
||||||
}
|
|
||||||
face.surfaceIndex = surface-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::ResolveTags()
|
void LWOImporter::ResolveTags()
|
||||||
{
|
{
|
||||||
|
// --- this function is used for both LWO2 and LWOB
|
||||||
mMapping->resize(mTags->size(),0xffffffff);
|
mMapping->resize(mTags->size(),0xffffffff);
|
||||||
for (unsigned int a = 0; a < mTags->size();++a)
|
for (unsigned int a = 0; a < mTags->size();++a)
|
||||||
{
|
{
|
||||||
|
@ -454,6 +453,7 @@ void LWOImporter::ResolveTags()
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::ParseString(std::string& out,unsigned int max)
|
void LWOImporter::ParseString(std::string& out,unsigned int max)
|
||||||
{
|
{
|
||||||
|
// --- this function is used for both LWO2 and LWOB
|
||||||
unsigned int iCursor = 0;
|
unsigned int iCursor = 0;
|
||||||
const char* in = (const char*)mFileBuffer,*sz = in;
|
const char* in = (const char*)mFileBuffer,*sz = in;
|
||||||
while (*in)
|
while (*in)
|
||||||
|
@ -472,6 +472,7 @@ void LWOImporter::ParseString(std::string& out,unsigned int max)
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::AdjustTexturePath(std::string& out)
|
void LWOImporter::AdjustTexturePath(std::string& out)
|
||||||
{
|
{
|
||||||
|
// --- this function is used for both LWO2 and LWOB
|
||||||
if (::strstr(out.c_str(), "(sequence)"))
|
if (::strstr(out.c_str(), "(sequence)"))
|
||||||
{
|
{
|
||||||
// remove the (sequence) and append 000
|
// remove the (sequence) and append 000
|
||||||
|
@ -480,9 +481,34 @@ void LWOImporter::AdjustTexturePath(std::string& out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::LoadLWOTags(unsigned int size)
|
void LWOImporter::LoadLWOTags(unsigned int size)
|
||||||
{
|
{
|
||||||
|
// --- this function is used for both LWO2 and LWOB
|
||||||
|
|
||||||
const char* szCur = (const char*)mFileBuffer, *szLast = szCur;
|
const char* szCur = (const char*)mFileBuffer, *szLast = szCur;
|
||||||
const char* const szEnd = szLast+size;
|
const char* const szEnd = szLast+size;
|
||||||
while (szCur < szEnd)
|
while (szCur < szEnd)
|
||||||
|
@ -501,6 +527,7 @@ void LWOImporter::LoadLWOTags(unsigned int size)
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::LoadLWOPoints(unsigned int length)
|
void LWOImporter::LoadLWOPoints(unsigned int length)
|
||||||
{
|
{
|
||||||
|
// --- this function is used for both LWO2 and LWOB
|
||||||
mCurLayer->mTempPoints.resize( length / 12 );
|
mCurLayer->mTempPoints.resize( length / 12 );
|
||||||
|
|
||||||
// perform endianess conversions
|
// perform endianess conversions
|
||||||
|
@ -514,6 +541,17 @@ void LWOImporter::LoadLWOPoints(unsigned int length)
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::LoadLWOPolygons(unsigned int length)
|
void LWOImporter::LoadLWOPolygons(unsigned int length)
|
||||||
{
|
{
|
||||||
|
// --- this function is used for both LWO2 and LWOB
|
||||||
|
if (mIsLWO2)
|
||||||
|
{
|
||||||
|
uint32_t type = *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer += 4;
|
||||||
|
if (type != AI_LWO_FACE)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("LWO2: Only POLS.FACE chunsk are supported.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// first find out how many faces and vertices we'll finally need
|
// 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* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
|
||||||
LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
|
LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
|
||||||
|
@ -525,76 +563,158 @@ void LWOImporter::LoadLWOPolygons(unsigned int length)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int iNumFaces = 0,iNumVertices = 0;
|
unsigned int iNumFaces = 0,iNumVertices = 0;
|
||||||
CountVertsAndFaces(iNumVertices,iNumFaces,cursor,end);
|
if (mIsLWO2)CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end);
|
||||||
|
else CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end);
|
||||||
|
|
||||||
// allocate the output array and copy face indices
|
// allocate the output array and copy face indices
|
||||||
if (iNumFaces)
|
if (iNumFaces)
|
||||||
{
|
{
|
||||||
cursor = (LE_NCONST uint16_t*)mFileBuffer;
|
cursor = (LE_NCONST uint16_t*)mFileBuffer;
|
||||||
// this->mTempPoints->resize(iNumVertices);
|
|
||||||
mCurLayer->mFaces.resize(iNumFaces);
|
mCurLayer->mFaces.resize(iNumFaces);
|
||||||
FaceList::iterator it = mCurLayer->mFaces.begin();
|
FaceList::iterator it = mCurLayer->mFaces.begin();
|
||||||
CopyFaceIndices(it,cursor,end);
|
if (mIsLWO2)CopyFaceIndicesLWO2(it,cursor,end);
|
||||||
|
else CopyFaceIndicesLWOB(it,cursor,end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::LoadLWOBFile()
|
void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& faces,
|
||||||
|
LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
|
||||||
{
|
{
|
||||||
LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
|
while (cursor < end && max--)
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
|
uint16_t numIndices = *cursor++;
|
||||||
LE_NCONST IFF::ChunkHeader* const head = (LE_NCONST IFF::ChunkHeader*)mFileBuffer;
|
numIndices &= 0x03FF;
|
||||||
AI_LSWAP4(head->length);
|
verts += numIndices;++faces;
|
||||||
AI_LSWAP4(head->type);
|
|
||||||
mFileBuffer += sizeof(IFF::ChunkHeader);
|
|
||||||
if (mFileBuffer + head->length > end)
|
|
||||||
{
|
|
||||||
throw new ImportErrorException("LWOB: Invalid file, the size attribute of "
|
|
||||||
"a chunk points behind the end of the file");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
LE_NCONST uint8_t* const next = mFileBuffer+head->length;
|
|
||||||
switch (head->type)
|
|
||||||
{
|
|
||||||
// vertex list
|
|
||||||
case AI_LWO_PNTS:
|
|
||||||
{
|
|
||||||
if (!mCurLayer->mTempPoints.empty())
|
|
||||||
DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
|
|
||||||
else LoadLWOPoints(head->length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// face list
|
|
||||||
case AI_LWO_POLS:
|
|
||||||
{
|
|
||||||
if (!mCurLayer->mFaces.empty())
|
|
||||||
DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
|
|
||||||
else LoadLWOPolygons(head->length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// list of tags
|
|
||||||
case AI_LWO_SRFS:
|
|
||||||
{
|
|
||||||
if (!mTags->empty())
|
|
||||||
DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
|
|
||||||
else LoadLWOTags(head->length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// surface chunk
|
for(uint16_t i = 0; i < numIndices; i++)
|
||||||
case AI_LWO_SURF:
|
ReadVSizedIntLWO2((uint8_t*&)cursor);
|
||||||
{
|
|
||||||
if (!mSurfaces->empty())
|
|
||||||
DefaultLogger::get()->warn("LWO: SURF chunk encountered twice");
|
|
||||||
else LoadLWOBSurface(head->length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mFileBuffer = next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
|
||||||
|
LE_NCONST uint16_t*& cursor,
|
||||||
|
const uint16_t* const end,
|
||||||
|
unsigned int max)
|
||||||
|
{
|
||||||
|
while (cursor < end && max--)
|
||||||
|
{
|
||||||
|
LWO::Face& face = *it;++it;
|
||||||
|
if(face.mNumIndices = (*cursor++) & 0x03FF)
|
||||||
|
{
|
||||||
|
face.mIndices = new unsigned int[face.mNumIndices];
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < face.mNumIndices; i++)
|
||||||
|
{
|
||||||
|
face.mIndices[i] = ReadVSizedIntLWO2((uint8_t*&)cursor) + mCurLayer->mPointIDXOfs;
|
||||||
|
if(face.mIndices[i] > mCurLayer->mTempPoints.size())
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("LWO2: face index is out of range");
|
||||||
|
face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size()-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else DefaultLogger::get()->warn("LWO2: face has 0 indices");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
|
||||||
|
{
|
||||||
|
uint32_t type = *((LE_NCONST uint32_t*)mFileBuffer);mFileBuffer+=4;
|
||||||
|
AI_LSWAP4(type);
|
||||||
|
|
||||||
|
if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LE_NCONST uint8_t* const end = mFileBuffer+length;
|
||||||
|
while (mFileBuffer < end)
|
||||||
|
{
|
||||||
|
unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
|
||||||
|
unsigned int j = ReadVSizedIntLWO2(mFileBuffer);
|
||||||
|
|
||||||
|
if (i > mCurLayer->mFaces.size())
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("LWO2: face index in ptag list is out of range");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case AI_LWO_SURF:
|
||||||
|
mCurLayer->mFaces[i].surfaceIndex = j;
|
||||||
|
break;
|
||||||
|
case AI_LWO_SMGP:
|
||||||
|
mCurLayer->mFaces[i].smoothGroup = j;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
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;
|
||||||
|
|
||||||
|
VMapEntry* base;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case AI_LWO_TXUV:
|
||||||
|
if (dims != 2)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("LWO2: Found UV channel with != 2 components");
|
||||||
|
}
|
||||||
|
mCurLayer->mUVChannels.push_back(UVChannel(mCurLayer->mTempPoints.size()));
|
||||||
|
base = &mCurLayer->mUVChannels.back();
|
||||||
|
case AI_LWO_WGHT:
|
||||||
|
if (dims != 1)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("LWO2: found vertex weight map with != 1 components");
|
||||||
|
}
|
||||||
|
mCurLayer->mWeightChannels.push_back(WeightChannel(mCurLayer->mTempPoints.size()));
|
||||||
|
base = &mCurLayer->mWeightChannels.back();
|
||||||
|
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(mCurLayer->mTempPoints.size()));
|
||||||
|
base = &mCurLayer->mVColorChannels.back();
|
||||||
|
default: return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// read the name of the vertex map
|
||||||
|
ParseString(base->name,length);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
while (mFileBuffer < end)
|
||||||
|
{
|
||||||
|
unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs;
|
||||||
|
if (idx > mCurLayer->mTempPoints.size())
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("LWO2: vertex index in vmap/vmad is out of range");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < type;++i)
|
||||||
|
{
|
||||||
|
base->rawData[idx*dims+i]= *((float*)mFileBuffer);
|
||||||
|
mFileBuffer += 4;
|
||||||
|
}
|
||||||
|
mFileBuffer += diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::LoadLWO2File()
|
void LWOImporter::LoadLWO2File()
|
||||||
{
|
{
|
||||||
|
@ -647,24 +767,41 @@ void LWOImporter::LoadLWO2File()
|
||||||
// vertex list
|
// vertex list
|
||||||
case AI_LWO_PNTS:
|
case AI_LWO_PNTS:
|
||||||
{
|
{
|
||||||
if (!mCurLayer->mTempPoints.empty())
|
unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
|
||||||
DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
|
LoadLWOPoints(head->length);
|
||||||
else LoadLWOPoints(head->length);
|
mCurLayer->mPointIDXOfs = old;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// vertex tags
|
||||||
|
//case AI_LWO_VMAD:
|
||||||
|
case AI_LWO_VMAP:
|
||||||
|
{
|
||||||
|
if (mCurLayer->mTempPoints.empty())
|
||||||
|
DefaultLogger::get()->warn("LWO2: Unexpected VMAD/VMAP chunk");
|
||||||
|
else LoadLWO2VertexMap(head->length,head->type == AI_LWO_VMAD);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// face list
|
// face list
|
||||||
case AI_LWO_POLS:
|
case AI_LWO_POLS:
|
||||||
{
|
{
|
||||||
if (!mCurLayer->mFaces.empty())
|
unsigned int old = (unsigned int)mCurLayer->mFaces.size();
|
||||||
DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
|
LoadLWOPolygons(head->length);
|
||||||
else LoadLWOPolygons(head->length);
|
mCurLayer->mFaceIDXOfs = old;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// polygon tags
|
||||||
|
case AI_LWO_PTAG:
|
||||||
|
{
|
||||||
|
if (mCurLayer->mFaces.empty())
|
||||||
|
DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
|
||||||
|
else LoadLWO2PolygonTags(head->length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// list of tags
|
// list of tags
|
||||||
case AI_LWO_SRFS:
|
case AI_LWO_SRFS:
|
||||||
{
|
{
|
||||||
if (!mTags->empty())
|
if (!mTags->empty())
|
||||||
DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
|
DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
|
||||||
else LoadLWOTags(head->length);
|
else LoadLWOTags(head->length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -673,8 +810,8 @@ void LWOImporter::LoadLWO2File()
|
||||||
case AI_LWO_SURF:
|
case AI_LWO_SURF:
|
||||||
{
|
{
|
||||||
if (!mSurfaces->empty())
|
if (!mSurfaces->empty())
|
||||||
DefaultLogger::get()->warn("LWO: SURF chunk encountered twice");
|
DefaultLogger::get()->warn("LWO2: SURF chunk encountered twice");
|
||||||
else LoadLWOBSurface(head->length);
|
else LoadLWO2Surface(head->length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,13 @@ namespace Assimp {
|
||||||
using namespace LWO;
|
using namespace LWO;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
/** Clas to load LWO files
|
/** Class to load LWO files.
|
||||||
|
*
|
||||||
|
* @note Methods named "xxxLWO2[xxx]" are used with the newer LWO2 format.
|
||||||
|
* Methods named "xxxLWOB[xxx]" are used with the older LWOB format.
|
||||||
|
* Methods named "xxxLWO[xxx]" are used with both formats.
|
||||||
|
* Methods named "xxx" are used to preprocess the loaded data -
|
||||||
|
* they aren't specific to one format version, either
|
||||||
*/
|
*/
|
||||||
class LWOImporter : public BaseImporter
|
class LWOImporter : public BaseImporter
|
||||||
{
|
{
|
||||||
|
@ -157,6 +163,19 @@ private:
|
||||||
*/
|
*/
|
||||||
void LoadLWOPolygons(unsigned int length);
|
void LoadLWOPolygons(unsigned int length);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Load polygon tags from a PTAG chunk
|
||||||
|
* @param length Size of the chunk
|
||||||
|
*/
|
||||||
|
void LoadLWO2PolygonTags(unsigned int length);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Load a vertex map from a VMAP/VMAD chunk
|
||||||
|
* @param length Size of the chunk
|
||||||
|
* @param perPoly Operate on per-polygon base?
|
||||||
|
*/
|
||||||
|
void LoadLWO2VertexMap(unsigned int length, bool perPoly);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Load polygons from a PNTS chunk
|
/** Load polygons from a PNTS chunk
|
||||||
* @param length Size of the chunk
|
* @param length Size of the chunk
|
||||||
|
@ -167,7 +186,13 @@ private:
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Count vertices and faces in a LWOB/LWO2 file
|
/** Count vertices and faces in a LWOB/LWO2 file
|
||||||
*/
|
*/
|
||||||
void CountVertsAndFaces(unsigned int& verts,
|
void CountVertsAndFacesLWO2(unsigned int& verts,
|
||||||
|
unsigned int& faces,
|
||||||
|
LE_NCONST uint16_t*& cursor,
|
||||||
|
const uint16_t* const end,
|
||||||
|
unsigned int max = 0xffffffff);
|
||||||
|
|
||||||
|
void CountVertsAndFacesLWOB(unsigned int& verts,
|
||||||
unsigned int& faces,
|
unsigned int& faces,
|
||||||
LE_NCONST uint16_t*& cursor,
|
LE_NCONST uint16_t*& cursor,
|
||||||
const uint16_t* const end,
|
const uint16_t* const end,
|
||||||
|
@ -176,7 +201,12 @@ private:
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Read vertices and faces in a LWOB/LWO2 file
|
/** Read vertices and faces in a LWOB/LWO2 file
|
||||||
*/
|
*/
|
||||||
void CopyFaceIndices(LWO::FaceList::iterator& it,
|
void CopyFaceIndicesLWO2(LWO::FaceList::iterator& it,
|
||||||
|
LE_NCONST uint16_t*& cursor,
|
||||||
|
const uint16_t* const end,
|
||||||
|
unsigned int max = 0xffffffff);
|
||||||
|
|
||||||
|
void CopyFaceIndicesLWOB(LWO::FaceList::iterator& it,
|
||||||
LE_NCONST uint16_t*& cursor,
|
LE_NCONST uint16_t*& cursor,
|
||||||
const uint16_t* const end,
|
const uint16_t* const end,
|
||||||
unsigned int max = 0xffffffff);
|
unsigned int max = 0xffffffff);
|
||||||
|
@ -213,6 +243,23 @@ private:
|
||||||
*/
|
*/
|
||||||
void ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat);
|
void ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat);
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Get a list of all UV/VC channels required by a specific surface.
|
||||||
|
*
|
||||||
|
* @param surf Working surface
|
||||||
|
* @param layer Working layer
|
||||||
|
* @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,
|
||||||
|
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]);
|
||||||
|
|
||||||
|
void FindVCChannels(const LWO::Surface& surf,
|
||||||
|
const LWO::Layer& layer,
|
||||||
|
unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
/** Generate the final node graph
|
/** Generate the final node graph
|
||||||
* Unused nodes are deleted.
|
* Unused nodes are deleted.
|
||||||
|
@ -220,6 +267,12 @@ private:
|
||||||
*/
|
*/
|
||||||
void GenerateNodeGraph(std::vector<aiNode*>& apcNodes);
|
void GenerateNodeGraph(std::vector<aiNode*>& apcNodes);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
/** Read a variable sized integer
|
||||||
|
* @param inout Input and output buffer
|
||||||
|
*/
|
||||||
|
int ReadVSizedIntLWO2(uint8_t*& inout);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** true if the file is a LWO2 file*/
|
/** true if the file is a LWO2 file*/
|
||||||
|
|
|
@ -113,140 +113,17 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void LWOImporter::LoadLWOBSurface(unsigned int size)
|
void LWOImporter::FindUVChannels(const LWO::Surface& surf, const LWO::Layer& layer,
|
||||||
|
unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
|
||||||
{
|
{
|
||||||
LE_NCONST uint8_t* const end = mFileBuffer + size;
|
out[0] = 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t iCursor = 0;
|
// ------------------------------------------------------------------------------------------------
|
||||||
mSurfaces->push_back( LWO::Surface () );
|
void LWOImporter::FindVCChannels(const LWO::Surface& surf, const LWO::Layer& layer,
|
||||||
LWO::Surface& surf = mSurfaces->back();
|
unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
|
||||||
LWO::Texture* pTex = NULL;
|
{
|
||||||
|
out[0] = 0xffffffff;
|
||||||
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;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// glossiness
|
|
||||||
case AI_LWO_GLOS:
|
|
||||||
{
|
|
||||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,GLOS,2);
|
|
||||||
AI_LSWAP2P(mFileBuffer);
|
|
||||||
surf.mGlossiness = float(*((int16_t*)mFileBuffer));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// color texture
|
|
||||||
case AI_LWO_CTEX:
|
|
||||||
{
|
|
||||||
pTex = &surf.mColorTexture;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// diffuse texture
|
|
||||||
case AI_LWO_DTEX:
|
|
||||||
{
|
|
||||||
pTex = &surf.mDiffuseTexture;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// specular texture
|
|
||||||
case AI_LWO_STEX:
|
|
||||||
{
|
|
||||||
pTex = &surf.mSpecularTexture;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// bump texture
|
|
||||||
case AI_LWO_BTEX:
|
|
||||||
{
|
|
||||||
pTex = &surf.mBumpTexture;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// transparency texture
|
|
||||||
case AI_LWO_TTEX:
|
|
||||||
{
|
|
||||||
pTex = &surf.mTransparencyTexture;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// texture path
|
|
||||||
case AI_LWO_TIMG:
|
|
||||||
{
|
|
||||||
if (pTex)
|
|
||||||
{
|
|
||||||
ParseString(pTex->mFileName,head_length);
|
|
||||||
AdjustTexturePath(pTex->mFileName);
|
|
||||||
mFileBuffer += pTex->mFileName.length();
|
|
||||||
}
|
|
||||||
else DefaultLogger::get()->warn("LWOB: TIMG tag was encuntered although "
|
|
||||||
"there was no xTEX tag before");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// texture strength
|
|
||||||
case AI_LWO_TVAL:
|
|
||||||
{
|
|
||||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head_length,TVAL,1);
|
|
||||||
if (pTex)pTex->mStrength = *mFileBuffer / 255.0f;
|
|
||||||
else DefaultLogger::get()->warn("LWOB: TVAL tag was encuntered "
|
|
||||||
"although there was no xTEX tag before");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mFileBuffer = next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -140,6 +140,8 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
MeshInfo* currentMeshWithNormals = NULL;
|
MeshInfo* currentMeshWithNormals = NULL;
|
||||||
MeshInfo* currentMesh = NULL;
|
MeshInfo* currentMesh = NULL;
|
||||||
|
|
||||||
|
ShadingInfo s; // current material info
|
||||||
|
|
||||||
char line[4096];
|
char line[4096];
|
||||||
const char* sz;
|
const char* sz;
|
||||||
unsigned int sphere = 0,cylinder = 0,cone = 0,numNamed = 0;
|
unsigned int sphere = 0,cylinder = 0,cone = 0,numNamed = 0;
|
||||||
|
@ -197,8 +199,6 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
{
|
{
|
||||||
SkipSpaces(&line[1],&sz);
|
SkipSpaces(&line[1],&sz);
|
||||||
|
|
||||||
ShadingInfo s; // color;
|
|
||||||
|
|
||||||
// read just the RGB colors, the rest is ignored for the moment
|
// read just the RGB colors, the rest is ignored for the moment
|
||||||
sz = fast_atof_move(sz, s.color.r);
|
sz = fast_atof_move(sz, s.color.r);
|
||||||
SkipSpaces(&sz);
|
SkipSpaces(&sz);
|
||||||
|
@ -241,6 +241,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
{
|
{
|
||||||
meshesLocked.push_back(MeshInfo(false,true));
|
meshesLocked.push_back(MeshInfo(false,true));
|
||||||
MeshInfo& currentMesh = meshesLocked.back();
|
MeshInfo& currentMesh = meshesLocked.back();
|
||||||
|
currentMesh.shader = s;
|
||||||
|
|
||||||
sz = &line[1];
|
sz = &line[1];
|
||||||
aiVector3D center; float radius;
|
aiVector3D center; float radius;
|
||||||
|
@ -261,6 +262,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
{
|
{
|
||||||
meshesLocked.push_back(MeshInfo(false,true));
|
meshesLocked.push_back(MeshInfo(false,true));
|
||||||
MeshInfo& currentMesh = meshes.back();
|
MeshInfo& currentMesh = meshes.back();
|
||||||
|
currentMesh.shader = s;
|
||||||
|
|
||||||
sz = &line[1];
|
sz = &line[1];
|
||||||
aiVector3D center1, center2; float radius1, radius2;
|
aiVector3D center1, center2; float radius1, radius2;
|
||||||
|
@ -286,7 +288,8 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
||||||
// '#' - comment
|
// '#' - comment
|
||||||
else if ('#' == line[0])
|
else if ('#' == line[0])
|
||||||
{
|
{
|
||||||
DefaultLogger::get()->info(line);
|
const char* sz;SkipSpaces(&line[1],&sz);
|
||||||
|
if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,6 @@ void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh)
|
||||||
posEpsilon,poResult);
|
posEpsilon,poResult);
|
||||||
|
|
||||||
aiVector3D vNormals;
|
aiVector3D vNormals;
|
||||||
float fDiv = 0.0f;
|
|
||||||
for (std::vector<unsigned int>::const_iterator
|
for (std::vector<unsigned int>::const_iterator
|
||||||
a = poResult.begin();
|
a = poResult.begin();
|
||||||
a != poResult.end();++a)
|
a != poResult.end();++a)
|
||||||
|
@ -125,10 +124,8 @@ void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh)
|
||||||
vNormals += sMesh.mNormals[(*a)];
|
vNormals += sMesh.mNormals[(*a)];
|
||||||
//fDiv += 1.0f;
|
//fDiv += 1.0f;
|
||||||
}
|
}
|
||||||
//vNormals.x /= fDiv;vNormals.y /= fDiv;vNormals.z /= fDiv;
|
|
||||||
vNormals.Normalize();
|
vNormals.Normalize();
|
||||||
avNormals[(*i).mIndices[c]] = vNormals;
|
avNormals[(*i).mIndices[c]] = vNormals;
|
||||||
//poResult.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sMesh.mNormals = avNormals;
|
sMesh.mNormals = avNormals;
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
#default color
|
||||||
|
|
||||||
|
# A simple sphere
|
||||||
|
s 5.0 5.0 5.0 10.0
|
||||||
|
|
||||||
|
#blue
|
||||||
|
f 0.0 0.0 1.0 0 1 1
|
||||||
|
|
||||||
|
# Another simple sphere
|
||||||
|
s 5.0 4.0 8.0 3.0
|
||||||
|
|
||||||
|
#green
|
||||||
|
f 0.0 1.0 0.0 0 1 1
|
||||||
|
|
||||||
|
# And another one
|
||||||
|
s 1.0 -4.0 2.0 4.0
|
||||||
|
|
||||||
|
#red
|
||||||
|
f 1.0 0.0 0.0 0 1 1
|
||||||
|
|
||||||
|
# a simple cone
|
||||||
|
c 10 10 5 3
|
||||||
|
c 14 14 3 6
|
|
@ -1101,6 +1101,14 @@
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="FBX"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Collada"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
|
@ -1276,6 +1284,10 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="LWO"
|
Name="LWO"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\code\LWOBLoader.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\code\LWOLoader.cpp"
|
RelativePath="..\..\code\LWOLoader.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue