42 #include <assimp/postprocess.h> 44 using std::ostringstream;
45 using std::stringstream;
53 : joint_vertex_xform(joint_vertex_xform), weight(weight)
75 _importer.FreeScene();
85 _importer.GetExtensionList(aexts);
88 char *sub = strtok(aexts.data,
";");
89 while (sub !=
nullptr) {
91 sub = strtok(
nullptr,
";");
104 _filename = filename;
106 unsigned int flags = aiProcess_Triangulate | aiProcess_GenUVCoords;
108 if (assimp_calc_tangent_space) {
109 flags |= aiProcess_CalcTangentSpace;
111 if (assimp_join_identical_vertices) {
112 flags |= aiProcess_JoinIdenticalVertices;
114 if (assimp_improve_cache_locality) {
115 flags |= aiProcess_ImproveCacheLocality;
117 if (assimp_remove_redundant_materials) {
118 flags |= aiProcess_RemoveRedundantMaterials;
120 if (assimp_fix_infacing_normals) {
121 flags |= aiProcess_FixInfacingNormals;
123 if (assimp_optimize_meshes) {
124 flags |= aiProcess_OptimizeMeshes;
126 if (assimp_optimize_graph) {
127 flags |= aiProcess_OptimizeGraph;
129 if (assimp_flip_winding_order) {
130 flags |= aiProcess_FlipWindingOrder;
132 if (assimp_gen_normals) {
133 if (assimp_smooth_normal_angle == 0.0) {
134 flags |= aiProcess_GenNormals;
137 flags |= aiProcess_GenSmoothNormals;
138 _importer.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,
139 assimp_smooth_normal_angle);
143 _scene = _importer.ReadFile(_filename.c_str(), flags);
144 if (_scene ==
nullptr) {
159 nassertv(_scene !=
nullptr);
168 _textures =
new PT(
Texture)[_scene->mNumTextures];
169 for (
size_t i = 0; i < _scene->mNumTextures; ++i) {
174 _mat_states =
new CPT(
RenderState)[_scene->mNumMaterials];
175 for (
size_t i = 0; i < _scene->mNumMaterials; ++i) {
180 _geoms =
new PT(
Geom)[_scene->mNumMeshes];
181 _geom_matindices =
new unsigned int[_scene->mNumMeshes];
182 for (
size_t i = 0; i < _scene->mNumMeshes; ++i) {
187 if (_scene->mRootNode !=
nullptr) {
188 load_node(*_scene->mRootNode, _root);
192 for (
size_t i = 0; i < _scene->mNumLights; ++i) {
193 load_light(*_scene->mLights[i]);
197 delete[] _mat_states;
199 delete[] _geom_matindices;
205 const aiNode *AssimpLoader::
206 find_node(
const aiNode &root,
const aiString &name) {
209 if (root.mName == name) {
212 for (
size_t i = 0; i < root.mNumChildren; ++i) {
213 node = find_node(*root.mChildren[i], name);
227 load_texture(
size_t index) {
228 const aiTexture &tex = *_scene->mTextures[index];
232 if (tex.mHeight == 0) {
235 <<
"Reading embedded compressed texture with format " << tex.achFormatHint <<
" and size " << tex.mWidth <<
"\n";
237 str.
write((
char*) tex.pcData, tex.mWidth);
239 if (strncmp(tex.achFormatHint,
"dds", 3) == 0) {
248 if (strncmp(tex.achFormatHint,
"jp\0", 3) == 0) {
254 if (img.
read(str,
"", ftype)) {
262 <<
"Reading embedded raw texture with size " << tex.mWidth <<
"x" << tex.mHeight <<
"\n";
264 ptex->setup_2d_texture(tex.mWidth, tex.mHeight, Texture::T_unsigned_byte, Texture::F_rgba);
265 PTA_uchar data = ptex->modify_ram_image();
268 for (
size_t i = 0; i < tex.mWidth * tex.mHeight; ++i) {
269 const aiTexel &texel = tex.pcData[i];
280 _textures[index] = ptex;
288 load_texture_stage(
const aiMaterial &mat,
const aiTextureType &ttype, CPT(
TextureAttrib) &tattr) {
290 aiTextureMapping mapping;
291 unsigned int uvindex;
294 aiTextureMapMode mapmode;
296 for (
size_t i = 0; i < mat.GetTextureCount(ttype); ++i) {
297 mat.GetTexture(ttype, i, &path, &mapping,
nullptr, &blend, &op, &mapmode);
299 if (AI_SUCCESS != mat.Get(AI_MATKEY_UVWSRC(ttype, i), uvindex)) {
316 if (path.data[0] ==
'*') {
317 long num = strtol(path.data + 1,
nullptr, 10);
318 ptex = _textures[num];
320 }
else if (path.length > 0) {
350 if (ptex !=
nullptr) {
351 tattr = DCAST(
TextureAttrib, tattr->add_on_stage(stage, ptex));
360 load_material(
size_t index) {
361 const aiMaterial &mat = *_scene->mMaterials[index];
363 CPT(
RenderState) state = RenderState::make_empty();
375 if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_DIFFUSE, col)) {
379 if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_SPECULAR, col)) {
380 if (AI_SUCCESS == mat.Get(AI_MATKEY_SHININESS_STRENGTH, fval)) {
381 pmat->set_specular(LColor(col.r * fval, col.g * fval, col.b * fval, 1));
383 pmat->set_specular(LColor(col.r, col.g, col.b, 1));
387 if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_AMBIENT, col)) {
388 pmat->set_specular(LColor(col.r, col.g, col.b, 1));
391 if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_EMISSIVE, col)) {
392 pmat->set_emission(LColor(col.r, col.g, col.b, 1));
395 if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_TRANSPARENT, col)) {
398 if (AI_SUCCESS == mat.Get(AI_MATKEY_SHININESS, fval)) {
399 pmat->set_shininess(fval);
403 state = state->add_attrib(MaterialAttrib::make(pmat));
407 if (AI_SUCCESS == mat.Get(AI_MATKEY_ENABLE_WIREFRAME, ival)) {
409 state = state->add_attrib(RenderModeAttrib::make(RenderModeAttrib::M_wireframe));
411 state = state->add_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled));
417 if (AI_SUCCESS == mat.Get(AI_MATKEY_TWOSIDED, ival)) {
419 state = state->add_attrib(CullFaceAttrib::make(CullFaceAttrib::M_cull_none));
421 state = state->add_attrib(CullFaceAttrib::make_default());
427 load_texture_stage(mat, aiTextureType_DIFFUSE, tattr);
428 load_texture_stage(mat, aiTextureType_LIGHTMAP, tattr);
430 state = state->add_attrib(tattr);
433 _mat_states[index] = state;
441 const aiMatrix4x4 &t = node.mTransformation;
442 LMatrix4 mat(t.a1, t.b1, t.c1, t.d1,
443 t.a2, t.b2, t.c2, t.d2,
444 t.a3, t.b3, t.c3, t.d3,
445 t.a4, t.b4, t.c4, t.d4);
449 <<
"Creating joint for: " << node.mName.C_Str() <<
"\n";
451 for (
size_t i = 0; i < node.mNumChildren; ++i) {
452 if (_bonemap.find(node.mChildren[i]->mName.C_Str()) != _bonemap.end()) {
453 create_joint(character, bundle, joint, *node.mChildren[i]);
462 create_anim_channel(
const aiAnimation &anim,
AnimBundle *bundle,
AnimGroup *parent,
const aiNode &node) {
466 aiNodeAnim *node_anim =
nullptr;
467 for (
size_t i = 0; i < anim.mNumChannels; ++i) {
468 if (anim.mChannels[i]->mNodeName == node.mName) {
469 node_anim = anim.mChannels[i];
475 <<
"Found channel for node: " << node.mName.C_Str() <<
"\n";
483 PTA_stdfloat tablex = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys);
484 PTA_stdfloat tabley = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys);
485 PTA_stdfloat tablez = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys);
486 for (
size_t i = 0; i < node_anim->mNumPositionKeys; ++i) {
487 tablex[i] = node_anim->mPositionKeys[i].mValue.x;
488 tabley[i] = node_anim->mPositionKeys[i].mValue.y;
489 tablez[i] = node_anim->mPositionKeys[i].mValue.z;
491 group->set_table(
'x', tablex);
492 group->set_table(
'y', tabley);
493 group->set_table(
'z', tablez);
496 PTA_stdfloat tableh = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys);
497 PTA_stdfloat tablep = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys);
498 PTA_stdfloat tabler = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys);
499 for (
size_t i = 0; i < node_anim->mNumRotationKeys; ++i) {
500 aiQuaternion ai_quat = node_anim->mRotationKeys[i].mValue;
501 LVecBase3 hpr = LQuaternion(ai_quat.w, ai_quat.x, ai_quat.y, ai_quat.z).get_hpr();
502 tableh[i] = hpr.get_x();
503 tablep[i] = hpr.get_y();
504 tabler[i] = hpr.get_z();
506 group->set_table(
'h', tableh);
507 group->set_table(
'p', tablep);
508 group->set_table(
'r', tabler);
511 PTA_stdfloat tablei = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys);
512 PTA_stdfloat tablej = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys);
513 PTA_stdfloat tablek = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys);
514 for (
size_t i = 0; i < node_anim->mNumScalingKeys; ++i) {
515 tablei[i] = node_anim->mScalingKeys[i].mValue.x;
516 tablej[i] = node_anim->mScalingKeys[i].mValue.y;
517 tablek[i] = node_anim->mScalingKeys[i].mValue.z;
519 group->set_table(
'i', tablei);
520 group->set_table(
'j', tablej);
521 group->set_table(
'k', tablek);
525 <<
"No channel found for node: " << node.mName.C_Str() <<
"\n";
529 for (
size_t i = 0; i < node.mNumChildren; ++i) {
530 if (_bonemap.find(node.mChildren[i]->mName.C_Str()) != _bonemap.end()) {
531 create_anim_channel(anim, bundle, group, *node.mChildren[i]);
540 load_mesh(
size_t index) {
541 const aiMesh &mesh = *_scene->mMeshes[index];
545 if (mesh.HasBones()) {
547 <<
"Creating character for " << mesh.mName.C_Str() <<
"\n";
550 for (
size_t i = 0; i < mesh.mNumBones; ++i) {
551 const aiBone &bone = *mesh.mBones[i];
552 const aiNode *node = find_node(*_scene->mRootNode, bone.mName);
553 _bonemap[bone.mName.C_Str()] = node;
557 character =
new Character(mesh.mName.C_Str());
561 for (
size_t i = 0; i < mesh.mNumBones; ++i) {
562 const aiBone &bone = *mesh.mBones[i];
565 const aiNode *root = _bonemap[bone.mName.C_Str()];
566 while (root->mParent && _bonemap.find(root->mParent->mName.C_Str()) != _bonemap.end()) {
567 root = root->mParent;
571 if (character->
find_joint(root->mName.C_Str())) {
575 create_joint(character, bundle, skeleton, *root);
583 for (
size_t i = 0; i < mesh.mNumBones; ++i) {
584 const aiBone &bone = *mesh.mBones[i];
586 if (joint ==
nullptr) {
588 <<
"Could not find joint for bone: " << bone.mName.C_Str() <<
"\n";
594 for (
size_t j = 0; j < bone.mNumWeights; ++j) {
595 const aiVertexWeight &weight = bone.mWeights[j];
597 bone_weights[weight.mVertexId].push_back(BoneWeight(jvt, weight.mWeight));
604 aformat->
add_column(InternalName::get_vertex(), 3, Geom::NT_stdfloat, Geom::C_point);
605 if (mesh.HasNormals()) {
606 aformat->add_column(InternalName::get_normal(), 3, Geom::NT_stdfloat, Geom::C_vector);
608 if (mesh.HasVertexColors(0)) {
609 aformat->add_column(InternalName::get_color(), 4, Geom::NT_stdfloat, Geom::C_color);
611 unsigned int num_uvs = mesh.GetNumUVChannels();
614 aformat->add_column(InternalName::get_texcoord(), 3, Geom::NT_stdfloat, Geom::C_texcoord);
615 for (
unsigned int u = 1; u < num_uvs; ++u) {
618 aformat->add_column(InternalName::get_texcoord_name(out.str()), 3, Geom::NT_stdfloat, Geom::C_texcoord);
623 tb_aformat->
add_column(InternalName::make(
"transform_blend"), 1, Geom::NT_uint16, Geom::C_index);
626 for (
size_t i = 0; i < _scene->mNumAnimations; ++i) {
627 aiAnimation &ai_anim = *_scene->mAnimations[i];
628 bool convert_anim =
false;
631 <<
"Checking to see if anim (" << ai_anim.mName.C_Str() <<
") matches character (" << mesh.mName.C_Str() <<
")\n";
632 for (
size_t j = 0; j < ai_anim.mNumChannels; ++j) {
634 <<
"Searching for " << ai_anim.mChannels[j]->mNodeName.C_Str() <<
" in bone map" <<
"\n";
635 if (_bonemap.find(ai_anim.mChannels[j]->mNodeName.C_Str()) != _bonemap.end()) {
643 <<
"Found animation (" << ai_anim.mName.C_Str() <<
") for character (" << mesh.mName.C_Str() <<
")\n";
646 unsigned int frames = 0;
647 for (
size_t j = 0; j < ai_anim.mNumChannels; ++j) {
648 if (ai_anim.mChannels[j]->mNumPositionKeys > frames) {
649 frames = ai_anim.mChannels[j]->mNumPositionKeys;
651 if (ai_anim.mChannels[j]->mNumRotationKeys > frames) {
652 frames = ai_anim.mChannels[j]->mNumRotationKeys;
654 if (ai_anim.mChannels[j]->mNumScalingKeys > frames) {
655 frames = ai_anim.mChannels[j]->mNumScalingKeys;
658 PN_stdfloat fps = frames / (ai_anim.mTicksPerSecond * ai_anim.mDuration);
660 <<
"FPS " << fps <<
"\n";
662 <<
"Frames " << frames <<
"\n";
667 for (
size_t i = 0; i < mesh.mNumBones; ++i) {
668 const aiBone &bone = *mesh.mBones[i];
671 const aiNode *root = _bonemap[bone.mName.C_Str()];
672 while (root->mParent && _bonemap.find(root->mParent->mName.C_Str()) != _bonemap.end()) {
673 root = root->mParent;
677 if (root->mName == bone.mName) {
678 create_anim_channel(ai_anim, bundle, skeleton, *root);
682 character->add_child(bundle_node);
694 format->add_array(tb_aformat);
698 format->set_animation(aspec);
702 string name (mesh.mName.data, mesh.mName.length);
705 vdata->set_transform_blend_table(tbtable);
707 vdata->unclean_set_num_rows(mesh.mNumVertices);
711 for (
size_t i = 0; i < mesh.mNumVertices; ++i) {
712 const aiVector3D &vec = mesh.mVertices[i];
713 vertex.add_data3(vec.x, vec.y, vec.z);
717 if (mesh.HasNormals()) {
719 for (
size_t i = 0; i < mesh.mNumVertices; ++i) {
720 const aiVector3D &vec = mesh.mNormals[i];
721 normal.add_data3(vec.x, vec.y, vec.z);
726 if (mesh.HasVertexColors(0)) {
728 for (
size_t i = 0; i < mesh.mNumVertices; ++i) {
729 const aiColor4D &col = mesh.mColors[0][i];
730 color.add_data4(col.r, col.g, col.b, col.a);
738 for (
size_t i = 0; i < mesh.mNumVertices; ++i) {
739 const aiVector3D &vec = mesh.mTextureCoords[0][i];
740 texcoord0.add_data3(vec.x, vec.y, vec.z);
742 for (
unsigned int u = 1; u < num_uvs; ++u) {
745 GeomVertexWriter texcoord (vdata, InternalName::get_texcoord_name(out.str()));
746 for (
size_t i = 0; i < mesh.mNumVertices; ++i) {
747 const aiVector3D &vec = mesh.mTextureCoords[u][i];
748 texcoord.add_data3(vec.x, vec.y, vec.z);
755 GeomVertexWriter transform_blend (vdata, InternalName::get_transform_blend());
757 for (
size_t i = 0; i < mesh.mNumVertices; ++i) {
760 for (
size_t j = 0; j < bone_weights[i].size(); ++j) {
761 tblend.
add_transform(bone_weights[i][j].joint_vertex_xform, bone_weights[i][j].weight);
763 transform_blend.add_data1i(tbtable->add_blend(tblend));
777 for (
size_t i = 0; i < mesh.mNumFaces; ++i) {
778 const aiFace &face = mesh.mFaces[i];
780 if (face.mNumIndices == 0) {
783 }
else if (face.mNumIndices == 1) {
784 points->add_vertex(face.mIndices[0]);
785 points->close_primitive();
786 }
else if (face.mNumIndices == 2) {
787 lines->add_vertices(face.mIndices[0], face.mIndices[1]);
788 lines->close_primitive();
789 }
else if (face.mNumIndices == 3) {
790 triangles->add_vertices(face.mIndices[0], face.mIndices[1], face.mIndices[2]);
791 triangles->close_primitive();
793 nassertd(
false) continue;
799 if (points->get_num_primitives() > 0) {
802 if (lines->get_num_primitives() > 0) {
803 geom->add_primitive(lines);
805 if (triangles->get_num_primitives() > 0) {
806 geom->add_primitive(triangles);
809 _geoms[index] = geom;
810 _geom_matindices[index] = mesh.mMaterialIndex;
813 _charmap[mesh.mName.C_Str()] = character;
821 load_node(
const aiNode &node,
PandaNode *parent) {
826 if (_bonemap.find(node.mName.C_Str()) != _bonemap.end()) {
831 string name (node.mName.data, node.mName.length);
832 if (node.mNumMeshes > 0) {
838 if (_charmap.find(node.mName.C_Str()) != _charmap.end()) {
839 character = _charmap[node.mName.C_Str()];
840 parent->add_child(character);
842 parent->add_child(pnode);
846 const aiMatrix4x4 &t = node.mTransformation;
847 if (!t.IsIdentity()) {
848 LMatrix4 mat(t.a1, t.b1, t.c1, t.d1,
849 t.a2, t.b2, t.c2, t.d2,
850 t.a3, t.b3, t.c3, t.d3,
851 t.a4, t.b4, t.c4, t.d4);
852 pnode->set_transform(TransformState::make_mat(mat));
855 for (
size_t i = 0; i < node.mNumChildren; ++i) {
856 load_node(*node.mChildren[i], pnode);
859 if (node.mNumMeshes > 0) {
865 if (node.mNumMeshes == 1) {
866 meshIndex = node.mMeshes[0];
867 gnode->add_geom(_geoms[meshIndex]);
868 gnode->set_state(_mat_states[_geom_matindices[meshIndex]]);
870 for (
size_t i = 0; i < node.mNumMeshes; ++i) {
871 meshIndex = node.mMeshes[i];
872 gnode->add_geom(_geoms[node.mMeshes[i]],
873 _mat_states[_geom_matindices[meshIndex]]);
878 assimp_cat.debug() <<
"Adding char to geom\n";
879 character->add_child(gnode);
888 load_light(
const aiLight &light) {
889 string name (light.mName.data, light.mName.length);
890 assimp_cat.debug() <<
"Found light '" << name <<
"'\n";
895 switch (light.mType) {
896 case aiLightSource_DIRECTIONAL: {
898 _root->add_child(dlight);
900 col = light.mColorDiffuse;
901 dlight->set_color(LColor(col.r, col.g, col.b, 1));
903 col = light.mColorSpecular;
904 dlight->set_specular_color(LColor(col.r, col.g, col.b, 1));
906 vec = light.mPosition;
907 dlight->set_point(LPoint3(vec.x, vec.y, vec.z));
909 vec = light.mDirection;
910 dlight->set_direction(LVector3(vec.x, vec.y, vec.z));
913 case aiLightSource_POINT: {
915 _root->add_child(plight);
917 col = light.mColorDiffuse;
918 plight->set_color(LColor(col.r, col.g, col.b, 1));
920 col = light.mColorSpecular;
921 plight->set_specular_color(LColor(col.r, col.g, col.b, 1));
923 vec = light.mPosition;
924 plight->set_point(LPoint3(vec.x, vec.y, vec.z));
926 plight->set_attenuation(LVecBase3(light.mAttenuationConstant,
927 light.mAttenuationLinear,
928 light.mAttenuationQuadratic));
931 case aiLightSource_SPOT: {
933 _root->add_child(plight);
935 col = light.mColorDiffuse;
936 plight->set_color(LColor(col.r, col.g, col.b, 1));
938 col = light.mColorSpecular;
939 plight->set_specular_color(LColor(col.r, col.g, col.b, 1));
941 plight->set_attenuation(LVecBase3(light.mAttenuationConstant,
942 light.mAttenuationLinear,
943 light.mAttenuationQuadratic));
945 plight->get_lens()->set_fov(light.mAngleOuterCone);
949 vec = light.mDirection;
950 LPoint3 pos (light.mPosition.x, light.mPosition.y, light.mPosition.z);
952 ::look_at(quat, LPoint3(vec.x, vec.y, vec.z), LVector3::up());
953 plight->set_transform(TransformState::make_pos_quat_scale(pos, quat, LVecBase3(1, 1, 1)));
963 assimp_cat.warning() <<
"Light '" << name <<
"' has an unknown type!\n";
968 col = light.mColorAmbient;
969 LVecBase4 ambient (col.r, col.g, col.b, 0);
970 if (ambient != LVecBase4::zero()) {
972 alight->set_color(ambient);
973 _root->add_child(alight);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A node of this type is created automatically at the root of each model file that is loaded.
bool read(const Filename &filename)
Reads from the indicated file.
A light shining from infinitely far away in a particular direction, like sunlight.
std::string get_dirname() const
Returns the directory part of the filename.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A basic node of the scene graph or data graph.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CharacterJoint * find_joint(const std::string &name) const
Returns a pointer to the joint with the given name, if there is such a joint, or NULL if there is no ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
The collection of all the joints and sliders in the character.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Defines a series of disconnected points.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An animated character, with skeleton-morph animation and either soft- skinned or hard-skinned vertice...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
This is the root of an AnimChannel hierarchy.
A hierarchy of directories and files that appears to be one continuous file system,...
void build_graph()
Converts scene graph structures into a Panda3D scene graph, with _root being the root node.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the base class of a family of classes that represent particular image file types that PNMImag...
bool read(const Filename &filename, PNMFileType *type=nullptr, bool report_unknown_type=true)
Reads the indicated image filename.
void get_extensions(std::string &ext) const
Returns a space-separated list of extensions that Assimp can load, without the leading dots.
bool make_canonical()
Converts this filename to a canonical name by replacing the directory part with the fully-qualified d...
void add_primitive(const GeomPrimitive *primitive)
Inserts a new GeomPrimitive structure to the Geom object.
A light source that seems to illuminate all points in space at once.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
set_diffuse
Specifies the diffuse color setting of the material.
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
This is our own Panda specialization on the default STL vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_panda()
Specifies that vertex animation is to be performed by Panda.
This is the base class for AnimChannel and AnimBundle.
The name of a file, such as a texture file or an Egg file.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
A light originating from a single point in space, and shining in a particular direction,...
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Defines the way an object appears in the presence of lighting.
PNMFileType * get_type_from_extension(const std::string &filename) const
Tries to determine what the PNMFileType is likely to be for a particular image file based on its exte...
static SparseArray lower_on(int on_bits)
Returns a SparseArray whose lower on_bits bits are on.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
std::string get_basename() const
Returns the basename part of the filename.
Defines a series of disconnected line segments.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class maintains the set of all known PNMFileTypes in the universe.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_regular_file(const Filename &filename) const
Convenience function; returns true if the named file exists and is a regular file.
This represents one joint of the character's animation, containing an animating transform matrix.
set_texcoord_name
Indicate which set of UV's this texture stage will use.
Defines a series of disconnected triangles.
An animation channel that issues a matrix each frame, read from a table such as might have been read ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a node that contains a pointer to an AnimBundle.
Defines the properties of a named stage of the multitexture pipeline.
static void set_default()
Makes sure there's a global PandaLogger object and makes sure that it is Assimp's default logger.
Custom implementation of Assimp::IOSystem.
A light originating from a single point in space, and shining in all directions.
A node that holds Geom objects, renderable pieces of geometry.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
bool write(const Filename &fullpath)
Writes the texture to the named filename.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the base class for PartRoot and MovingPart.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.