mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
add assimp stuff
This commit is contained in:
parent
d30f60c70f
commit
19e73932d2
36
pandatool/src/assimp/Sources.pp
Normal file
36
pandatool/src/assimp/Sources.pp
Normal file
@ -0,0 +1,36 @@
|
||||
#begin lib_target
|
||||
#define BUILD_TARGET $[HAVE_ASSIMP]
|
||||
|
||||
#define TARGET p3assimp
|
||||
#define BUILDING_DLL BUILDING_ASSIMP
|
||||
#define LOCAL_LIBS \
|
||||
pandatoolbase
|
||||
#define USE_PACKAGES assimp
|
||||
|
||||
#define OTHER_LIBS \
|
||||
egg2pg:c egg:c pandaegg:m \
|
||||
pstatclient:c mathutil:c linmath:c putil:c \
|
||||
gobj:c chan:c parametrics:c pgraph:c pgraphnodes:c \
|
||||
pnmimage:c grutil:c collide:c tform:c text:c \
|
||||
char:c dgraph:c display:c device:c cull:c \
|
||||
downloader:c pipeline:c \
|
||||
event:c gsgbase:c lerp:c movies:c \
|
||||
panda:m \
|
||||
pandabase:c express:c pandaexpress:m \
|
||||
interrogatedb:c prc:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m \
|
||||
assimp:c
|
||||
|
||||
#define SOURCES \
|
||||
assimpLoader.cxx assimpLoader.h \
|
||||
config_assimp.cxx config_assimp.h \
|
||||
loaderFileTypeAssimp.cxx loaderFileTypeAssimp.h \
|
||||
pandaIOStream.cxx pandaIOStream.h \
|
||||
pandaIOSystem.cxx pandaIOSystem.h \
|
||||
pandaLogger.cxx pandaLogger.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
assimpLoader.h \
|
||||
config_assimp.h loaderFileTypeAssimp.h
|
||||
|
||||
#end lib_target
|
14
pandatool/src/assimp/assimpLoader.I
Normal file
14
pandatool/src/assimp/assimpLoader.I
Normal file
@ -0,0 +1,14 @@
|
||||
// Filename: assimpLoader.I
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
644
pandatool/src/assimp/assimpLoader.cxx
Normal file
644
pandatool/src/assimp/assimpLoader.cxx
Normal file
@ -0,0 +1,644 @@
|
||||
// Filename: assimpLoader.cxx
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "assimpLoader.h"
|
||||
|
||||
#include "geomNode.h"
|
||||
#include "luse.h"
|
||||
#include "geomVertexWriter.h"
|
||||
#include "geomPoints.h"
|
||||
#include "geomLines.h"
|
||||
#include "geomTriangles.h"
|
||||
#include "pnmFileTypeRegistry.h"
|
||||
#include "pnmImage.h"
|
||||
#include "materialAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "cullFaceAttrib.h"
|
||||
#include "lightNode.h"
|
||||
#include "ambientLight.h"
|
||||
#include "directionalLight.h"
|
||||
#include "spotlight.h"
|
||||
#include "pointLight.h"
|
||||
#include "look_at.h"
|
||||
#include "texturePool.h"
|
||||
|
||||
#include "pandaIOSystem.h"
|
||||
#include "pandaLogger.h"
|
||||
|
||||
#include "aiPostProcess.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AssimpLoader::
|
||||
AssimpLoader() :
|
||||
_error (false),
|
||||
_geoms (NULL) {
|
||||
|
||||
PandaLogger::set_default();
|
||||
_importer.SetIOHandler(new PandaIOSystem);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AssimpLoader::
|
||||
~AssimpLoader() {
|
||||
_importer.FreeScene();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::get_extensions
|
||||
// Access: Public
|
||||
// Description: Returns a space-separated list of extensions that
|
||||
// Assimp can load, without the leading dots.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AssimpLoader::
|
||||
get_extensions(string &ext) const {
|
||||
aiString aexts;
|
||||
_importer.GetExtensionList(aexts);
|
||||
|
||||
// The format is like: *.mdc;*.mdl;*.mesh.xml;*.mot
|
||||
char *sub = strtok(aexts.data, ";");
|
||||
while (sub != NULL) {
|
||||
ext += sub + 2;
|
||||
sub = strtok(NULL, ";");
|
||||
|
||||
if (sub != NULL) {
|
||||
ext += ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::read
|
||||
// Access: Public
|
||||
// Description: Reads from the indicated file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AssimpLoader::
|
||||
read(const Filename &filename) {
|
||||
_filename = filename;
|
||||
|
||||
// I really don't know why we need to flip the winding order,
|
||||
// but otherwise the models I tested with are showing inside out.
|
||||
_scene = _importer.ReadFile(_filename.c_str(), aiProcess_Triangulate | aiProcess_GenUVCoords | aiProcess_FlipWindingOrder);
|
||||
if (_scene == NULL) {
|
||||
_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
_error = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::build_graph
|
||||
// Access: Public
|
||||
// Description: Converts scene graph structures into a Panda3D
|
||||
// scene graph, with _root being the root node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AssimpLoader::
|
||||
build_graph() {
|
||||
nassertv(_scene != NULL); // read() must be called first
|
||||
nassertv(!_error); // and have succeeded
|
||||
|
||||
// Protect the import process
|
||||
MutexHolder holder(_lock);
|
||||
|
||||
_root = new ModelRoot(_filename.get_basename());
|
||||
|
||||
// Import all of the embedded textures first.
|
||||
_textures = new PT(Texture)[_scene->mNumTextures];
|
||||
for (size_t i = 0; i < _scene->mNumTextures; ++i) {
|
||||
load_texture(i);
|
||||
}
|
||||
|
||||
// Then the materials.
|
||||
_mat_states = new CPT(RenderState)[_scene->mNumMaterials];
|
||||
for (size_t i = 0; i < _scene->mNumMaterials; ++i) {
|
||||
load_material(i);
|
||||
}
|
||||
|
||||
// And then the meshes.
|
||||
_geoms = new PT(Geom)[_scene->mNumMeshes];
|
||||
_geom_matindices = new unsigned int[_scene->mNumMeshes];
|
||||
for (size_t i = 0; i < _scene->mNumMeshes; ++i) {
|
||||
load_mesh(i);
|
||||
}
|
||||
|
||||
// And now the node structure.
|
||||
if (_scene->mRootNode != NULL) {
|
||||
load_node(*_scene->mRootNode, _root);
|
||||
}
|
||||
|
||||
// And lastly, the lights.
|
||||
for (size_t i = 0; i < _scene->mNumLights; ++i) {
|
||||
load_light(*_scene->mLights[i]);
|
||||
}
|
||||
|
||||
delete[] _textures;
|
||||
delete[] _mat_states;
|
||||
delete[] _geoms;
|
||||
delete[] _geom_matindices;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::load_texture
|
||||
// Access: Private
|
||||
// Description: Converts an aiTexture into a Texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AssimpLoader::
|
||||
load_texture(size_t index) {
|
||||
const aiTexture &tex = *_scene->mTextures[index];
|
||||
|
||||
PT(Texture) ptex = new Texture;
|
||||
|
||||
if (tex.mHeight == 0) {
|
||||
// Compressed texture.
|
||||
assimp_cat.debug()
|
||||
<< "Reading embedded compressed texture with format " << tex.achFormatHint << " and size " << tex.mWidth << "\n";
|
||||
stringstream str;
|
||||
str.write((char*) tex.pcData, tex.mWidth);
|
||||
|
||||
if (strncmp(tex.achFormatHint, "dds", 3) == 0) {
|
||||
ptex->read_dds(str);
|
||||
|
||||
} else {
|
||||
const PNMFileTypeRegistry *reg = PNMFileTypeRegistry::get_global_ptr();
|
||||
PNMFileType *ftype;
|
||||
PNMImage img;
|
||||
|
||||
// Work around a bug in Assimp, it sometimes writes jp instead of jpg
|
||||
if (strncmp(tex.achFormatHint, "jp\0", 3) == 0) {
|
||||
ftype = reg->get_type_from_extension("jpg");
|
||||
} else {
|
||||
ftype = reg->get_type_from_extension(tex.achFormatHint);
|
||||
}
|
||||
|
||||
if (img.read(str, "", ftype)) {
|
||||
ptex->load(img);
|
||||
} else {
|
||||
ptex = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assimp_cat.debug()
|
||||
<< "Reading embedded raw texture with size " << tex.mWidth << "x" << tex.mHeight << "\n";
|
||||
|
||||
ptex->setup_2d_texture(tex.mWidth, tex.mHeight, Texture::T_unsigned_byte, Texture::F_rgba);
|
||||
PTA_uchar data = ptex->modify_ram_image();
|
||||
|
||||
size_t p = 0;
|
||||
for (size_t i = 0; i < tex.mWidth * tex.mHeight; ++i) {
|
||||
const aiTexel &texel = tex.pcData[i];
|
||||
data[p++] = texel.b;
|
||||
data[p++] = texel.g;
|
||||
data[p++] = texel.r;
|
||||
data[p++] = texel.a;
|
||||
}
|
||||
}
|
||||
|
||||
//ostringstream path;
|
||||
//path << "/tmp/" << index << ".png";
|
||||
//ptex->write(path.str());
|
||||
|
||||
_textures[index] = ptex;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::load_texture_stage
|
||||
// Access: Private
|
||||
// Description: Converts an aiMaterial into a RenderState.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AssimpLoader::
|
||||
load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, CPT(TextureAttrib) &tattr) {
|
||||
aiString path;
|
||||
aiTextureMapping mapping;
|
||||
unsigned int uvindex;
|
||||
float blend;
|
||||
aiTextureOp op;
|
||||
aiTextureMapMode mapmode;
|
||||
|
||||
for (size_t i = 0; i < mat.GetTextureCount(ttype); ++i) {
|
||||
mat.GetTexture(ttype, i, &path, &mapping, NULL, &blend, &op, &mapmode);
|
||||
|
||||
if (AI_SUCCESS != mat.Get(AI_MATKEY_UVWSRC(ttype, i), uvindex)) {
|
||||
// If there's no texture coordinate set for this texture,
|
||||
// assume that it's the same as the index on the stack.
|
||||
//TODO: if there's only one set on the mesh,
|
||||
// force everything to use just the first stage.
|
||||
uvindex = i;
|
||||
}
|
||||
|
||||
stringstream str;
|
||||
str << uvindex;
|
||||
PT(TextureStage) stage = new TextureStage(str.str());
|
||||
if (uvindex > 0) {
|
||||
stage->set_texcoord_name(InternalName::get_texcoord_name(str.str()));
|
||||
}
|
||||
PT(Texture) ptex = NULL;
|
||||
|
||||
// I'm not sure if this is the right way to handle it, as
|
||||
// I couldn't find much information on embedded textures.
|
||||
if (path.data[0] == '*') {
|
||||
long num = strtol(path.data + 1, NULL, 10);
|
||||
ptex = _textures[num];
|
||||
|
||||
} else if (path.length > 0) {
|
||||
Filename fn = Filename::from_os_specific(string(path.data, path.length));
|
||||
|
||||
// Try to find the file by moving up twice in the hierarchy.
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
Filename dir (_filename);
|
||||
_filename.make_canonical();
|
||||
dir = _filename.get_dirname();
|
||||
|
||||
// Quake 3 BSP doesn't specify an extension for textures.
|
||||
if (vfs->is_regular_file(Filename(dir, fn))) {
|
||||
fn = Filename(dir, fn);
|
||||
} else if (vfs->is_regular_file(Filename(dir, fn + ".tga"))) {
|
||||
fn = Filename(dir, fn + ".tga");
|
||||
} else if (vfs->is_regular_file(Filename(dir, fn + ".jpg"))) {
|
||||
fn = Filename(dir, fn + ".jpg");
|
||||
} else {
|
||||
dir = _filename.get_dirname();
|
||||
if (vfs->is_regular_file(Filename(dir, fn))) {
|
||||
fn = Filename(dir, fn);
|
||||
} else if (vfs->is_regular_file(Filename(dir, fn + ".tga"))) {
|
||||
fn = Filename(dir, fn + ".tga");
|
||||
} else if (vfs->is_regular_file(Filename(dir, fn + ".jpg"))) {
|
||||
fn = Filename(dir, fn + ".jpg");
|
||||
}
|
||||
}
|
||||
|
||||
ptex = TexturePool::load_texture(fn);
|
||||
}
|
||||
|
||||
if (ptex != NULL) {
|
||||
tattr = DCAST(TextureAttrib, tattr->add_on_stage(stage, ptex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::load_material
|
||||
// Access: Private
|
||||
// Description: Converts an aiMaterial into a RenderState.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AssimpLoader::
|
||||
load_material(size_t index) {
|
||||
const aiMaterial &mat = *_scene->mMaterials[index];
|
||||
|
||||
CPT(RenderState) state = RenderState::make_empty();
|
||||
|
||||
aiColor3D col;
|
||||
bool have;
|
||||
int ival;
|
||||
float fval;
|
||||
|
||||
// XXX a lot of this is untested.
|
||||
|
||||
// First do the material attribute.
|
||||
PT(Material) pmat = new Material;
|
||||
have = false;
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_DIFFUSE, col)) {
|
||||
pmat->set_diffuse(Colorf(col.r, col.g, col.b, 1));
|
||||
have = true;
|
||||
}
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_SPECULAR, col)) {
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_SHININESS_STRENGTH, fval)) {
|
||||
pmat->set_specular(Colorf(col.r * fval, col.g * fval, col.b * fval, 1));
|
||||
} else {
|
||||
pmat->set_specular(Colorf(col.r, col.g, col.b, 1));
|
||||
}
|
||||
have = true;
|
||||
}
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_AMBIENT, col)) {
|
||||
pmat->set_specular(Colorf(col.r, col.g, col.b, 1));
|
||||
have = true;
|
||||
}
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_EMISSIVE, col)) {
|
||||
pmat->set_emission(Colorf(col.r, col.g, col.b, 1));
|
||||
have = true;
|
||||
}
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_TRANSPARENT, col)) {
|
||||
//FIXME: ???
|
||||
}
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_SHININESS, fval)) {
|
||||
pmat->set_shininess(fval);
|
||||
have = true;
|
||||
}
|
||||
if (have) {
|
||||
state = state->add_attrib(MaterialAttrib::make(pmat));
|
||||
}
|
||||
|
||||
// Wireframe.
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_ENABLE_WIREFRAME, ival)) {
|
||||
if (ival) {
|
||||
state = state->add_attrib(RenderModeAttrib::make(RenderModeAttrib::M_wireframe));
|
||||
} else {
|
||||
state = state->add_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled));
|
||||
}
|
||||
}
|
||||
|
||||
// Backface culling. Not sure if this is also supposed to
|
||||
// set the twoside flag in the material, I'm guessing not.
|
||||
if (AI_SUCCESS == mat.Get(AI_MATKEY_TWOSIDED, ival)) {
|
||||
if (ival) {
|
||||
state = state->add_attrib(CullFaceAttrib::make(CullFaceAttrib::M_cull_none));
|
||||
} else {
|
||||
state = state->add_attrib(CullFaceAttrib::make_default());
|
||||
}
|
||||
}
|
||||
|
||||
// And let's not forget the textures!
|
||||
CPT(TextureAttrib) tattr = DCAST(TextureAttrib, TextureAttrib::make());
|
||||
load_texture_stage(mat, aiTextureType_DIFFUSE, tattr);
|
||||
load_texture_stage(mat, aiTextureType_LIGHTMAP, tattr);
|
||||
if (tattr->get_num_on_stages() > 0) {
|
||||
state = state->add_attrib(tattr);
|
||||
}
|
||||
|
||||
_mat_states[index] = state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::load_mesh
|
||||
// Access: Private
|
||||
// Description: Converts an aiMesh into a Geom.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AssimpLoader::
|
||||
load_mesh(size_t index) {
|
||||
const aiMesh &mesh = *_scene->mMeshes[index];
|
||||
|
||||
// Create the vertex format.
|
||||
PT(GeomVertexArrayFormat) aformat = new GeomVertexArrayFormat;
|
||||
aformat->add_column(InternalName::get_vertex(), 3, Geom::NT_float32, Geom::C_point);
|
||||
if (mesh.HasNormals()) {
|
||||
aformat->add_column(InternalName::get_normal(), 3, Geom::NT_float32, Geom::C_vector);
|
||||
}
|
||||
if (mesh.HasVertexColors(0)) {
|
||||
aformat->add_column(InternalName::get_color(), 4, Geom::NT_float32, Geom::C_color);
|
||||
}
|
||||
unsigned int num_uvs = mesh.GetNumUVChannels();
|
||||
if (num_uvs > 0) {
|
||||
// UV sets are named texcoord, texcoord.1, texcoord.2...
|
||||
aformat->add_column(InternalName::get_texcoord(), 3, Geom::NT_float32, Geom::C_texcoord);
|
||||
for (unsigned int u = 1; u < num_uvs; ++u) {
|
||||
ostringstream out;
|
||||
out << u;
|
||||
aformat->add_column(InternalName::get_texcoord_name(out.str()), 3, Geom::NT_float32, Geom::C_texcoord);
|
||||
}
|
||||
}
|
||||
//TODO: if there is only one UV set, hackily iterate over the texture stages and clear the texcoord name things
|
||||
|
||||
PT(GeomVertexFormat) format = new GeomVertexFormat;
|
||||
format->add_array(aformat);
|
||||
|
||||
// Create the GeomVertexData.
|
||||
string name (mesh.mName.data, mesh.mName.length);
|
||||
PT(GeomVertexData) vdata = new GeomVertexData(name, GeomVertexFormat::register_format(format), Geom::UH_static);
|
||||
vdata->unclean_set_num_rows(mesh.mNumVertices);
|
||||
|
||||
// Read out the vertices.
|
||||
GeomVertexWriter vertex (vdata, InternalName::get_vertex());
|
||||
for (size_t i = 0; i < mesh.mNumVertices; ++i) {
|
||||
const aiVector3D &vec = mesh.mVertices[i];
|
||||
vertex.add_data3f(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
// Now the normals, if any.
|
||||
if (mesh.HasNormals()) {
|
||||
GeomVertexWriter normal (vdata, InternalName::get_normal());
|
||||
for (size_t i = 0; i < mesh.mNumVertices; ++i) {
|
||||
const aiVector3D &vec = mesh.mNormals[i];
|
||||
normal.add_data3f(vec.x, vec.y, vec.z);
|
||||
}
|
||||
}
|
||||
|
||||
// Vertex colors, if any. We only import the first set.
|
||||
if (mesh.HasVertexColors(0)) {
|
||||
GeomVertexWriter color (vdata, InternalName::get_color());
|
||||
for (size_t i = 0; i < mesh.mNumVertices; ++i) {
|
||||
const aiColor4D &col = mesh.mColors[0][i];
|
||||
color.add_data4f(col.r, col.g, col.b, col.a);
|
||||
}
|
||||
}
|
||||
|
||||
// Now the texture coordinates.
|
||||
if (num_uvs > 0) {
|
||||
// UV sets are named texcoord, texcoord.1, texcoord.2...
|
||||
GeomVertexWriter texcoord0 (vdata, InternalName::get_texcoord());
|
||||
for (size_t i = 0; i < mesh.mNumVertices; ++i) {
|
||||
const aiVector3D &vec = mesh.mTextureCoords[0][i];
|
||||
texcoord0.add_data3f(vec.x, vec.y, vec.z);
|
||||
}
|
||||
for (unsigned int u = 1; u < num_uvs; ++u) {
|
||||
ostringstream out;
|
||||
out << u;
|
||||
GeomVertexWriter texcoord (vdata, InternalName::get_texcoord_name(out.str()));
|
||||
for (size_t i = 0; i < mesh.mNumVertices; ++i) {
|
||||
const aiVector3D &vec = mesh.mTextureCoords[u][i];
|
||||
texcoord.add_data3f(vec.x, vec.y, vec.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now read out the primitives.
|
||||
// Keep in mind that we called ReadFile with the aiProcess_Triangulate
|
||||
// flag earlier, so we don't have to worry about polygons.
|
||||
PT(GeomPoints) points = new GeomPoints(Geom::UH_static);
|
||||
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
|
||||
PT(GeomTriangles) triangles = new GeomTriangles(Geom::UH_static);
|
||||
|
||||
// Now add the vertex indices.
|
||||
for (size_t i = 0; i < mesh.mNumFaces; ++i) {
|
||||
const aiFace &face = mesh.mFaces[i];
|
||||
|
||||
if (face.mNumIndices == 0) {
|
||||
// It happens, strangely enough.
|
||||
continue;
|
||||
} else if (face.mNumIndices == 1) {
|
||||
points->add_vertex(face.mIndices[0]);
|
||||
points->close_primitive();
|
||||
} else if (face.mNumIndices == 2) {
|
||||
lines->add_vertices(face.mIndices[0], face.mIndices[1]);
|
||||
lines->close_primitive();
|
||||
} else if (face.mNumIndices == 3) {
|
||||
triangles->add_vertices(face.mIndices[0], face.mIndices[1], face.mIndices[2]);
|
||||
triangles->close_primitive();
|
||||
} else {
|
||||
nassertd(false) continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a geom and add the primitives to it.
|
||||
PT(Geom) geom = new Geom(vdata);
|
||||
if (points->get_num_primitives() > 0) {
|
||||
geom->add_primitive(points);
|
||||
}
|
||||
if (lines->get_num_primitives() > 0) {
|
||||
geom->add_primitive(lines);
|
||||
}
|
||||
if (triangles->get_num_primitives() > 0) {
|
||||
geom->add_primitive(triangles);
|
||||
}
|
||||
|
||||
_geoms[index] = geom;
|
||||
_geom_matindices[index] = mesh.mMaterialIndex;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::load_node
|
||||
// Access: Private
|
||||
// Description: Converts an aiNode into a PandaNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AssimpLoader::
|
||||
load_node(const aiNode &node, PandaNode *parent) {
|
||||
PT(PandaNode) pnode;
|
||||
|
||||
// Create the node and give it a name.
|
||||
string name (node.mName.data, node.mName.length);
|
||||
if (node.mNumMeshes > 0) {
|
||||
pnode = new GeomNode(name);
|
||||
} else {
|
||||
pnode = new PandaNode(name);
|
||||
}
|
||||
parent->add_child(pnode);
|
||||
|
||||
// Load in the transformation matrix.
|
||||
const aiMatrix4x4 &t = node.mTransformation;
|
||||
if (!t.IsIdentity()) {
|
||||
LMatrix4f mat(t.a1, t.b1, t.c1, t.d1,
|
||||
t.a2, t.b2, t.c2, t.d2,
|
||||
t.a3, t.b3, t.c3, t.d3,
|
||||
t.a4, t.b4, t.c4, t.d4);
|
||||
pnode->set_transform(TransformState::make_mat(mat));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node.mNumChildren; ++i) {
|
||||
load_node(*node.mChildren[i], pnode);
|
||||
}
|
||||
|
||||
if (node.mNumMeshes > 0) {
|
||||
// Remember, we created this as GeomNode earlier.
|
||||
PT(GeomNode) gnode = DCAST(GeomNode, pnode);
|
||||
size_t meshIndex;
|
||||
|
||||
// If there's only mesh, don't bother using a per-geom state.
|
||||
if (node.mNumMeshes == 1) {
|
||||
meshIndex = node.mMeshes[0];
|
||||
gnode->add_geom(_geoms[meshIndex]);
|
||||
gnode->set_state(_mat_states[_geom_matindices[meshIndex]]);
|
||||
|
||||
} else {
|
||||
for (size_t i = 0; i < node.mNumMeshes; ++i) {
|
||||
meshIndex = node.mMeshes[i];
|
||||
gnode->add_geom(_geoms[node.mMeshes[i]],
|
||||
_mat_states[_geom_matindices[meshIndex]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AssimpLoader::load_light
|
||||
// Access: Private
|
||||
// Description: Converts an aiLight into a LightNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AssimpLoader::
|
||||
load_light(const aiLight &light) {
|
||||
string name (light.mName.data, light.mName.length);
|
||||
assimp_cat.debug() << "Found light '" << name << "'\n";
|
||||
|
||||
aiColor3D col;
|
||||
aiVector3D vec;
|
||||
|
||||
PT(LightNode) lnode;
|
||||
|
||||
switch (light.mType) {
|
||||
case aiLightSource_DIRECTIONAL: {
|
||||
PT(DirectionalLight) dlight = new DirectionalLight(name);
|
||||
lnode = DCAST(LightNode, dlight);
|
||||
|
||||
col = light.mColorSpecular;
|
||||
dlight->set_specular_color(Colorf(col.r, col.g, col.b, 1));
|
||||
|
||||
vec = light.mPosition;
|
||||
dlight->set_point(LPoint3f(vec.x, vec.y, vec.z));
|
||||
|
||||
vec = light.mDirection;
|
||||
dlight->set_direction(LVector3f(vec.x, vec.y, vec.z));
|
||||
break; }
|
||||
|
||||
case aiLightSource_POINT: {
|
||||
PT(PointLight) plight = new PointLight(name);
|
||||
lnode = DCAST(LightNode, plight);
|
||||
|
||||
col = light.mColorSpecular;
|
||||
plight->set_specular_color(Colorf(col.r, col.g, col.b, 1));
|
||||
|
||||
vec = light.mPosition;
|
||||
plight->set_point(LPoint3f(vec.x, vec.y, vec.z));
|
||||
|
||||
plight->set_attenuation(LVecBase3f(light.mAttenuationConstant,
|
||||
light.mAttenuationLinear,
|
||||
light.mAttenuationQuadratic));
|
||||
break; }
|
||||
|
||||
case aiLightSource_SPOT: {
|
||||
PT(Spotlight) plight = new Spotlight(name);
|
||||
lnode = DCAST(LightNode, plight);
|
||||
|
||||
col = light.mColorSpecular;
|
||||
plight->set_specular_color(Colorf(col.r, col.g, col.b, 1));
|
||||
|
||||
plight->set_attenuation(LVecBase3f(light.mAttenuationConstant,
|
||||
light.mAttenuationLinear,
|
||||
light.mAttenuationQuadratic));
|
||||
|
||||
plight->get_lens()->set_fov(light.mAngleOuterCone);
|
||||
//TODO: translate mAngleInnerCone to an exponent, somehow
|
||||
|
||||
// This *should* be about right.
|
||||
vec = light.mDirection;
|
||||
LPoint3f pos (light.mPosition.x, light.mPosition.y, light.mPosition.z);
|
||||
LQuaternionf quat;
|
||||
::look_at(quat, LPoint3f(vec.x, vec.y, vec.z), LVector3f::up());
|
||||
plight->set_transform(TransformState::make_pos_quat_scale(pos, quat, LVecBase3f(1, 1, 1)));
|
||||
break; }
|
||||
|
||||
default:
|
||||
assimp_cat.warning() << "Light '" << name << "' has an unknown type!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's an ambient color, add it as ambient light.
|
||||
LVecBase4f ambient (col.r, col.g, col.b, 0);
|
||||
if (ambient != LVecBase4f::zero()) {
|
||||
PT(AmbientLight) alight = new AmbientLight(name);
|
||||
col = light.mColorAmbient;
|
||||
alight->set_color(ambient);
|
||||
_root->add_child(alight);
|
||||
}
|
||||
|
||||
_root->add_child(lnode);
|
||||
col = light.mColorDiffuse;
|
||||
lnode->set_color(Colorf(col.r, col.g, col.b, 1));
|
||||
}
|
67
pandatool/src/assimp/assimpLoader.h
Normal file
67
pandatool/src/assimp/assimpLoader.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Filename: assimpLoader.h
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ASSIMPLOADER_H
|
||||
#define ASSIMPLOADER_H
|
||||
|
||||
#include "config_assimp.h"
|
||||
#include "filename.h"
|
||||
#include "modelRoot.h"
|
||||
#include "texture.h"
|
||||
|
||||
#include "aiScene.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AssimpLoader
|
||||
// Description : Class that interfaces with Assimp and builds Panda
|
||||
// nodes to represent the Assimp structures.
|
||||
// The loader should be reusable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class AssimpLoader : public TypedReferenceCount {
|
||||
public:
|
||||
AssimpLoader();
|
||||
virtual ~AssimpLoader();
|
||||
|
||||
void get_extensions(string &ext) const;
|
||||
|
||||
bool read(const Filename &filename);
|
||||
void build_graph();
|
||||
|
||||
public:
|
||||
bool _error;
|
||||
PT(ModelRoot) _root;
|
||||
Filename _filename;
|
||||
Mutex _lock;
|
||||
|
||||
private:
|
||||
Assimp::Importer _importer;
|
||||
const aiScene *_scene;
|
||||
|
||||
// These arrays are temporarily used during the build_graph run.
|
||||
PT(Texture) *_textures;
|
||||
CPT(RenderState) *_mat_states;
|
||||
PT(Geom) *_geoms;
|
||||
unsigned int *_geom_matindices;
|
||||
|
||||
void load_texture(size_t index);
|
||||
void load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, CPT(TextureAttrib) &tattr);
|
||||
void load_material(size_t index);
|
||||
void load_mesh(size_t index);
|
||||
void load_node(const aiNode &node, PandaNode *parent);
|
||||
void load_light(const aiLight &light);
|
||||
};
|
||||
|
||||
#include "assimpLoader.I"
|
||||
|
||||
#endif
|
49
pandatool/src/assimp/config_assimp.cxx
Normal file
49
pandatool/src/assimp/config_assimp.cxx
Normal file
@ -0,0 +1,49 @@
|
||||
// Filename: config_assimp.cxx
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_assimp.h"
|
||||
|
||||
#include "loaderFileTypeAssimp.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
#include "loaderFileTypeRegistry.h"
|
||||
|
||||
ConfigureDef(config_assimp);
|
||||
NotifyCategoryDef(assimp, "");
|
||||
|
||||
ConfigureFn(config_assimp) {
|
||||
init_libassimp();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libassimp
|
||||
// Description: Initializes the library. This must be called at
|
||||
// least once before any of the functions or classes in
|
||||
// this library can be used. Normally it will be
|
||||
// called by the static initializers and need not be
|
||||
// called explicitly, but special cases exist.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
init_libassimp() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
LoaderFileTypeAssimp::init_type();
|
||||
|
||||
LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr();
|
||||
reg->register_type(new LoaderFileTypeAssimp);
|
||||
}
|
29
pandatool/src/assimp/config_assimp.h
Normal file
29
pandatool/src/assimp/config_assimp.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Filename: config_assimp.h
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_ASSIMP_H
|
||||
#define CONFIG_ASSIMP_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "assimp.hpp"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
ConfigureDecl(config_assimp, EXPCL_ASSIMP, EXPTP_ASSIMP);
|
||||
NotifyCategoryDecl(assimp, EXPCL_ASSIMP, EXPTP_ASSIMP);
|
||||
|
||||
extern EXPCL_ASSIMP void init_libassimp();
|
||||
|
||||
#endif
|
106
pandatool/src/assimp/loaderFileTypeAssimp.cxx
Normal file
106
pandatool/src/assimp/loaderFileTypeAssimp.cxx
Normal file
@ -0,0 +1,106 @@
|
||||
// Filename: loaderFileTypeAssimp.cxx
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "loaderFileTypeAssimp.h"
|
||||
#include "config_assimp.h"
|
||||
#include "assimpLoader.h"
|
||||
|
||||
TypeHandle LoaderFileTypeAssimp::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeAssimp::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LoaderFileTypeAssimp::
|
||||
LoaderFileTypeAssimp() : _loader(new AssimpLoader) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeAssimp::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LoaderFileTypeAssimp::
|
||||
~LoaderFileTypeAssimp() {
|
||||
if (_loader != NULL) {
|
||||
delete _loader;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeAssimp::get_name
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string LoaderFileTypeAssimp::
|
||||
get_name() const {
|
||||
return "Assimp Importer";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeAssimp::get_extension
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string LoaderFileTypeAssimp::
|
||||
get_extension() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeAssimp::get_additional_extensions
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a space-separated list of extension, in
|
||||
// addition to the one returned by get_extension(), that
|
||||
// are recognized by this converter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string LoaderFileTypeAssimp::
|
||||
get_additional_extensions() const {
|
||||
string exts;
|
||||
_loader->get_extensions(exts);
|
||||
return exts;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeAssimp::supports_compressed
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns true if this file type can transparently load
|
||||
// compressed files (with a .pz extension), false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool LoaderFileTypeAssimp::
|
||||
supports_compressed() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LoaderFileTypeAssimp::load_file
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(PandaNode) LoaderFileTypeAssimp::
|
||||
load_file(const Filename &path, const LoaderOptions &options,
|
||||
BamCacheRecord *record) const {
|
||||
|
||||
assimp_cat.info()
|
||||
<< "Reading " << path << "\n";
|
||||
|
||||
if (!_loader->read(path)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_loader->build_graph();
|
||||
return DCAST(PandaNode, _loader->_root);
|
||||
}
|
63
pandatool/src/assimp/loaderFileTypeAssimp.h
Normal file
63
pandatool/src/assimp/loaderFileTypeAssimp.h
Normal file
@ -0,0 +1,63 @@
|
||||
// Filename: loaderFileTypeAssimp.h
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOADERFILETYPEASSIMP_H
|
||||
#define LOADERFILETYPEASSIMP_H
|
||||
|
||||
#include "config_assimp.h"
|
||||
#include "loaderFileType.h"
|
||||
|
||||
class AssimpLoader;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : LoaderFileTypeAssimp
|
||||
// Description : This defines the Loader interface that uses the
|
||||
// Assimp library to load various model formats.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_ASSIMP LoaderFileTypeAssimp : public LoaderFileType {
|
||||
public:
|
||||
LoaderFileTypeAssimp();
|
||||
virtual ~LoaderFileTypeAssimp();
|
||||
|
||||
virtual string get_name() const;
|
||||
virtual string get_extension() const;
|
||||
virtual string get_additional_extensions() const;
|
||||
virtual bool supports_compressed() const;
|
||||
|
||||
virtual PT(PandaNode) load_file(const Filename &path, const LoaderOptions &options,
|
||||
BamCacheRecord *record) const;
|
||||
|
||||
public:
|
||||
AssimpLoader *_loader;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
LoaderFileType::init_type();
|
||||
register_type(_type_handle, "LoaderFileTypeAssimp",
|
||||
LoaderFileType::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
104
pandatool/src/assimp/pandaIOStream.cxx
Normal file
104
pandatool/src/assimp/pandaIOStream.cxx
Normal file
@ -0,0 +1,104 @@
|
||||
// Filename: pandaIOStream.cxx
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandaIOStream.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOStream::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaIOStream::
|
||||
PandaIOStream(istream &stream) : _istream(stream) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOStream::FileSize
|
||||
// Access: Public
|
||||
// Description: Returns the size of this file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t PandaIOStream::
|
||||
FileSize() const {
|
||||
nassertr(false, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOStream::Flush
|
||||
// Access: Public
|
||||
// Description: See fflush.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaIOStream::
|
||||
Flush() {
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOStream::Read
|
||||
// Access: Public
|
||||
// Description: See fread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t PandaIOStream::
|
||||
Read(void *buffer, size_t size, size_t count) {
|
||||
_istream.read((char*) buffer, size * count);
|
||||
return _istream.gcount();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOStream::Seek
|
||||
// Access: Public
|
||||
// Description: See fseek.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
aiReturn PandaIOStream::
|
||||
Seek(size_t offset, aiOrigin origin) {
|
||||
switch (origin) {
|
||||
case aiOrigin_SET:
|
||||
_istream.seekg(offset, ios::beg);
|
||||
break;
|
||||
|
||||
case aiOrigin_CUR:
|
||||
_istream.seekg(offset, ios::cur);
|
||||
break;
|
||||
|
||||
case aiOrigin_END:
|
||||
_istream.seekg(offset, ios::end);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_istream.good()) {
|
||||
return AI_SUCCESS;
|
||||
} else {
|
||||
return AI_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOStream::Tell
|
||||
// Access: Public
|
||||
// Description: See ftell.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t PandaIOStream::
|
||||
Tell() const {
|
||||
_istream.tellg();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOStream::Write
|
||||
// Access: Public
|
||||
// Description: See fwrite.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t PandaIOStream::
|
||||
Write(const void *buffer, size_t size, size_t count) {
|
||||
nassertr(false, 0);
|
||||
}
|
48
pandatool/src/assimp/pandaIOStream.h
Normal file
48
pandatool/src/assimp/pandaIOStream.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Filename: pandaIOStream.h
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PANDAIOSTREAM_H
|
||||
#define PANDAIOSTREAM_H
|
||||
|
||||
#include "config_assimp.h"
|
||||
|
||||
#include "IOStream.h"
|
||||
|
||||
class PandaIOSystem;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PandaIOStream
|
||||
// Description : Custom implementation of Assimp::IOStream. It
|
||||
// simply wraps around an istream object, and is
|
||||
// unable to write.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PandaIOStream : public Assimp::IOStream {
|
||||
public:
|
||||
PandaIOStream(istream &stream);
|
||||
virtual ~PandaIOStream() {};
|
||||
|
||||
size_t FileSize() const;
|
||||
void Flush();
|
||||
size_t Read(void *pvBuffer, size_t pSize, size_t pCount);
|
||||
aiReturn Seek(size_t pOffset, aiOrigin pOrigin);
|
||||
size_t Tell() const;
|
||||
size_t Write(const void *buffer, size_t size, size_t count);
|
||||
|
||||
private:
|
||||
istream &_istream;
|
||||
|
||||
friend class PandaIOSystem;
|
||||
};
|
||||
|
||||
#endif
|
99
pandatool/src/assimp/pandaIOSystem.cxx
Normal file
99
pandatool/src/assimp/pandaIOSystem.cxx
Normal file
@ -0,0 +1,99 @@
|
||||
// Filename: pandaIOSystem.cxx
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandaIOSystem.h"
|
||||
#include "pandaIOStream.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOSystem::Constructor
|
||||
// Access: Public
|
||||
// Description: Initializes the object with the given VFS, or the
|
||||
// global one if none was specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PandaIOSystem::
|
||||
PandaIOSystem(VirtualFileSystem *vfs) : _vfs(vfs) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOSystem::Exists
|
||||
// Access: Public
|
||||
// Description: Returns true if the file exists, duh.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PandaIOSystem::
|
||||
Exists(const char *file) const {
|
||||
Filename fn = Filename::from_os_specific(file);
|
||||
return _vfs->exists(fn);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOSystem::Close
|
||||
// Access: Public
|
||||
// Description: Closes the indicated file stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaIOSystem::
|
||||
Close(Assimp::IOStream *file) {
|
||||
PandaIOStream *pstr = (PandaIOStream*) file;
|
||||
_vfs->close_read_file(&pstr->_istream);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOSystem::ComparePaths
|
||||
// Access: Public
|
||||
// Description: Returns true if the two paths point to the same
|
||||
// file, false if not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PandaIOSystem::
|
||||
ComparePaths(const char *p1, const char *p2) const {
|
||||
Filename fn1 = Filename::from_os_specific(p1);
|
||||
Filename fn2 = Filename::from_os_specific(p2);
|
||||
fn1.make_canonical();
|
||||
fn2.make_canonical();
|
||||
return fn1 == fn2;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOSystem::getOsSeparator
|
||||
// Access: Public
|
||||
// Description: Returns the path separator for this operating
|
||||
// system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
char PandaIOSystem::
|
||||
getOsSeparator() const {
|
||||
#ifdef _WIN32
|
||||
return '\\';
|
||||
#else
|
||||
return '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaIOSystem::Open
|
||||
// Access: Public
|
||||
// Description: Opens the indicated file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Assimp::IOStream *PandaIOSystem::
|
||||
Open(const char *file, const char *mode) {
|
||||
Filename fn = Filename::from_os_specific(file);
|
||||
|
||||
if (mode[0] == 'r') {
|
||||
istream *stream = _vfs->open_read_file(file, true);
|
||||
if (stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return new PandaIOStream(*stream);
|
||||
|
||||
} else {
|
||||
nassertr(false, NULL); // Not implemented on purpose.
|
||||
}
|
||||
}
|
43
pandatool/src/assimp/pandaIOSystem.h
Normal file
43
pandatool/src/assimp/pandaIOSystem.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Filename: pandaIOSystem.h
|
||||
// Created by: rdb (29Mar11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PANDAIOSYSTEM_H
|
||||
#define PANDAIOSYSTEM_H
|
||||
|
||||
#include "config_assimp.h"
|
||||
#include "virtualFileSystem.h"
|
||||
|
||||
#include "IOSystem.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PandaIOSystem
|
||||
// Description : Custom implementation of Assimp::IOSystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PandaIOSystem : public Assimp::IOSystem {
|
||||
public:
|
||||
PandaIOSystem(VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr());
|
||||
virtual ~PandaIOSystem() {};
|
||||
|
||||
void Close(Assimp::IOStream *file);
|
||||
bool ComparePaths(const char *p1, const char *p2) const;
|
||||
bool Exists(const char *file) const;
|
||||
char getOsSeparator() const;
|
||||
Assimp::IOStream *Open(const char *file, const char *mode);
|
||||
|
||||
private:
|
||||
VirtualFileSystem *_vfs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
71
pandatool/src/assimp/pandaLogger.cxx
Normal file
71
pandatool/src/assimp/pandaLogger.cxx
Normal file
@ -0,0 +1,71 @@
|
||||
// Filename: pandaLogger.cxx
|
||||
// Created by: rdb (05May11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandaLogger.h"
|
||||
|
||||
#include "DefaultLogger.h"
|
||||
|
||||
PandaLogger *PandaLogger::_ptr = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaLogger::set_default
|
||||
// Access: Public
|
||||
// Description: Makes sure there's a global PandaLogger object and
|
||||
// makes sure that it is Assimp's default logger.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaLogger::
|
||||
set_default() {
|
||||
if (_ptr == NULL) {
|
||||
_ptr = new PandaLogger;
|
||||
}
|
||||
if (_ptr != Assimp::DefaultLogger::get()) {
|
||||
Assimp::DefaultLogger::set(_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaLogger::OnDebug
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaLogger::OnDebug(const char *message) {
|
||||
assimp_cat.debug() << message << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaLogger::OnError
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaLogger::OnError(const char *message) {
|
||||
assimp_cat.error() << message << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaLogger::OnInfo
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaLogger::OnInfo(const char *message) {
|
||||
assimp_cat.info() << message << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaLogger::OnWarn
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaLogger::OnWarn(const char *message) {
|
||||
assimp_cat.warning() << message << "\n";
|
||||
}
|
44
pandatool/src/assimp/pandaLogger.h
Normal file
44
pandatool/src/assimp/pandaLogger.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Filename: pandaLogger.h
|
||||
// Created by: rdb (05May11)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
//
|
||||
// All use of this software is subject to the terms of the revised BSD
|
||||
// license. You should have received a copy of this license along
|
||||
// with this source code in a file named "LICENSE."
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PANDALOGGER_H
|
||||
#define PANDALOGGER_H
|
||||
|
||||
#include "config_assimp.h"
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PandaLogger
|
||||
// Description : Custom implementation of Assimp::Logger. It
|
||||
// simply wraps around the assimp_cat methods.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PandaLogger : public Assimp::Logger {
|
||||
public:
|
||||
static void set_default();
|
||||
|
||||
protected:
|
||||
INLINE bool attachStream(Assimp::LogStream*, unsigned int) {};
|
||||
INLINE bool detatchStream(Assimp::LogStream*, unsigned int) {};
|
||||
|
||||
void OnDebug(const char *message);
|
||||
void OnError(const char *message);
|
||||
void OnInfo(const char *message);
|
||||
void OnWarn(const char *message);
|
||||
|
||||
private:
|
||||
static PandaLogger *_ptr;
|
||||
};
|
||||
|
||||
#endif
|
@ -19,6 +19,14 @@
|
||||
|
||||
#if defined(WIN32_VC) && !defined(CPPPARSER) && !defined(LINK_ALL_STATIC)
|
||||
|
||||
#ifdef BUILDING_ASSIMP
|
||||
#define EXPCL_ASSIMP __declspec(dllexport)
|
||||
#define EXPTP_ASSIMP
|
||||
#else
|
||||
#define EXPCL_ASSIMP __declspec(dllimport)
|
||||
#define EXPTP_ASSIMP extern
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_PTLOADER
|
||||
#define EXPCL_PTLOADER __declspec(dllexport)
|
||||
#define EXPTP_PTLOADER
|
||||
@ -29,6 +37,9 @@
|
||||
|
||||
#else /* !WIN32_VC */
|
||||
|
||||
#define EXPCL_ASSIMP
|
||||
#define EXPTP_ASSIMP
|
||||
|
||||
#define EXPCL_PTLOADER
|
||||
#define EXPTP_PTLOADER
|
||||
|
||||
|
@ -94,10 +94,10 @@ init_libptloader() {
|
||||
ObjToEggConverter *obj = new ObjToEggConverter;
|
||||
reg->register_type(new LoaderFileTypePandatool(obj));
|
||||
|
||||
#ifdef HAVE_FCOLLADA
|
||||
DAEToEggConverter *dae = new DAEToEggConverter;
|
||||
reg->register_type(new LoaderFileTypePandatool(dae));
|
||||
#endif
|
||||
//#ifdef HAVE_FCOLLADA
|
||||
// DAEToEggConverter *dae = new DAEToEggConverter;
|
||||
// reg->register_type(new LoaderFileTypePandatool(dae));
|
||||
//#endif
|
||||
|
||||
#ifdef HAVE_MAYA
|
||||
// Register the Maya converter as a deferred type. We don't compile
|
||||
|
Loading…
x
Reference in New Issue
Block a user