15 #include "colladaLoader.h" 16 #include "virtualFileSystem.h" 18 #include "string_utils.h" 20 #include "geomVertexWriter.h" 21 #include "geomTriangles.h" 22 #include "lightNode.h" 23 #include "lightAttrib.h" 24 #include "ambientLight.h" 25 #include "directionalLight.h" 26 #include "pointLight.h" 27 #include "spotlight.h" 29 #include "colladaBindMaterial.h" 30 #include "colladaPrimitive.h" 33 #include "pre_collada_include.h" 34 #include <dom/domCOLLADA.h> 35 #include <dom/domNode.h> 36 #include <dom/domVisual_scene.h> 37 #include <dom/domTranslate.h> 38 #include <dom/domRotate.h> 39 #include <dom/domMatrix.h> 41 #if PANDA_COLLADA_VERSION >= 15 42 #include <dom/domInstance_with_extra.h> 44 #include <dom/domInstanceWithExtra.h> 45 #define domInstance_with_extra domInstanceWithExtra 46 #define domTargetable_floatRef domTargetableFloatRef 49 #define TOSTRING(x) (x == NULL ? "" : x) 86 if (!vfs->read_file(_filename, data,
true)) {
88 <<
"Error reading " << _filename <<
"\n";
93 _collada = _dae->openFromMemory(_filename.
to_os_specific(), data.c_str());
94 _error = (_collada == NULL);
110 domCOLLADA::domScene* scene = _collada->getScene();
111 domInstance_with_extra* inst = scene->getInstance_visual_scene();
112 domVisual_scene* vscene = daeSafeCast<domVisual_scene> (inst->getUrl().getElement());
114 load_visual_scene(*vscene, _root);
123 load_visual_scene(domVisual_scene& scene,
PandaNode *parent) {
125 if (scene.getUserData() != NULL) {
126 parent->add_child((
PandaNode *) scene.getUserData());
131 scene.setUserData((
void *) pnode);
132 parent->add_child(pnode);
135 domExtra_Array &extras = scene.getExtra_array();
136 for (
size_t i = 0; i < extras.getCount(); ++i) {
137 load_tags(*extras[i], pnode);
141 domNode_Array &nodes = scene.getNode_array();
142 for (
size_t i = 0; i < nodes.getCount(); ++i) {
143 load_node(*nodes[i], pnode);
147 if (_lights.size() > 0) {
150 for (it = _lights.begin(); it != _lights.end(); ++it) {
151 lattr = DCAST(
LightAttrib, lattr->add_on_light(*it));
153 pnode->set_state(RenderState::make(lattr));
164 load_node(domNode& node,
PandaNode *parent) {
166 if (node.getUserData() != NULL) {
167 parent->add_child((
PandaNode *) node.getUserData());
173 pnode =
new PandaNode(TOSTRING(node.getName()));
174 node.setUserData((
void *) pnode);
175 parent->add_child(pnode);
180 daeElementRefArray &elements = node.getContents();
181 for (
size_t i = elements.getCount(); i > 0; --i) {
182 daeElementRef &elem = elements[i - 1];
184 switch (elem->getElementType()) {
185 case COLLADA_TYPE::LOOKAT: {
187 domFloat3x3 &l = (daeSafeCast<domLookat>(elem))->getValue();
194 up = side.cross(forward);
203 case COLLADA_TYPE::MATRIX: {
204 domFloat4x4 &m = (daeSafeCast<domMatrix>(elem))->getValue();
206 m[0], m[4], m[ 8], m[12],
207 m[1], m[5], m[ 9], m[13],
208 m[2], m[6], m[10], m[14],
209 m[3], m[7], m[11], m[15]);
212 case COLLADA_TYPE::ROTATE: {
213 domFloat4 &r = (daeSafeCast<domRotate>(elem))->getValue();
217 case COLLADA_TYPE::SCALE: {
218 domFloat3 &s = (daeSafeCast<domScale>(elem))->getValue();
222 case COLLADA_TYPE::SKEW:
224 collada_cat.error() <<
"<skew> not supported yet\n";
226 case COLLADA_TYPE::TRANSLATE: {
227 domFloat3 &t = (daeSafeCast<domTranslate>(elem))->getValue();
238 pnode->set_transform(TransformState::make_mat(transform));
242 domInstance_camera_Array &caminst = node.getInstance_camera_array();
243 for (
size_t i = 0; i < caminst.getCount(); ++i) {
244 domCamera* target = daeSafeCast<domCamera> (caminst[i]->getUrl().getElement());
245 load_camera(*target, pnode);
249 domInstance_controller_Array &ctrlinst = node.getInstance_controller_array();
250 for (
size_t i = 0; i < ctrlinst.getCount(); ++i) {
251 domController* target = daeSafeCast<domController> (ctrlinst[i]->getUrl().getElement());
253 if (target->getSkin() != NULL) {
254 domGeometry* geom = daeSafeCast<domGeometry> (target->getSkin()->getSource().getElement());
261 domInstance_geometry_Array &ginst = node.getInstance_geometry_array();
262 for (
size_t i = 0; i < ginst.getCount(); ++i) {
263 load_instance_geometry(*ginst[i], pnode);
267 domInstance_light_Array &linst = node.getInstance_light_array();
268 for (
size_t i = 0; i < linst.getCount(); ++i) {
269 domLight* target = daeSafeCast<domLight> (linst[i]->getUrl().getElement());
270 load_light(*target, pnode);
274 domInstance_node_Array &ninst = node.getInstance_node_array();
275 for (
size_t i = 0; i < ninst.getCount(); ++i) {
276 domNode* target = daeSafeCast<domNode> (ninst[i]->getUrl().getElement());
277 load_node(*target, pnode);
281 domNode_Array &nodes = node.getNode_array();
282 for (
size_t i = 0; i < nodes.getCount(); ++i) {
283 load_node(*nodes[i], pnode);
287 domExtra_Array &extras = node.getExtra_array();
288 for (
size_t i = 0; i < extras.getCount(); ++i) {
289 load_tags(*extras[i], pnode);
300 load_tags(domExtra &extra,
PandaNode *node) {
301 domTechnique_Array &techniques = extra.getTechnique_array();
303 for (
size_t t = 0; t < techniques.getCount(); ++t) {
304 if (cmp_nocase(techniques[t]->getProfile(),
"PANDA3D") == 0) {
305 const daeElementRefArray &children = techniques[t]->getChildren();
307 for (
size_t c = 0; c < children.getCount(); ++c) {
308 daeElement &child = *children[c];
310 if (cmp_nocase(child.getElementName(),
"tag") == 0) {
311 const string &name = child.getAttribute(
"name");
312 if (name.size() > 0) {
313 node->
set_tag(name, child.getCharData());
315 collada_cat.warning() <<
"Ignoring <tag> without name attribute\n";
317 }
else if (cmp_nocase(child.getElementName(),
"param") == 0) {
318 collada_cat.error() <<
319 "Unknown <param> attribute in PANDA3D technique. " 320 "Did you mean to use <tag> instead?\n";
332 load_camera(domCamera &cam,
PandaNode *parent) {
334 if (cam.getUserData() != NULL) {
335 parent->add_child((
PandaNode *) cam.getUserData());
348 load_instance_geometry(domInstance_geometry &inst,
PandaNode *parent) {
350 if (inst.getUserData() != NULL) {
351 parent->add_child((
PandaNode *) inst.getUserData());
355 domGeometry* geom = daeSafeCast<domGeometry> (inst.getUrl().getElement());
356 nassertv(geom != NULL);
360 inst.setUserData((
void *) gnode);
361 parent->add_child(gnode);
363 domBind_materialRef bind_mat = inst.getBind_material();
365 if (bind_mat != NULL) {
366 cbm.load_bind_material(*bind_mat);
369 load_geometry(*geom, gnode, cbm);
372 domExtra_Array &extras = geom->getExtra_array();
373 for (
size_t i = 0; i < extras.getCount(); ++i) {
374 load_tags(*extras[i], gnode);
385 domMesh* mesh = geom.getMesh();
392 domLines_Array &lines_array = mesh->getLines_array();
393 for (
size_t i = 0; i < lines_array.getCount(); ++i) {
400 domLinestrips_Array &linestrips_array = mesh->getLinestrips_array();
401 for (
size_t i = 0; i < linestrips_array.getCount(); ++i) {
408 domPolygons_Array &polygons_array = mesh->getPolygons_array();
409 for (
size_t i = 0; i < polygons_array.getCount(); ++i) {
416 domPolylist_Array &polylist_array = mesh->getPolylist_array();
417 for (
size_t i = 0; i < polylist_array.getCount(); ++i) {
424 domTriangles_Array &triangles_array = mesh->getTriangles_array();
425 for (
size_t i = 0; i < triangles_array.getCount(); ++i) {
432 domTrifans_Array &trifans_array = mesh->getTrifans_array();
433 for (
size_t i = 0; i < trifans_array.getCount(); ++i) {
440 domTristrips_Array &tristrips_array = mesh->getTristrips_array();
441 for (
size_t i = 0; i < tristrips_array.getCount(); ++i) {
454 load_light(domLight &light,
PandaNode *parent) {
456 if (light.getUserData() != NULL) {
457 parent->add_child((
PandaNode *) light.getUserData());
462 domLight::domTechnique_common &tc = *light.getTechnique_common();
465 domLight::domTechnique_common::domAmbientRef ambient = tc.getAmbient();
466 if (ambient != NULL) {
470 domFloat3 &
color = ambient->getColor()->getValue();
471 alight->set_color(
LColor(color[0], color[1], color[2], 1.0));
475 domLight::domTechnique_common::domDirectionalRef directional = tc.getDirectional();
476 if (directional != NULL) {
480 domFloat3 &
color = directional->getColor()->getValue();
481 dlight->set_color(
LColor(color[0], color[1], color[2], 1.0));
482 dlight->set_direction(
LVector3f(0, 0, -1));
486 domLight::domTechnique_common::domPointRef point = tc.getPoint();
491 domFloat3 &
color = point->getColor()->getValue();
492 plight->set_color(
LColor(color[0], color[1], color[2], 1.0));
495 domTargetable_floatRef fval = point->getConstant_attenuation();
497 atten[0] = fval->getValue();
499 fval = point->getLinear_attenuation();
501 atten[1] = fval->getValue();
503 fval = point->getQuadratic_attenuation();
505 atten[2] = fval->getValue();
508 plight->set_attenuation(atten);
512 domLight::domTechnique_common::domSpotRef spot = tc.getSpot();
517 domFloat3 &
color = spot->getColor()->getValue();
518 slight->set_color(
LColor(color[0], color[1], color[2], 1.0));
521 domTargetable_floatRef fval = spot->getConstant_attenuation();
523 atten[0] = fval->getValue();
525 fval = spot->getLinear_attenuation();
527 atten[1] = fval->getValue();
529 fval = spot->getQuadratic_attenuation();
531 atten[2] = fval->getValue();
534 slight->set_attenuation(atten);
536 fval = spot->getFalloff_angle();
538 slight->get_lens()->set_fov(fval->getValue());
540 slight->get_lens()->set_fov(180.0f);
543 fval = spot->getFalloff_exponent();
545 slight->set_exponent(fval->getValue());
547 slight->set_exponent(0.0f);
554 parent->add_child(lnode);
555 _lights.push_back(lnode);
556 light.setUserData((
void*) lnode);
559 domExtra_Array &extras = light.getExtra_array();
560 for (
size_t i = 0; i < extras.getCount(); ++i) {
561 load_tags(*extras[i], lnode);
A node of this type is created automatically at the root of each model file that is loaded...
A light shining from infinitely far away in a particular direction, like sunlight.
void set_tag(const string &key, const string &value, Thread *current_thread=Thread::get_current_thread())
Associates a user-defined value with a user-defined key which is stored on the node.
string get_basename() const
Returns the basename part of the filename.
static const LMatrix4f & ident_mat()
Returns an identity matrix.
A basic node of the scene graph or data graph.
This is the base class for all three-component vectors and points.
static LMatrix4f scale_mat(const LVecBase3f &scale)
Returns a matrix that applies the indicated scale in each of the three axes.
static LMatrix4f translate_mat(const LVecBase3f &trans)
Returns a matrix that applies the indicated translation.
A derivative of Light and of PandaNode.
static LMatrix4f rotate_mat(float angle, const LVecBase3f &axis, CoordinateSystem cs=CS_default)
Returns a matrix that rotates by the given angle in degrees counterclockwise about the indicated vect...
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
A light source that seems to illuminate all points in space at once.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
void build_graph()
Converts scene graph structures into a Panda3D scene graph, with _root being the root node...
This is our own Panda specialization on the default STL vector.
The name of a file, such as a texture file or an Egg file.
This is a 4-by-4 transform matrix.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
A light originating from a single point in space, and shining in a particular direction, with a cone-shaped falloff.
static ColladaPrimitive * from_dom(domLines &lines)
Returns the ColladaPrimitive object that represents the provided DOM input element.
void set_col(int col, const LVecBase4f &v)
Replaces the indicated column of the matrix.
This is the base class for all three-component vectors and points.
Class that deals with COLLADA primitive structures, such as <triangles> and <polylist>.
bool normalize()
Normalizes the vector in place.
string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
Class that deals with binding materials to COLLADA geometry.
A light originating from a single point in space, and shining in all directions.
A node that holds Geom objects, renderable pieces of geometry.
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
bool read(const Filename &filename)
Reads from the indicated file.
Indicates which set of lights should be considered "on" to illuminate geometry at this level and belo...