commit
9eba139feb
|
@ -0,0 +1,560 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2012, 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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||
|
||||
#include "3DSExporter.h"
|
||||
#include "3DSLoader.h"
|
||||
#include "SceneCombiner.h"
|
||||
#include "SplitLargeMeshes.h"
|
||||
|
||||
using namespace Assimp;
|
||||
namespace Assimp {
|
||||
|
||||
namespace {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// Scope utility to write a 3DS file chunk.
|
||||
//
|
||||
// Upon construction, the chunk header is written with the chunk type (flags)
|
||||
// filled out, but the chunk size left empty. Upon destruction, the correct chunk
|
||||
// size based on the then-position of the output stream cursor is filled in.
|
||||
class ChunkWriter {
|
||||
enum {
|
||||
CHUNK_SIZE_NOT_SET = 0xdeadbeef
|
||||
, SIZE_OFFSET = 2
|
||||
};
|
||||
public:
|
||||
|
||||
ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type)
|
||||
: writer(writer)
|
||||
{
|
||||
chunk_start_pos = writer.GetCurrentPos();
|
||||
writer.PutU2(chunk_type);
|
||||
writer.PutU4(CHUNK_SIZE_NOT_SET);
|
||||
}
|
||||
|
||||
~ChunkWriter() {
|
||||
std::size_t head_pos = writer.GetCurrentPos();
|
||||
|
||||
ai_assert(head_pos > chunk_start_pos);
|
||||
const std::size_t chunk_size = head_pos - chunk_start_pos;
|
||||
|
||||
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
|
||||
writer.PutU4(chunk_size);
|
||||
writer.SetCurrentPos(head_pos);
|
||||
}
|
||||
|
||||
private:
|
||||
StreamWriterLE& writer;
|
||||
std::size_t chunk_start_pos;
|
||||
};
|
||||
|
||||
|
||||
// Return an unique name for a given |mesh| attached to |node| that
|
||||
// preserves the mesh's given name if it has one. |index| is the index
|
||||
// of the mesh in |aiScene::mMeshes|.
|
||||
std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) {
|
||||
static const std::string underscore = "_";
|
||||
char postfix[10] = {0};
|
||||
ASSIMP_itoa10(postfix, index);
|
||||
|
||||
std::string result = node.mName.C_Str();
|
||||
if (mesh.mName.length > 0) {
|
||||
result += underscore + mesh.mName.C_Str();
|
||||
}
|
||||
return result + underscore + postfix;
|
||||
}
|
||||
|
||||
// Return an unique name for a given |mat| with original position |index|
|
||||
// in |aiScene::mMaterials|. The name preserves the original material
|
||||
// name if possible.
|
||||
std::string GetMaterialName(const aiMaterial& mat, unsigned int index) {
|
||||
static const std::string underscore = "_";
|
||||
char postfix[10] = {0};
|
||||
ASSIMP_itoa10(postfix, index);
|
||||
|
||||
aiString mat_name;
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
|
||||
return mat_name.C_Str() + underscore + postfix;
|
||||
}
|
||||
|
||||
return "Material" + underscore + postfix;
|
||||
}
|
||||
|
||||
// Collect world transformations for each node
|
||||
void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
|
||||
const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
|
||||
trafos[node] = parent * node->mTransformation;
|
||||
for (unsigned int i = 0; i < node->mNumChildren; ++i) {
|
||||
CollectTrafos(node->mChildren[i], trafos);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a flat list of the meshes (by index) assigned to each node
|
||||
void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) {
|
||||
for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
|
||||
meshes.insert(std::make_pair(node, node->mMeshes[i]));
|
||||
}
|
||||
for (unsigned int i = 0; i < node->mNumChildren; ++i) {
|
||||
CollectMeshes(node->mChildren[i], meshes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
|
||||
void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
|
||||
{
|
||||
boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
|
||||
if(outfile == NULL) {
|
||||
throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile));
|
||||
}
|
||||
|
||||
// TODO: This extra copy should be avoided and all of this made a preprocess
|
||||
// requirement of the 3DS exporter.
|
||||
//
|
||||
// 3DS meshes can be max 0xffff (16 Bit) vertices and faces, respectively.
|
||||
// SplitLargeMeshes can do this, but it requires the correct limit to be set
|
||||
// which is not possible with the current way of specifying preprocess steps
|
||||
// in |Exporter::ExportFormatEntry|.
|
||||
aiScene* scenecopy_tmp;
|
||||
SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
|
||||
std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
|
||||
|
||||
SplitLargeMeshesProcess_Triangle tri_splitter;
|
||||
tri_splitter.SetLimit(0xffff);
|
||||
tri_splitter.Execute(scenecopy.get());
|
||||
|
||||
SplitLargeMeshesProcess_Vertex vert_splitter;
|
||||
vert_splitter.SetLimit(0xffff);
|
||||
vert_splitter.Execute(scenecopy.get());
|
||||
|
||||
// Invoke the actual exporter
|
||||
Discreet3DSExporter exporter(outfile, scenecopy.get());
|
||||
}
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* scene)
|
||||
: scene(scene)
|
||||
, writer(outfile)
|
||||
{
|
||||
CollectTrafos(scene->mRootNode, trafos);
|
||||
CollectMeshes(scene->mRootNode, meshes);
|
||||
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
|
||||
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
|
||||
WriteMeshes();
|
||||
WriteMaterials();
|
||||
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
|
||||
writer.PutF4(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
|
||||
WriteHierarchy(*scene->mRootNode, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level)
|
||||
{
|
||||
// 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
|
||||
|
||||
// Assimp node names are unique and distinct from all mesh-node
|
||||
// names we generate; thus we can use them as-is
|
||||
WriteString(node.mName);
|
||||
|
||||
// Two unknown int16 values - it is even unclear if 0 is a safe value
|
||||
// but luckily importers do not know better either.
|
||||
writer.PutI4(0);
|
||||
|
||||
int16_t hierarchy_pos = static_cast<int16_t>(seq);
|
||||
if (sibling_level != -1) {
|
||||
hierarchy_pos = sibling_level;
|
||||
}
|
||||
|
||||
// Write the hierarchy position
|
||||
writer.PutI2(hierarchy_pos);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: write transformation chunks
|
||||
|
||||
++seq;
|
||||
sibling_level = seq;
|
||||
|
||||
// Write all children
|
||||
for (unsigned int i = 0; i < node.mNumChildren; ++i) {
|
||||
seq = WriteHierarchy(*node.mChildren[i], seq, i == 0 ? -1 : sibling_level);
|
||||
}
|
||||
|
||||
// Write all meshes as separate nodes to be able to reference the meshes by name
|
||||
for (unsigned int i = 0; i < node.mNumMeshes; ++i) {
|
||||
const bool first_child = node.mNumChildren == 0 && i == 0;
|
||||
|
||||
const unsigned int mesh_idx = node.mMeshes[i];
|
||||
const aiMesh& mesh = *scene->mMeshes[mesh_idx];
|
||||
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
|
||||
WriteString(GetMeshName(mesh, mesh_idx, node));
|
||||
|
||||
writer.PutI4(0);
|
||||
writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level));
|
||||
++seq;
|
||||
}
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Discreet3DSExporter::WriteMaterials()
|
||||
{
|
||||
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
|
||||
const aiMaterial& mat = *scene->mMaterials[i];
|
||||
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME);
|
||||
const std::string& name = GetMaterialName(mat, i);
|
||||
WriteString(name);
|
||||
}
|
||||
|
||||
aiColor3D color;
|
||||
if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
|
||||
WriteColor(color);
|
||||
}
|
||||
|
||||
if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
|
||||
WriteColor(color);
|
||||
}
|
||||
|
||||
if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
|
||||
WriteColor(color);
|
||||
}
|
||||
|
||||
if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
|
||||
WriteColor(color);
|
||||
}
|
||||
|
||||
aiShadingMode shading_mode;
|
||||
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
|
||||
|
||||
Discreet3DS::shadetype3ds shading_mode_out;
|
||||
switch(shading_mode) {
|
||||
case aiShadingMode_Flat:
|
||||
case aiShadingMode_NoShading:
|
||||
shading_mode_out = Discreet3DS::Flat;
|
||||
break;
|
||||
|
||||
case aiShadingMode_Gouraud:
|
||||
case aiShadingMode_Toon:
|
||||
case aiShadingMode_OrenNayar:
|
||||
case aiShadingMode_Minnaert:
|
||||
shading_mode_out = Discreet3DS::Gouraud;
|
||||
break;
|
||||
|
||||
case aiShadingMode_Phong:
|
||||
case aiShadingMode_Blinn:
|
||||
case aiShadingMode_CookTorrance:
|
||||
case aiShadingMode_Fresnel:
|
||||
shading_mode_out = Discreet3DS::Phong;
|
||||
break;
|
||||
|
||||
default:
|
||||
ai_assert(false);
|
||||
};
|
||||
writer.PutU2(static_cast<uint16_t>(shading_mode_out));
|
||||
}
|
||||
|
||||
|
||||
float f;
|
||||
if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS);
|
||||
WritePercentChunk(f);
|
||||
}
|
||||
|
||||
if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT);
|
||||
WritePercentChunk(f);
|
||||
}
|
||||
|
||||
int twosided;
|
||||
if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
|
||||
writer.PutI2(1);
|
||||
}
|
||||
|
||||
WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
|
||||
WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
|
||||
WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
|
||||
WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
|
||||
WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP);
|
||||
WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP);
|
||||
WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags)
|
||||
{
|
||||
aiString path;
|
||||
aiTextureMapMode map_mode[2] = {
|
||||
aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
|
||||
};
|
||||
float blend = 1.0f;
|
||||
if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: handle embedded textures properly
|
||||
if (path.data[0] == '*') {
|
||||
DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
|
||||
return;
|
||||
}
|
||||
|
||||
ChunkWriter chunk(writer, chunk_flags);
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
|
||||
WriteString(path);
|
||||
}
|
||||
|
||||
WritePercentChunk(blend);
|
||||
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
|
||||
uint16_t val = 0; // WRAP
|
||||
if (map_mode[0] == aiTextureMapMode_Mirror) {
|
||||
val = 0x2;
|
||||
}
|
||||
else if (map_mode[0] == aiTextureMapMode_Decal) {
|
||||
val = 0x10;
|
||||
}
|
||||
writer.PutU2(val);
|
||||
}
|
||||
// TODO: export texture transformation (i.e. UV offset, scale, rotation)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Discreet3DSExporter::WriteMeshes()
|
||||
{
|
||||
// NOTE: 3DS allows for instances. However:
|
||||
// i) not all importers support reading them
|
||||
// ii) instances are not as flexible as they are in assimp, in particular,
|
||||
// nodes can carry (and instance) only one mesh.
|
||||
//
|
||||
// This exporter currently deep clones all instanced meshes, i.e. for each mesh
|
||||
// attached to a node a full TRIMESH chunk is written to the file.
|
||||
//
|
||||
// Furthermore, the TRIMESH is transformed into world space so that it will
|
||||
// appear correctly if importers don't read the scene hierarchy at all.
|
||||
for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) {
|
||||
const aiNode& node = *(*it).first;
|
||||
const unsigned int mesh_idx = (*it).second;
|
||||
|
||||
const aiMesh& mesh = *scene->mMeshes[mesh_idx];
|
||||
|
||||
// This should not happen if the SLM step is correctly executed
|
||||
// before the scene is handed to the exporter
|
||||
ai_assert(mesh.mNumVertices <= 0xffff);
|
||||
ai_assert(mesh.mNumFaces <= 0xffff);
|
||||
|
||||
const aiMatrix4x4& trafo = trafos[&node];
|
||||
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK);
|
||||
|
||||
// Mesh name is tied to the node it is attached to so it can later be referenced
|
||||
const std::string& name = GetMeshName(mesh, mesh_idx, node);
|
||||
WriteString(name);
|
||||
|
||||
|
||||
// TRIMESH chunk
|
||||
ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH);
|
||||
|
||||
// Vertices in world space
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
|
||||
|
||||
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
|
||||
writer.PutU2(count);
|
||||
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
|
||||
const aiVector3D& v = trafo * mesh.mVertices[i];
|
||||
writer.PutF4(v.x);
|
||||
writer.PutF4(v.y);
|
||||
writer.PutF4(v.z);
|
||||
}
|
||||
}
|
||||
|
||||
// UV coordinates
|
||||
if (mesh.HasTextureCoords(0)) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
|
||||
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
|
||||
writer.PutU2(count);
|
||||
|
||||
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
|
||||
const aiVector3D& v = mesh.mTextureCoords[0][i];
|
||||
writer.PutF4(v.x);
|
||||
writer.PutF4(v.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Faces (indices)
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
|
||||
|
||||
ai_assert(mesh.mNumFaces <= 0xffff);
|
||||
|
||||
// Count triangles, discard lines and points
|
||||
uint16_t count = 0;
|
||||
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
|
||||
const aiFace& f = mesh.mFaces[i];
|
||||
if (f.mNumIndices < 3) {
|
||||
continue;
|
||||
}
|
||||
// TRIANGULATE step is a pre-requisite so we should not see polys here
|
||||
ai_assert(f.mNumIndices == 3);
|
||||
++count;
|
||||
}
|
||||
|
||||
writer.PutU2(count);
|
||||
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
|
||||
const aiFace& f = mesh.mFaces[i];
|
||||
if (f.mNumIndices < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < 3; ++j) {
|
||||
ai_assert(f.mIndices[j] <= 0xffff);
|
||||
writer.PutI2(static_cast<uint16_t>(f.mIndices[j]));
|
||||
}
|
||||
|
||||
// Edge visibility flag
|
||||
writer.PutI2(0x0);
|
||||
}
|
||||
|
||||
// TODO: write smoothing groups (CHUNK_SMOOLIST)
|
||||
|
||||
WriteFaceMaterialChunk(mesh);
|
||||
}
|
||||
|
||||
// Transformation matrix by which the mesh vertices have been pre-transformed with.
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX);
|
||||
for (unsigned int r = 0; r < 4; ++r) {
|
||||
for (unsigned int c = 0; c < 3; ++c) {
|
||||
writer.PutF4(trafo[r][c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
|
||||
{
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
|
||||
const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
|
||||
WriteString(name);
|
||||
|
||||
// Because assimp splits meshes by material, only a single
|
||||
// FACEMAT chunk needs to be written
|
||||
ai_assert(mesh.mNumFaces <= 0xffff);
|
||||
const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces);
|
||||
writer.PutU2(count);
|
||||
|
||||
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
|
||||
writer.PutU2(static_cast<uint16_t>(i));
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Discreet3DSExporter::WriteString(const std::string& s) {
|
||||
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
|
||||
writer.PutI1(*it);
|
||||
}
|
||||
writer.PutI1('\0');
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Discreet3DSExporter::WriteString(const aiString& s) {
|
||||
for (std::size_t i = 0; i < s.length; ++i) {
|
||||
writer.PutI1(s.data[i]);
|
||||
}
|
||||
writer.PutI1('\0');
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
|
||||
writer.PutF4(color.r);
|
||||
writer.PutF4(color.g);
|
||||
writer.PutF4(color.b);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Discreet3DSExporter::WritePercentChunk(float f) {
|
||||
ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
|
||||
writer.PutF4(f);
|
||||
}
|
||||
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2012, 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 3DSExporter.h
|
||||
* 3DS Exporter Main Header
|
||||
*/
|
||||
#ifndef AI_3DSEXPORTER_H_INC
|
||||
#define AI_3DSEXPORTER_H_INC
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "StreamWriter.h"
|
||||
|
||||
struct aiScene;
|
||||
struct aiNode;
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Helper class to export a given scene to a 3DS file. */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
class Discreet3DSExporter
|
||||
{
|
||||
public:
|
||||
Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* pScene);
|
||||
|
||||
private:
|
||||
|
||||
void WriteMeshes();
|
||||
void WriteMaterials();
|
||||
void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
|
||||
|
||||
void WriteFaceMaterialChunk(const aiMesh& mesh);
|
||||
|
||||
int WriteHierarchy(const aiNode& node, int level, int sibling_level);
|
||||
|
||||
void WriteString(const std::string& s);
|
||||
void WriteString(const aiString& s);
|
||||
void WriteColor(const aiColor3D& color);
|
||||
void WritePercentChunk(float f);
|
||||
|
||||
private:
|
||||
|
||||
const aiScene* const scene;
|
||||
StreamWriterLE writer;
|
||||
|
||||
std::map<const aiNode*, aiMatrix4x4> trafos;
|
||||
|
||||
typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
|
||||
MeshesByNodeMap meshes;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -111,6 +111,7 @@ SET( Common_SRCS
|
|||
MemoryIOWrapper.h
|
||||
ParsingUtils.h
|
||||
StreamReader.h
|
||||
StreamWriter.h
|
||||
StringComparison.h
|
||||
SGSpatialSort.cpp
|
||||
SGSpatialSort.h
|
||||
|
@ -151,6 +152,8 @@ SET( 3DS_SRCS
|
|||
3DSHelper.h
|
||||
3DSLoader.cpp
|
||||
3DSLoader.h
|
||||
3DSExporter.h
|
||||
3DSExporter.cpp
|
||||
)
|
||||
SOURCE_GROUP(3DS FILES ${3DS_SRCS})
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ void ExportSceneObj(const char*,IOSystem*, const aiScene*);
|
|||
void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
|
||||
void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
|
||||
void ExportScenePly(const char*,IOSystem*, const aiScene*);
|
||||
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
|
||||
void ExportScene3DS(const char*, IOSystem*, const aiScene*);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// global array of all export formats which Assimp supports in its current build
|
||||
|
@ -90,7 +90,7 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_FXILE_EXPORTER
|
||||
Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
|
||||
aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
|
||||
aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
||||
|
@ -113,9 +113,10 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
),
|
||||
#endif
|
||||
|
||||
//#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||
// ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
|
||||
//#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||
Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
|
||||
aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
|
||||
#endif
|
||||
};
|
||||
|
||||
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Open Asset Import Library (assimp)
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2012, 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 Defines the StreamWriter class which writes data to
|
||||
* a binary stream with a well-defined endianess. */
|
||||
|
||||
#ifndef AI_STREAMWRITER_H_INCLUDED
|
||||
#define AI_STREAMWRITER_H_INCLUDED
|
||||
|
||||
#include "ByteSwap.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
/** Wrapper class around IOStream to allow for consistent writing of binary data in both
|
||||
* little and big endian format. Don't attempt to instance the template directly. Use
|
||||
* StreamWriterLE to read from a little-endian stream and StreamWriterBE to read from a
|
||||
* BE stream. Alternatively, there is StreamWriterAny if the endianess of the output
|
||||
* stream is to be determined at runtime.
|
||||
*/
|
||||
// --------------------------------------------------------------------------------------------
|
||||
template <bool SwapEndianess = false, bool RuntimeSwitch = false>
|
||||
class StreamWriter
|
||||
{
|
||||
enum {
|
||||
INITIAL_CAPACITY = 1024
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Construction from a given stream with a well-defined endianess.
|
||||
*
|
||||
* The StreamReader holds a permanent strong reference to the
|
||||
* stream, which is released upon destruction.
|
||||
* @param stream Input stream. The stream is not re-seeked and writing
|
||||
continues at the current position of the stream cursor.
|
||||
* @param le If @c RuntimeSwitch is true: specifies whether the
|
||||
* stream is in little endian byte order. Otherwise the
|
||||
* endianess information is defined by the @c SwapEndianess
|
||||
* template parameter and this parameter is meaningless. */
|
||||
StreamWriter(boost::shared_ptr<IOStream> stream, bool le = false)
|
||||
: stream(stream)
|
||||
, le(le)
|
||||
, cursor()
|
||||
{
|
||||
ai_assert(stream);
|
||||
buffer.reserve(INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
StreamWriter(IOStream* stream, bool le = false)
|
||||
: stream(boost::shared_ptr<IOStream>(stream))
|
||||
, le(le)
|
||||
, cursor()
|
||||
{
|
||||
ai_assert(stream);
|
||||
buffer.reserve(INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
~StreamWriter() {
|
||||
stream->Write(&buffer[0], 1, buffer.size());
|
||||
stream->Flush();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write a float to the stream */
|
||||
void PutF4(float f)
|
||||
{
|
||||
Put(f);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write a double to the stream */
|
||||
void PutF8(double d) {
|
||||
Put(d);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write a signed 16 bit integer to the stream */
|
||||
void PutI2(int16_t n) {
|
||||
Put(n);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write a signed 8 bit integer to the stream */
|
||||
void PutI1(int8_t n) {
|
||||
Put(n);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write an signed 32 bit integer to the stream */
|
||||
void PutI4(int32_t n) {
|
||||
Put(n);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write a signed 64 bit integer to the stream */
|
||||
void PutI8(int64_t n) {
|
||||
Put(n);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write a unsigned 16 bit integer to the stream */
|
||||
void PutU2(uint16_t n) {
|
||||
Put(n);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write a unsigned 8 bit integer to the stream */
|
||||
void PutU1(uint8_t n) {
|
||||
Put(n);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write an unsigned 32 bit integer to the stream */
|
||||
void PutU4(uint32_t n) {
|
||||
Put(n);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Write a unsigned 64 bit integer to the stream */
|
||||
void PutU8(uint64_t n) {
|
||||
Put(n);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** overload operator<< and allow chaining of MM ops. */
|
||||
template <typename T>
|
||||
StreamWriter& operator << (T f) {
|
||||
Put(f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
std::size_t GetCurrentPos() const {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
void SetCurrentPos(std::size_t new_cursor) {
|
||||
cursor = new_cursor;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Generic write method. ByteSwap::Swap(T*) *must* be defined */
|
||||
template <typename T>
|
||||
void Put(T f) {
|
||||
Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f, le);
|
||||
|
||||
if (cursor + sizeof(T) >= buffer.size()) {
|
||||
buffer.resize(cursor + sizeof(T));
|
||||
}
|
||||
|
||||
void* dest = &buffer[cursor];
|
||||
|
||||
// reinterpret_cast + assignment breaks strict aliasing rules
|
||||
// and generally causes trouble on platforms such as ARM that
|
||||
// do not silently ignore alignment faults.
|
||||
::memcpy(dest, &f, sizeof(T));
|
||||
cursor += sizeof(T);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
boost::shared_ptr<IOStream> stream;
|
||||
bool le;
|
||||
|
||||
std::vector<uint8_t> buffer;
|
||||
std::size_t cursor;
|
||||
};
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// `static` StreamWriter. Their byte order is fixed and they might be a little bit faster.
|
||||
#ifdef AI_BUILD_BIG_ENDIAN
|
||||
typedef StreamWriter<true> StreamWriterLE;
|
||||
typedef StreamWriter<false> StreamWriterBE;
|
||||
#else
|
||||
typedef StreamWriter<true> StreamWriterBE;
|
||||
typedef StreamWriter<false> StreamWriterLE;
|
||||
#endif
|
||||
|
||||
// `dynamic` StreamWriter. The byte order of the input data is specified in the
|
||||
// c'tor. This involves runtime branching and might be a little bit slower.
|
||||
typedef StreamWriter<true,true> StreamWriterAny;
|
||||
|
||||
} // end namespace Assimp
|
||||
|
||||
#endif // !! AI_STREAMWriter_H_INCLUDED
|
|
@ -15,7 +15,8 @@ SOURCE_GROUP( unit FILES
|
|||
unit/BoostWorkaround/tupletest.cpp
|
||||
)
|
||||
|
||||
SOURCE_GROUP( cppunit FILES
|
||||
|
||||
SET( CPPUNIT_SRCS
|
||||
../contrib/cppunit-1.12.1/src/cppunit/AdditionalMessage.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/Asserter.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/BeOsDynamicLibraryManager.cpp
|
||||
|
@ -70,59 +71,10 @@ SOURCE_GROUP( cppunit FILES
|
|||
../contrib/cppunit-1.12.1/src/cppunit/XmlOutputter.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/XmlOutputterHook.cpp
|
||||
)
|
||||
SOURCE_GROUP(cppunit FILES ${CPPUNIT_SRCS})
|
||||
|
||||
SOURCE_GROUP( tests FILES
|
||||
unit/Main.cpp
|
||||
unit/UnitTestPCH.cpp
|
||||
unit/UnitTestPCH.h
|
||||
unit/utFindDegenerates.cpp
|
||||
unit/utFindDegenerates.h
|
||||
unit/utFindInvalidData.cpp
|
||||
unit/utFindInvalidData.h
|
||||
unit/utFixInfacingNormals.cpp
|
||||
unit/utGenNormals.cpp
|
||||
unit/utGenNormals.h
|
||||
unit/utImporter.cpp
|
||||
unit/utImporter.h
|
||||
unit/utImproveCacheLocality.cpp
|
||||
unit/utJoinVertices.cpp
|
||||
unit/utJoinVertices.h
|
||||
unit/utLimitBoneWeights.cpp
|
||||
unit/utLimitBoneWeights.h
|
||||
unit/utMaterialSystem.cpp
|
||||
unit/utMaterialSystem.h
|
||||
unit/utPretransformVertices.cpp
|
||||
unit/utPretransformVertices.h
|
||||
unit/utRemoveComments.cpp
|
||||
unit/utRemoveComments.h
|
||||
unit/utRemoveComponent.cpp
|
||||
unit/utRemoveComponent.h
|
||||
unit/utRemoveRedundantMaterials.cpp
|
||||
unit/utRemoveRedundantMaterials.h
|
||||
unit/utScenePreprocessor.cpp
|
||||
unit/utScenePreprocessor.h
|
||||
unit/utSharedPPData.cpp
|
||||
unit/utSharedPPData.h
|
||||
unit/utSortByPType.cpp
|
||||
unit/utSortByPType.h
|
||||
unit/utSplitLargeMeshes.cpp
|
||||
unit/utSplitLargeMeshes.h
|
||||
unit/utTargetAnimation.cpp
|
||||
unit/utTargetAnimation.h
|
||||
unit/utTextureTransform.cpp
|
||||
unit/utTriangulate.cpp
|
||||
unit/utTriangulate.h
|
||||
unit/utVertexTriangleAdjacency.cpp
|
||||
unit/utVertexTriangleAdjacency.h
|
||||
unit/utNoBoostTest.cpp
|
||||
unit/utNoBoostTest.h
|
||||
)
|
||||
|
||||
add_executable( unit
|
||||
unit/CCompilerTest.c
|
||||
unit/Main.cpp
|
||||
unit/UnitTestPCH.cpp
|
||||
unit/UnitTestPCH.h
|
||||
SET( TEST_SRCS
|
||||
unit/utFindDegenerates.cpp
|
||||
unit/utFindDegenerates.h
|
||||
unit/utFindInvalidData.cpp
|
||||
|
@ -165,65 +117,20 @@ add_executable( unit
|
|||
unit/utNoBoostTest.cpp
|
||||
unit/utNoBoostTest.h
|
||||
unit/BoostWorkaround/tupletest.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/AdditionalMessage.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/Asserter.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/BeOsDynamicLibraryManager.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/BriefTestProgressListener.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/CompilerOutputter.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/DefaultProtector.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/DefaultProtector.h
|
||||
../contrib/cppunit-1.12.1/src/cppunit/DllMain.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/DynamicLibraryManager.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/DynamicLibraryManagerException.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/Exception.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/Message.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/PlugInManager.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/PlugInParameters.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/Protector.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/ProtectorChain.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/ProtectorChain.h
|
||||
../contrib/cppunit-1.12.1/src/cppunit/ProtectorContext.h
|
||||
../contrib/cppunit-1.12.1/src/cppunit/RepeatedTest.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/ShlDynamicLibraryManager.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/SourceLine.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/StringTools.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/SynchronizedObject.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/Test.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestAssert.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestCase.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestCaseDecorator.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestComposite.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestDecorator.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestFactoryRegistry.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestFailure.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestLeaf.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestNamer.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestPath.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestPlugInDefaultImpl.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestResult.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestResultCollector.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestRunner.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestSetUp.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestSuccessListener.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestSuite.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TestSuiteBuilderContext.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TextOutputter.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TextTestProgressListener.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TextTestResult.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TextTestRunner.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/TypeInfoHelper.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/UnixDynamicLibraryManager.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/Win32DynamicLibraryManager.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/XmlDocument.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/XmlElement.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/XmlOutputter.cpp
|
||||
../contrib/cppunit-1.12.1/src/cppunit/XmlOutputterHook.cpp
|
||||
)
|
||||
|
||||
IF( WIN32 )
|
||||
FIND_PACKAGE(DirectX REQUIRED)
|
||||
ENDIF( WIN32 )
|
||||
SOURCE_GROUP(tests FILES ${TEST_SRCS})
|
||||
|
||||
|
||||
add_executable( unit
|
||||
unit/CCompilerTest.c
|
||||
unit/Main.cpp
|
||||
unit/UnitTestPCH.cpp
|
||||
unit/UnitTestPCH.h
|
||||
${TEST_SRCS}
|
||||
${CPPUNIT_SRCS}
|
||||
)
|
||||
|
||||
SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
|
||||
|
||||
# TODO: Port to non-Windows platforms.
|
||||
target_link_libraries ( unit assimp ${DirectX_LIBRARY} ${DirectX_D3DX9_LIBRARY} comctl32.lib Winmm.lib )
|
||||
target_link_libraries ( unit assimp )
|
||||
|
|
|
@ -1030,18 +1030,17 @@ void PopulateExportMenu()
|
|||
//-------------------------------------------------------------------------------
|
||||
void DoExport(size_t formatId)
|
||||
{
|
||||
if (!g_szFileName) {
|
||||
if (!g_szFileName[0]) {
|
||||
MessageBox(g_hDlg, "No model loaded", "Export", MB_ICONERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
Exporter exp;
|
||||
const aiExportFormatDesc* const e = exp.GetExportFormatDescription(formatId);
|
||||
ai_assert(e);
|
||||
|
||||
char szFileName[MAX_PATH*2];
|
||||
DWORD dwTemp;
|
||||
if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",NULL,NULL,(BYTE*)szFileName,&dwTemp)) {
|
||||
ai_assert(dwTemp == MAX_PATH + 1);
|
||||
DWORD dwTemp = sizeof(szFileName);
|
||||
if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",NULL,NULL,(BYTE*)szFileName, &dwTemp)) {
|
||||
ai_assert(strlen(szFileName) <= MAX_PATH);
|
||||
|
||||
// invent a nice default file name
|
||||
|
|
Loading…
Reference in New Issue