Importer for Silo SIB files.
Wrote an importer for Nevercenter Silo's binary SIB model formatpull/717/head
parent
078dd0c08b
commit
d952823ffd
|
@ -86,8 +86,8 @@ static const aiImporterDesc desc = {
|
|||
int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \
|
||||
if(chunkSize <= 0) \
|
||||
continue; \
|
||||
const int oldReadLimit = stream->GetReadLimit(); \
|
||||
stream->SetReadLimit(stream->GetCurrentPos() + chunkSize); \
|
||||
const unsigned int oldReadLimit = stream->SetReadLimit( \
|
||||
stream->GetCurrentPos() + chunkSize); \
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -530,6 +530,11 @@ ADD_ASSIMP_IMPORTER(RAW
|
|||
RawLoader.h
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER(SIB
|
||||
SIBImporter.cpp
|
||||
SIBImporter.h
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER(SMD
|
||||
SMDLoader.cpp
|
||||
SMDLoader.h
|
||||
|
|
|
@ -101,6 +101,9 @@ corresponding preprocessor flag to selectively disable formats.
|
|||
#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
|
||||
# include "RawLoader.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
|
||||
# include "SIBImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
|
||||
# include "OFFLoader.h"
|
||||
#endif
|
||||
|
@ -238,6 +241,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
|
|||
#if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER)
|
||||
out.push_back( new RAWImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_SIB_IMPORTER)
|
||||
out.push_back( new SIBImporter());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER)
|
||||
out.push_back( new OFFImporter());
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,919 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2015, assimp 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 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 SIBImporter.cpp
|
||||
* @brief Implementation of the SIB importer class
|
||||
*
|
||||
* The Nevercenter Silo SIB format is undocumented.
|
||||
* All details here have been reverse engineered from
|
||||
* studying the binary files output by Silo.
|
||||
*
|
||||
* Nevertheless, this implementation is reasonably complete.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_SIB_IMPORTER
|
||||
|
||||
// internal headers
|
||||
#include "SIBImporter.h"
|
||||
#include "ByteSwapper.h"
|
||||
#include "StreamReader.h"
|
||||
#include "TinyFormatter.h"
|
||||
#include "../contrib/ConvertUTF/ConvertUTF.h"
|
||||
#include "../include/assimp/IOSystem.hpp"
|
||||
#include "../include/assimp/DefaultLogger.hpp"
|
||||
#include "../include/assimp/scene.h"
|
||||
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
static const aiImporterDesc desc = {
|
||||
"Silo SIB Importer",
|
||||
"Richard Mitton (http://www.codersnotes.com/about)",
|
||||
"",
|
||||
"Does not apply subdivision.",
|
||||
aiImporterFlags_SupportBinaryFlavour,
|
||||
0, 0,
|
||||
0, 0,
|
||||
"sib"
|
||||
};
|
||||
|
||||
struct SIBChunk
|
||||
{
|
||||
uint32_t Tag;
|
||||
uint32_t Size;
|
||||
} PACK_STRUCT;
|
||||
|
||||
enum { POS, NRM, UV, N };
|
||||
|
||||
typedef std::pair<uint32_t, uint32_t> SIBPair;
|
||||
static SIBPair makePair(uint32_t a, uint32_t b) { return (a<b) ? SIBPair(a, b) : SIBPair(b, a); }
|
||||
|
||||
struct SIBEdge
|
||||
{
|
||||
uint32_t faceA, faceB;
|
||||
bool creased;
|
||||
};
|
||||
|
||||
struct SIBMesh
|
||||
{
|
||||
aiMatrix4x4 axis;
|
||||
uint32_t numPts;
|
||||
std::vector<aiVector3D> pos, nrm, uv;
|
||||
std::vector<uint32_t> idx;
|
||||
std::vector<uint32_t> faceStart;
|
||||
std::vector<uint32_t> mtls;
|
||||
std::vector<SIBEdge> edges;
|
||||
std::map<SIBPair, uint32_t> edgeMap;
|
||||
};
|
||||
|
||||
struct SIBObject
|
||||
{
|
||||
aiString name;
|
||||
aiMatrix4x4 axis;
|
||||
size_t meshIdx, meshCount;
|
||||
};
|
||||
|
||||
struct SIB
|
||||
{
|
||||
std::vector<aiMaterial*> mtls;
|
||||
std::vector<aiMesh*> meshes;
|
||||
std::vector<aiLight*> lights;
|
||||
std::vector<SIBObject> objs, insts;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB)
|
||||
{
|
||||
SIBPair pair = (posA < posB) ? SIBPair(posA, posB) : SIBPair(posB, posA);
|
||||
std::map<SIBPair, uint32_t>::iterator it = mesh->edgeMap.find(pair);
|
||||
if (it != mesh->edgeMap.end())
|
||||
return mesh->edges[it->second];
|
||||
|
||||
SIBEdge edge;
|
||||
edge.creased = false;
|
||||
edge.faceA = edge.faceB = 0xffffffff;
|
||||
mesh->edgeMap[pair] = mesh->edges.size();
|
||||
mesh->edges.push_back(edge);
|
||||
return mesh->edges.back();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Helpers for reading chunked data.
|
||||
|
||||
#define TAG(A,B,C,D) ((A << 24) | (B << 16) | (C << 8) | D)
|
||||
|
||||
static SIBChunk ReadChunk(StreamReaderLE* stream)
|
||||
{
|
||||
SIBChunk chunk;
|
||||
chunk.Tag = stream->GetU4();
|
||||
chunk.Size = stream->GetU4();
|
||||
if (chunk.Size > stream->GetRemainingSizeToLimit())
|
||||
DefaultLogger::get()->error("SIB: Chunk overflow");
|
||||
ByteSwap::Swap4(&chunk.Tag);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static aiColor3D ReadColor(StreamReaderLE* stream)
|
||||
{
|
||||
float r = stream->GetF4();
|
||||
float g = stream->GetF4();
|
||||
float b = stream->GetF4();
|
||||
stream->GetU4(); // Colors have an unused(?) 4th component.
|
||||
return aiColor3D(r, g, b);
|
||||
}
|
||||
|
||||
static void UnknownChunk(StreamReaderLE* stream, const SIBChunk& chunk)
|
||||
{
|
||||
char temp[5] = { (chunk.Tag>>24)&0xff, (chunk.Tag>>16)&0xff, (chunk.Tag>>8)&0xff, chunk.Tag&0xff, '\0' };
|
||||
|
||||
DefaultLogger::get()->warn((Formatter::format(), "SIB: Skipping unknown '",temp,"' chunk."));
|
||||
}
|
||||
|
||||
// Reads a UTF-16LE string and returns it at UTF-8.
|
||||
static aiString ReadString(StreamReaderLE* stream, uint32_t numWChars)
|
||||
{
|
||||
// Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8)
|
||||
UTF16* temp = new UTF16[numWChars];
|
||||
UTF8* str = new UTF8[numWChars * 4 + 1];
|
||||
for (uint32_t n=0;n<numWChars;n++)
|
||||
temp[n] = stream->GetU2();
|
||||
|
||||
// Convert it and NUL-terminate.
|
||||
const UTF16 *start = temp, *end = temp + numWChars;
|
||||
UTF8 *dest = str, *limit = str + numWChars*4;
|
||||
ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion);
|
||||
*dest = '\0';
|
||||
|
||||
// Return the final string.
|
||||
aiString result = aiString((const char *)str);
|
||||
delete[] str;
|
||||
delete[] temp;
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
SIBImporter::SIBImporter()
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
SIBImporter::~SIBImporter()
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
|
||||
{
|
||||
return SimpleExtensionCheck(pFile, "sib");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiImporterDesc* SIBImporter::GetInfo () const
|
||||
{
|
||||
return &desc;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count)
|
||||
{
|
||||
mesh->pos.resize(count);
|
||||
|
||||
for (uint32_t n=0;n<count;n++) {
|
||||
mesh->pos[n].x = stream->GetF4();
|
||||
mesh->pos[n].y = stream->GetF4();
|
||||
mesh->pos[n].z = stream->GetF4();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadFaces(SIBMesh* mesh, StreamReaderLE* stream)
|
||||
{
|
||||
uint32_t ptIdx = 0;
|
||||
while (stream->GetRemainingSizeToLimit() > 0)
|
||||
{
|
||||
uint32_t numPoints = stream->GetU4();
|
||||
|
||||
// Store room for the N index channels, plus the point count.
|
||||
size_t pos = mesh->idx.size() + 1;
|
||||
mesh->idx.resize(pos + numPoints*N);
|
||||
mesh->idx[pos-1] = numPoints;
|
||||
uint32_t *idx = &mesh->idx[pos];
|
||||
|
||||
mesh->faceStart.push_back(pos-1);
|
||||
mesh->mtls.push_back(0);
|
||||
|
||||
// Read all the position data.
|
||||
// UV/normals will be supplied later.
|
||||
// Positions are supplied indexed already, so we preserve that
|
||||
// mapping. UVs are supplied uniquely, so we allocate unique indices.
|
||||
for (uint32_t n=0;n<numPoints;n++,idx+=N,ptIdx++)
|
||||
{
|
||||
uint32_t p = stream->GetU4();
|
||||
if (p >= mesh->pos.size())
|
||||
throw DeadlyImportError("Vertex index is out of range.");
|
||||
idx[POS] = p;
|
||||
idx[NRM] = ptIdx;
|
||||
idx[UV] = ptIdx;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate data channels for normals/UVs.
|
||||
mesh->nrm.resize(ptIdx, aiVector3D(0,0,0));
|
||||
mesh->uv.resize(ptIdx, aiVector3D(0,0,0));
|
||||
|
||||
mesh->numPts = ptIdx;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadUVs(SIBMesh* mesh, StreamReaderLE* stream)
|
||||
{
|
||||
while (stream->GetRemainingSizeToLimit() > 0)
|
||||
{
|
||||
uint32_t faceIdx = stream->GetU4();
|
||||
uint32_t numPoints = stream->GetU4();
|
||||
|
||||
if (faceIdx >= mesh->faceStart.size())
|
||||
throw DeadlyImportError("Invalid face index.");
|
||||
|
||||
uint32_t pos = mesh->faceStart[faceIdx];
|
||||
uint32_t *idx = &mesh->idx[pos + 1];
|
||||
|
||||
for (uint32_t n=0;n<numPoints;n++,idx+=N)
|
||||
{
|
||||
uint32_t id = idx[UV];
|
||||
mesh->uv[id].x = stream->GetF4();
|
||||
mesh->uv[id].y = stream->GetF4();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadMtls(SIBMesh* mesh, StreamReaderLE* stream)
|
||||
{
|
||||
// Material assignments are stored run-length encoded.
|
||||
// Also, we add 1 to each material so that we can use mtl #0
|
||||
// as the default material.
|
||||
uint32_t prevFace = stream->GetU4();
|
||||
uint32_t prevMtl = stream->GetU4() + 1;
|
||||
while (stream->GetRemainingSizeToLimit() > 0)
|
||||
{
|
||||
uint32_t face = stream->GetU4();
|
||||
uint32_t mtl = stream->GetU4() + 1;
|
||||
while (prevFace < face)
|
||||
{
|
||||
if (prevFace >= mesh->mtls.size())
|
||||
throw DeadlyImportError("Invalid face index.");
|
||||
mesh->mtls[prevFace++] = prevMtl;
|
||||
}
|
||||
|
||||
prevFace = face;
|
||||
prevMtl = mtl;
|
||||
}
|
||||
|
||||
while (prevFace < mesh->mtls.size())
|
||||
mesh->mtls[prevFace++] = prevMtl;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadAxis(aiMatrix4x4& axis, StreamReaderLE* stream)
|
||||
{
|
||||
axis.a4 = stream->GetF4();
|
||||
axis.b4 = stream->GetF4();
|
||||
axis.c4 = stream->GetF4();
|
||||
axis.d4 = 1;
|
||||
axis.a1 = stream->GetF4();
|
||||
axis.b1 = stream->GetF4();
|
||||
axis.c1 = stream->GetF4();
|
||||
axis.d1 = 0;
|
||||
axis.a2 = stream->GetF4();
|
||||
axis.b2 = stream->GetF4();
|
||||
axis.c2 = stream->GetF4();
|
||||
axis.d2 = 0;
|
||||
axis.a3 = stream->GetF4();
|
||||
axis.b3 = stream->GetF4();
|
||||
axis.c3 = stream->GetF4();
|
||||
axis.d3 = 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadEdges(SIBMesh* mesh, StreamReaderLE* stream)
|
||||
{
|
||||
while (stream->GetRemainingSizeToLimit() > 0)
|
||||
{
|
||||
uint32_t posA = stream->GetU4();
|
||||
uint32_t posB = stream->GetU4();
|
||||
GetEdge(mesh, posA, posB);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadCreases(SIBMesh* mesh, StreamReaderLE* stream)
|
||||
{
|
||||
while (stream->GetRemainingSizeToLimit() > 0)
|
||||
{
|
||||
uint32_t edge = stream->GetU4();
|
||||
if (edge >= mesh->edges.size())
|
||||
throw DeadlyImportError("SIB: Invalid edge index.");
|
||||
mesh->edges[edge].creased = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ConnectFaces(SIBMesh* mesh)
|
||||
{
|
||||
// Find faces connected to each edge.
|
||||
size_t numFaces = mesh->faceStart.size();
|
||||
for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++)
|
||||
{
|
||||
uint32_t *idx = &mesh->idx[mesh->faceStart[faceIdx]];
|
||||
uint32_t numPoints = *idx++;
|
||||
uint32_t prev = idx[(numPoints-1)*N+POS];
|
||||
|
||||
for (uint32_t i=0;i<numPoints;i++,idx+=N)
|
||||
{
|
||||
uint32_t next = idx[POS];
|
||||
|
||||
// Find this edge.
|
||||
SIBEdge& edge = GetEdge(mesh, prev, next);
|
||||
|
||||
// Link this face onto it.
|
||||
// This gives potentially undesirable normals when used
|
||||
// with non-2-manifold surfaces, but then so does Silo to begin with.
|
||||
if (edge.faceA == 0xffffffff)
|
||||
edge.faceA = faceIdx;
|
||||
else
|
||||
edge.faceB = faceIdx;
|
||||
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static aiVector3D CalculateVertexNormal(SIBMesh* mesh, uint32_t faceIdx, uint32_t pos,
|
||||
const std::vector<aiVector3D>& faceNormals)
|
||||
{
|
||||
// Creased edges complicate this. We need to find the start/end range of the
|
||||
// ring of faces that touch this position.
|
||||
// We do this in two passes. The first pass is to find the end of the range,
|
||||
// the second is to work backwards to the start and calculate the final normal.
|
||||
aiVector3D vtxNormal;
|
||||
for (int pass=0;pass<2;pass++)
|
||||
{
|
||||
vtxNormal = aiVector3D(0, 0, 0);
|
||||
uint32_t startFaceIdx = faceIdx;
|
||||
uint32_t prevFaceIdx = faceIdx;
|
||||
|
||||
// Process each connected face.
|
||||
while (true)
|
||||
{
|
||||
// Accumulate the face normal.
|
||||
vtxNormal += faceNormals[faceIdx];
|
||||
|
||||
uint32_t nextFaceIdx = 0xffffffff;
|
||||
|
||||
// Move to the next edge sharing this position.
|
||||
uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]];
|
||||
uint32_t numPoints = *idx++;
|
||||
uint32_t posA = idx[(numPoints-1)*N+POS];
|
||||
for (uint32_t n=0;n<numPoints;n++,idx+=N)
|
||||
{
|
||||
uint32_t posB = idx[POS];
|
||||
|
||||
// Test if this edge shares our target position.
|
||||
if (posA == pos || posB == pos)
|
||||
{
|
||||
SIBEdge& edge = GetEdge(mesh, posA, posB);
|
||||
|
||||
// Move to whichever side we didn't just come from.
|
||||
if (!edge.creased) {
|
||||
if (edge.faceA != prevFaceIdx && edge.faceA != faceIdx)
|
||||
nextFaceIdx = edge.faceA;
|
||||
else if (edge.faceB != prevFaceIdx && edge.faceB != faceIdx)
|
||||
nextFaceIdx = edge.faceB;
|
||||
}
|
||||
}
|
||||
|
||||
posA = posB;
|
||||
}
|
||||
|
||||
// Stop once we hit either an creased/unconnected edge, or we
|
||||
// wrapped around and hit our start point.
|
||||
if (nextFaceIdx == 0xffffffff || nextFaceIdx == startFaceIdx)
|
||||
break;
|
||||
|
||||
prevFaceIdx = faceIdx;
|
||||
faceIdx = nextFaceIdx;
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize it.
|
||||
float len = vtxNormal.Length();
|
||||
if (len > 0.000000001f)
|
||||
vtxNormal /= len;
|
||||
return vtxNormal;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void CalculateNormals(SIBMesh* mesh)
|
||||
{
|
||||
size_t numFaces = mesh->faceStart.size();
|
||||
|
||||
// Calculate face normals.
|
||||
std::vector<aiVector3D> faceNormals(numFaces);
|
||||
for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++)
|
||||
{
|
||||
uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]];
|
||||
uint32_t numPoints = *idx++;
|
||||
|
||||
aiVector3D faceNormal(0, 0, 0);
|
||||
|
||||
uint32_t *prev = &idx[(numPoints-1)*N];
|
||||
|
||||
for (uint32_t i=0;i<numPoints;i++)
|
||||
{
|
||||
uint32_t *next = &idx[i*N];
|
||||
|
||||
faceNormal += mesh->pos[prev[POS]] ^ mesh->pos[next[POS]];
|
||||
prev = next;
|
||||
}
|
||||
|
||||
faceNormals[faceIdx] = faceNormal;
|
||||
}
|
||||
|
||||
// Calculate vertex normals.
|
||||
for (size_t faceIdx=0;faceIdx<numFaces;faceIdx++)
|
||||
{
|
||||
uint32_t* idx = &mesh->idx[mesh->faceStart[faceIdx]];
|
||||
uint32_t numPoints = *idx++;
|
||||
|
||||
for (uint32_t i=0;i<numPoints;i++)
|
||||
{
|
||||
uint32_t pos = idx[i*N+POS];
|
||||
uint32_t nrm = idx[i*N+NRM];
|
||||
aiVector3D vtxNorm = CalculateVertexNormal(mesh, faceIdx, pos, faceNormals);
|
||||
mesh->nrm[nrm] = vtxNorm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
struct TempMesh
|
||||
{
|
||||
std::vector<aiVector3D> vtx;
|
||||
std::vector<aiVector3D> nrm;
|
||||
std::vector<aiVector3D> uv;
|
||||
std::vector<aiFace> faces;
|
||||
};
|
||||
|
||||
static void ReadShape(SIB* sib, StreamReaderLE* stream)
|
||||
{
|
||||
SIBMesh smesh;
|
||||
aiString name;
|
||||
|
||||
while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk))
|
||||
{
|
||||
SIBChunk chunk = ReadChunk(stream);
|
||||
unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
|
||||
|
||||
switch (chunk.Tag)
|
||||
{
|
||||
case TAG('M','I','R','P'): break; // mirror plane maybe?
|
||||
case TAG('I','M','R','P'): break; // instance mirror? (not supported here yet)
|
||||
case TAG('D','I','N','F'): break; // display info, not needed
|
||||
case TAG('P','I','N','F'): break; // ?
|
||||
case TAG('V','M','I','R'): break; // ?
|
||||
case TAG('F','M','I','R'): break; // ?
|
||||
case TAG('T','X','S','M'): break; // ?
|
||||
case TAG('F','A','H','S'): break; // ?
|
||||
case TAG('V','R','T','S'): ReadVerts(&smesh, stream, chunk.Size/12); break;
|
||||
case TAG('F','A','C','S'): ReadFaces(&smesh, stream); break;
|
||||
case TAG('F','T','V','S'): ReadUVs(&smesh, stream); break;
|
||||
case TAG('S','N','A','M'): name = ReadString(stream, chunk.Size/2); break;
|
||||
case TAG('F','A','M','A'): ReadMtls(&smesh, stream); break;
|
||||
case TAG('A','X','I','S'): ReadAxis(smesh.axis, stream); break;
|
||||
case TAG('E','D','G','S'): ReadEdges(&smesh, stream); break;
|
||||
case TAG('E','C','R','S'): ReadCreases(&smesh, stream); break;
|
||||
default: UnknownChunk(stream, chunk); break;
|
||||
}
|
||||
|
||||
stream->SetCurrentPos(stream->GetReadLimit());
|
||||
stream->SetReadLimit(oldLimit);
|
||||
}
|
||||
|
||||
assert(smesh.faceStart.size() == smesh.mtls.size()); // sanity check
|
||||
|
||||
// Silo doesn't store any normals in the file - we need to compute
|
||||
// them ourselves. We can't let AssImp handle it as AssImp doesn't
|
||||
// know about our creased edges.
|
||||
ConnectFaces(&smesh);
|
||||
CalculateNormals(&smesh);
|
||||
|
||||
// Construct the transforms.
|
||||
aiMatrix4x4 worldToLocal = smesh.axis;
|
||||
worldToLocal.Inverse();
|
||||
aiMatrix4x4 worldToLocalN = worldToLocal;
|
||||
worldToLocalN.a4 = worldToLocalN.b4 = worldToLocalN.c4 = 0.0f;
|
||||
worldToLocalN.Inverse().Transpose();
|
||||
|
||||
// Allocate final mesh data.
|
||||
// We'll allocate one mesh for each material. (we'll strip unused ones after)
|
||||
std::vector<TempMesh> meshes(sib->mtls.size());
|
||||
|
||||
// Un-index the source data and apply to each vertex.
|
||||
for (unsigned fi=0;fi<smesh.faceStart.size();fi++)
|
||||
{
|
||||
uint32_t start = smesh.faceStart[fi];
|
||||
uint32_t mtl = smesh.mtls[fi];
|
||||
uint32_t *idx = &smesh.idx[start];
|
||||
|
||||
if (mtl >= meshes.size())
|
||||
{
|
||||
DefaultLogger::get()->error("SIB: Face material index is invalid.");
|
||||
mtl = 0;
|
||||
}
|
||||
|
||||
TempMesh& dest = meshes[mtl];
|
||||
|
||||
aiFace face;
|
||||
face.mNumIndices = *idx++;
|
||||
face.mIndices = new unsigned[face.mNumIndices];
|
||||
for (unsigned pt=0;pt<face.mNumIndices;pt++,idx+=N)
|
||||
{
|
||||
size_t vtxIdx = dest.vtx.size();
|
||||
face.mIndices[pt] = vtxIdx;
|
||||
|
||||
// De-index it. We don't need to validate here as
|
||||
// we did it when creating the data.
|
||||
aiVector3D pos = smesh.pos[idx[POS]];
|
||||
aiVector3D nrm = smesh.nrm[idx[NRM]];
|
||||
aiVector3D uv = smesh.uv[idx[UV]];
|
||||
|
||||
// The verts are supplied in world-space, so let's
|
||||
// transform them back into the local space of this mesh:
|
||||
pos = worldToLocal * pos;
|
||||
nrm = worldToLocalN * nrm;
|
||||
|
||||
dest.vtx.push_back(pos);
|
||||
dest.nrm.push_back(nrm);
|
||||
dest.uv.push_back(uv);
|
||||
}
|
||||
dest.faces.push_back(face);
|
||||
}
|
||||
|
||||
SIBObject obj;
|
||||
obj.name = name;
|
||||
obj.axis = smesh.axis;
|
||||
obj.meshIdx = sib->meshes.size();
|
||||
|
||||
// Now that we know the size of everything,
|
||||
// we can build the final one-material-per-mesh data.
|
||||
for (size_t n=0;n<meshes.size();n++)
|
||||
{
|
||||
TempMesh& src = meshes[n];
|
||||
if (src.faces.empty())
|
||||
continue;
|
||||
|
||||
aiMesh* mesh = new aiMesh;
|
||||
mesh->mName = name;
|
||||
mesh->mNumFaces = src.faces.size();
|
||||
mesh->mFaces = new aiFace[mesh->mNumFaces];
|
||||
mesh->mNumVertices = src.vtx.size();
|
||||
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
||||
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
||||
mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
||||
mesh->mNumUVComponents[0] = 2;
|
||||
mesh->mMaterialIndex = n;
|
||||
|
||||
for (unsigned i=0;i<mesh->mNumVertices;i++)
|
||||
{
|
||||
mesh->mVertices[i] = src.vtx[i];
|
||||
mesh->mNormals[i] = src.nrm[i];
|
||||
mesh->mTextureCoords[0][i] = src.uv[i];
|
||||
}
|
||||
for (unsigned i=0;i<mesh->mNumFaces;i++)
|
||||
{
|
||||
mesh->mFaces[i] = src.faces[i];
|
||||
}
|
||||
|
||||
sib->meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
obj.meshCount = sib->meshes.size() - obj.meshIdx;
|
||||
sib->objs.push_back(obj);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadMaterial(SIB* sib, StreamReaderLE* stream)
|
||||
{
|
||||
aiColor3D diff = ReadColor(stream);
|
||||
aiColor3D ambi = ReadColor(stream);
|
||||
aiColor3D spec = ReadColor(stream);
|
||||
aiColor3D emis = ReadColor(stream);
|
||||
float shiny = (float)stream->GetU4();
|
||||
|
||||
uint32_t nameLen = stream->GetU4();
|
||||
aiString name = ReadString(stream, nameLen/2);
|
||||
uint32_t texLen = stream->GetU4();
|
||||
aiString tex = ReadString(stream, texLen/2);
|
||||
|
||||
aiMaterial* mtl = new aiMaterial();
|
||||
mtl->AddProperty(&diff, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
mtl->AddProperty(&ambi, 1, AI_MATKEY_COLOR_AMBIENT);
|
||||
mtl->AddProperty(&spec, 1, AI_MATKEY_COLOR_SPECULAR);
|
||||
mtl->AddProperty(&emis, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||
mtl->AddProperty(&shiny, 1, AI_MATKEY_SHININESS);
|
||||
mtl->AddProperty(&name, AI_MATKEY_NAME);
|
||||
if (tex.length > 0) {
|
||||
mtl->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
mtl->AddProperty(&tex, AI_MATKEY_TEXTURE_AMBIENT(0));
|
||||
}
|
||||
|
||||
sib->mtls.push_back(mtl);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadLightInfo(aiLight* light, StreamReaderLE* stream)
|
||||
{
|
||||
uint32_t type = stream->GetU4();
|
||||
switch (type) {
|
||||
case 0: light->mType = aiLightSource_POINT; break;
|
||||
case 1: light->mType = aiLightSource_SPOT; break;
|
||||
case 2: light->mType = aiLightSource_DIRECTIONAL; break;
|
||||
default: light->mType = aiLightSource_UNDEFINED; break;
|
||||
}
|
||||
|
||||
light->mPosition.x = stream->GetF4();
|
||||
light->mPosition.y = stream->GetF4();
|
||||
light->mPosition.z = stream->GetF4();
|
||||
light->mDirection.x = stream->GetF4();
|
||||
light->mDirection.y = stream->GetF4();
|
||||
light->mDirection.z = stream->GetF4();
|
||||
light->mColorDiffuse = ReadColor(stream);
|
||||
light->mColorAmbient = ReadColor(stream);
|
||||
light->mColorSpecular = ReadColor(stream);
|
||||
float spotExponent = stream->GetF4();
|
||||
float spotCutoff = stream->GetF4();
|
||||
light->mAttenuationConstant = stream->GetF4();
|
||||
light->mAttenuationLinear = stream->GetF4();
|
||||
light->mAttenuationQuadratic = stream->GetF4();
|
||||
|
||||
// Silo uses the OpenGL default lighting model for it's
|
||||
// spot cutoff/exponent. AssImp unfortunately, does not.
|
||||
// Let's try and approximate it by solving for the
|
||||
// 99% and 1% percentiles.
|
||||
// OpenGL: I = cos(angle)^E
|
||||
// Solving: angle = acos(I^(1/E))
|
||||
float E = 1.0f / std::max(spotExponent, 0.00001f);
|
||||
float inner = acosf(powf(0.99f, E));
|
||||
float outer = acosf(powf(0.01f, E));
|
||||
|
||||
// Apply the cutoff.
|
||||
outer = std::min(outer, AI_DEG_TO_RAD(spotCutoff));
|
||||
|
||||
light->mAngleInnerCone = std::min(inner, outer);
|
||||
light->mAngleOuterCone = outer;
|
||||
}
|
||||
|
||||
static void ReadLight(SIB* sib, StreamReaderLE* stream)
|
||||
{
|
||||
aiLight* light = new aiLight();
|
||||
|
||||
while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk))
|
||||
{
|
||||
SIBChunk chunk = ReadChunk(stream);
|
||||
unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
|
||||
|
||||
switch (chunk.Tag)
|
||||
{
|
||||
case TAG('L','N','F','O'): ReadLightInfo(light, stream); break;
|
||||
case TAG('S','N','A','M'): light->mName = ReadString(stream, chunk.Size/2); break;
|
||||
default: UnknownChunk(stream, chunk); break;
|
||||
}
|
||||
|
||||
stream->SetCurrentPos(stream->GetReadLimit());
|
||||
stream->SetReadLimit(oldLimit);
|
||||
}
|
||||
|
||||
sib->lights.push_back(light);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void ReadScale(aiMatrix4x4& axis, StreamReaderLE* stream)
|
||||
{
|
||||
aiMatrix4x4 scale;
|
||||
scale.a1 = stream->GetF4();
|
||||
scale.b1 = stream->GetF4();
|
||||
scale.c1 = stream->GetF4();
|
||||
scale.d1 = stream->GetF4();
|
||||
scale.a2 = stream->GetF4();
|
||||
scale.b2 = stream->GetF4();
|
||||
scale.c2 = stream->GetF4();
|
||||
scale.d2 = stream->GetF4();
|
||||
scale.a3 = stream->GetF4();
|
||||
scale.b3 = stream->GetF4();
|
||||
scale.c3 = stream->GetF4();
|
||||
scale.d3 = stream->GetF4();
|
||||
scale.a4 = stream->GetF4();
|
||||
scale.b4 = stream->GetF4();
|
||||
scale.c4 = stream->GetF4();
|
||||
scale.d4 = stream->GetF4();
|
||||
|
||||
axis = axis * scale;
|
||||
}
|
||||
|
||||
static void ReadInstance(SIB* sib, StreamReaderLE* stream)
|
||||
{
|
||||
SIBObject inst;
|
||||
uint32_t shapeIndex = 0;
|
||||
|
||||
while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk))
|
||||
{
|
||||
SIBChunk chunk = ReadChunk(stream);
|
||||
unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
|
||||
|
||||
switch (chunk.Tag)
|
||||
{
|
||||
case TAG('D','I','N','F'): break; // display info, not needed
|
||||
case TAG('P','I','N','F'): break; // ?
|
||||
case TAG('A','X','I','S'): ReadAxis(inst.axis, stream); break;
|
||||
case TAG('I','N','S','I'): shapeIndex = stream->GetU4(); break;
|
||||
case TAG('S','M','T','X'): ReadScale(inst.axis, stream); break;
|
||||
case TAG('S','N','A','M'): inst.name = ReadString(stream, chunk.Size/2); break;
|
||||
default: UnknownChunk(stream, chunk); break;
|
||||
}
|
||||
|
||||
stream->SetCurrentPos(stream->GetReadLimit());
|
||||
stream->SetReadLimit(oldLimit);
|
||||
}
|
||||
|
||||
if (shapeIndex >= sib->objs.size())
|
||||
throw DeadlyImportError("SIB: Invalid shape index.");
|
||||
|
||||
const SIBObject& src = sib->objs[shapeIndex];
|
||||
inst.meshIdx = src.meshIdx;
|
||||
inst.meshCount = src.meshCount;
|
||||
sib->insts.push_back(inst);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void CheckVersion(StreamReaderLE* stream)
|
||||
{
|
||||
uint32_t version = stream->GetU4();
|
||||
if (version != 1)
|
||||
throw DeadlyImportError("SIB: Unsupported file version.");
|
||||
}
|
||||
|
||||
static void ReadScene(SIB* sib, StreamReaderLE* stream)
|
||||
{
|
||||
// Parse each chunk in turn.
|
||||
while (stream->GetRemainingSizeToLimit() >= sizeof(SIBChunk))
|
||||
{
|
||||
SIBChunk chunk = ReadChunk(stream);
|
||||
unsigned oldLimit = stream->SetReadLimit(stream->GetCurrentPos() + chunk.Size);
|
||||
|
||||
switch (chunk.Tag)
|
||||
{
|
||||
case TAG('H','E','A','D'): CheckVersion(stream); break;
|
||||
case TAG('S','H','A','P'): ReadShape(sib, stream); break;
|
||||
case TAG('G','R','P','S'): break; // group assignment, we don't import this
|
||||
case TAG('T','E','X','P'): break; // ?
|
||||
case TAG('I','N','S','T'): ReadInstance(sib, stream); break;
|
||||
case TAG('M','A','T','R'): ReadMaterial(sib, stream); break;
|
||||
case TAG('L','G','H','T'): ReadLight(sib, stream); break;
|
||||
default: UnknownChunk(stream, chunk); break;
|
||||
}
|
||||
|
||||
stream->SetCurrentPos(stream->GetReadLimit());
|
||||
stream->SetReadLimit(oldLimit);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void SIBImporter::InternReadFile(const std::string& pFile,
|
||||
aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
StreamReaderLE stream(pIOHandler->Open(pFile, "rb"));
|
||||
|
||||
// We should have at least one chunk
|
||||
if (stream.GetRemainingSize() < 16)
|
||||
throw DeadlyImportError("SIB file is either empty or corrupt: " + pFile);
|
||||
|
||||
SIB sib;
|
||||
|
||||
// Default material.
|
||||
aiMaterial* defmtl = new aiMaterial;
|
||||
aiString defname = aiString(AI_DEFAULT_MATERIAL_NAME);
|
||||
defmtl->AddProperty(&defname, AI_MATKEY_NAME);
|
||||
sib.mtls.push_back(defmtl);
|
||||
|
||||
// Read it all.
|
||||
ReadScene(&sib, &stream);
|
||||
|
||||
// Join the instances and objects together.
|
||||
size_t firstInst = sib.objs.size();
|
||||
sib.objs.insert(sib.objs.end(), sib.insts.begin(), sib.insts.end());
|
||||
sib.insts.clear();
|
||||
|
||||
// Transfer to the aiScene.
|
||||
pScene->mNumMaterials = sib.mtls.size();
|
||||
pScene->mNumMeshes = sib.meshes.size();
|
||||
pScene->mNumLights = sib.lights.size();
|
||||
pScene->mMaterials = new aiMaterial* [pScene->mNumMaterials];
|
||||
pScene->mMeshes = new aiMesh* [pScene->mNumMeshes];
|
||||
pScene->mLights = new aiLight* [pScene->mNumLights];
|
||||
if (pScene->mNumMaterials)
|
||||
memcpy(pScene->mMaterials, &sib.mtls[0], sizeof(aiMaterial*) * pScene->mNumMaterials);
|
||||
if (pScene->mNumMeshes)
|
||||
memcpy(pScene->mMeshes, &sib.meshes[0], sizeof(aiMesh*) * pScene->mNumMeshes);
|
||||
if (pScene->mNumLights)
|
||||
memcpy(pScene->mLights, &sib.lights[0], sizeof(aiLight*) * pScene->mNumLights);
|
||||
|
||||
// Construct the root node.
|
||||
size_t childIdx = 0;
|
||||
aiNode *root = new aiNode();
|
||||
root->mName.Set("<SIBRoot>");
|
||||
root->mNumChildren = sib.objs.size() + sib.lights.size();
|
||||
root->mChildren = new aiNode* [root->mNumChildren];
|
||||
pScene->mRootNode = root;
|
||||
|
||||
// Add nodes for each object.
|
||||
for (size_t n=0;n<sib.objs.size();n++)
|
||||
{
|
||||
SIBObject& obj = sib.objs[n];
|
||||
aiNode* node = new aiNode;
|
||||
root->mChildren[childIdx++] = node;
|
||||
node->mName = obj.name;
|
||||
node->mParent = root;
|
||||
node->mTransformation = obj.axis;
|
||||
|
||||
node->mNumMeshes = obj.meshCount;
|
||||
node->mMeshes = new unsigned[node->mNumMeshes];
|
||||
for (unsigned i=0;i<node->mNumMeshes;i++)
|
||||
node->mMeshes[i] = obj.meshIdx + i;
|
||||
|
||||
// Mark instanced objects as being so.
|
||||
if (n >= firstInst)
|
||||
{
|
||||
node->mMetaData = new aiMetadata;
|
||||
node->mMetaData->mNumProperties = 1;
|
||||
node->mMetaData->mKeys = new aiString[1];
|
||||
node->mMetaData->mValues = new aiMetadataEntry[1];
|
||||
node->mMetaData->Set(0, "IsInstance", true);
|
||||
}
|
||||
}
|
||||
|
||||
// Add nodes for each light.
|
||||
// (no transformation as the light is already in world space)
|
||||
for (size_t n=0;n<sib.lights.size();n++)
|
||||
{
|
||||
aiLight* light = sib.lights[n];
|
||||
aiNode* node = new aiNode;
|
||||
root->mChildren[childIdx++] = node;
|
||||
node->mName = light->mName;
|
||||
node->mParent = root;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_SIB_IMPORTER
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2015, assimp 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 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 SIBImporter.h
|
||||
* @brief Declaration of the SIB importer class.
|
||||
*/
|
||||
#ifndef AI_SIBIMPORTER_H_INCLUDED
|
||||
#define AI_SIBIMPORTER_H_INCLUDED
|
||||
|
||||
#include "BaseImporter.h"
|
||||
#include "../include/assimp/types.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Importer class for the Nevercenter Silo SIB scene format
|
||||
*/
|
||||
class SIBImporter : public BaseImporter
|
||||
{
|
||||
public:
|
||||
SIBImporter();
|
||||
~SIBImporter();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Returns whether the class can handle the format of the given file.
|
||||
* See BaseImporter::CanRead() for details.
|
||||
*/
|
||||
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
|
||||
bool checkSig) const;
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Return importer meta information.
|
||||
* See #BaseImporter::GetInfo for the details
|
||||
*/
|
||||
const aiImporterDesc* GetInfo () const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Imports the given file into the given scene structure.
|
||||
* See BaseImporter::InternReadFile() for details
|
||||
*/
|
||||
void InternReadFile( const std::string& pFile, aiScene* pScene,
|
||||
IOSystem* pIOHandler);
|
||||
|
||||
private:
|
||||
|
||||
struct MeshInformation
|
||||
{
|
||||
explicit MeshInformation(const std::string& _name)
|
||||
: name(_name)
|
||||
{
|
||||
vertices.reserve(100);
|
||||
colors.reserve(100);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
|
||||
std::vector<aiVector3D> vertices;
|
||||
std::vector<aiColor4D> colors;
|
||||
};
|
||||
|
||||
struct GroupInformation
|
||||
{
|
||||
explicit GroupInformation(const std::string& _name)
|
||||
: name(_name)
|
||||
{
|
||||
meshes.reserve(10);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::vector<MeshInformation> meshes;
|
||||
};
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_SIBIMPORTER_H_INCLUDED
|
|
@ -253,24 +253,26 @@ public:
|
|||
*
|
||||
* @param limit Maximum number of bytes to be read from
|
||||
* the beginning of the file. Specifying UINT_MAX
|
||||
* resets the limit to the original end of the stream. */
|
||||
void SetReadLimit(unsigned int _limit) {
|
||||
|
||||
* resets the limit to the original end of the stream.
|
||||
* Returns the previously set limit. */
|
||||
unsigned int SetReadLimit(unsigned int _limit) {
|
||||
unsigned int prev = GetReadLimit();
|
||||
if (UINT_MAX == _limit) {
|
||||
limit = end;
|
||||
return;
|
||||
return prev;
|
||||
}
|
||||
|
||||
limit = buffer + _limit;
|
||||
if (limit > end) {
|
||||
throw DeadlyImportError("StreamReader: Invalid read limit");
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Get the current read limit in bytes. Reading over this limit
|
||||
* accidentially raises an exception. */
|
||||
int GetReadLimit() const {
|
||||
unsigned int GetReadLimit() const {
|
||||
return (unsigned int)(limit - buffer);
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Made by me (Richard Mitton).
|
||||
I waive all rights to this and release it into the public domain.
|
||||
Do with it as you wish.
|
Loading…
Reference in New Issue