Merge branch 'release/1.10.x'

This commit is contained in:
rdb 2022-11-03 13:31:05 +01:00
commit e75aae62f0
8 changed files with 320 additions and 39 deletions

View File

@ -15,6 +15,7 @@
#include "internalName.h" #include "internalName.h"
#include "bamReader.h" #include "bamReader.h"
#include "bamWriter.h" #include "bamWriter.h"
#include "indent.h"
using std::ostream; using std::ostream;
@ -221,15 +222,28 @@ compare_to(const TextureStage &other) const {
*/ */
void TextureStage:: void TextureStage::
write(ostream &out) const { write(ostream &out) const {
out << "TextureStage " << get_name() << ", sort = " << get_sort() << ", priority = " << get_priority() << "\n" write(out, 0);
<< " texcoords = " << get_texcoord_name()->get_name() }
<< ", mode = " << get_mode() << ", color = " << get_color()
<< ", scale = " << get_rgb_scale() << ", " << get_alpha_scale() /**
<< ", saved_result = " << get_saved_result() * Writes the details of this stage
<< ", tex_view_offset = " << get_tex_view_offset() << "\n"; */
void TextureStage::
write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< "TextureStage " << get_name() << ", sort = " << get_sort()
<< ", priority = " << get_priority() << "\n";
indent(out, indent_level)
<< " texcoords = " << get_texcoord_name()->get_name()
<< ", mode = " << get_mode() << ", color = " << get_color()
<< ", scale = " << get_rgb_scale() << ", " << get_alpha_scale()
<< ", saved_result = " << get_saved_result()
<< ", tex_view_offset = " << get_tex_view_offset() << "\n";
if (get_mode() == M_combine) { if (get_mode() == M_combine) {
out << " RGB combine mode = " << get_combine_rgb_mode() << "\n"; indent(out, indent_level)
<< " RGB combine mode = " << get_combine_rgb_mode() << "\n";
if (get_num_combine_rgb_operands() >= 1) { if (get_num_combine_rgb_operands() >= 1) {
out << " 0: " << get_combine_rgb_source0() << ", " out << " 0: " << get_combine_rgb_source0() << ", "
<< get_combine_rgb_operand0() << "\n"; << get_combine_rgb_operand0() << "\n";
@ -242,7 +256,8 @@ write(ostream &out) const {
out << " 2: " << get_combine_rgb_source2() << ", " out << " 2: " << get_combine_rgb_source2() << ", "
<< get_combine_rgb_operand2() << "\n"; << get_combine_rgb_operand2() << "\n";
} }
out << " alpha combine mode = " << get_combine_alpha_mode() << "\n"; indent(out, indent_level)
<< " alpha combine mode = " << get_combine_alpha_mode() << "\n";
if (get_num_combine_alpha_operands() >= 1) { if (get_num_combine_alpha_operands() >= 1) {
out << " 0: " << get_combine_alpha_source0() << ", " out << " 0: " << get_combine_alpha_source0() << ", "
<< get_combine_alpha_operand0() << "\n"; << get_combine_alpha_operand0() << "\n";

View File

@ -182,6 +182,7 @@ PUBLISHED:
int compare_to(const TextureStage &other) const; int compare_to(const TextureStage &other) const;
void write(std::ostream &out) const; void write(std::ostream &out) const;
void write(std::ostream &out, int indent_level) const;
void output(std::ostream &out) const; void output(std::ostream &out) const;
INLINE static TextureStage *get_default(); INLINE static TextureStage *get_default();

View File

@ -21,9 +21,11 @@
#include "geomTriangles.h" #include "geomTriangles.h"
#include "pnmFileTypeRegistry.h" #include "pnmFileTypeRegistry.h"
#include "pnmImage.h" #include "pnmImage.h"
#include "alphaTestAttrib.h"
#include "materialAttrib.h" #include "materialAttrib.h"
#include "textureAttrib.h" #include "textureAttrib.h"
#include "cullFaceAttrib.h" #include "cullFaceAttrib.h"
#include "transparencyAttrib.h"
#include "ambientLight.h" #include "ambientLight.h"
#include "directionalLight.h" #include "directionalLight.h"
#include "spotlight.h" #include "spotlight.h"
@ -35,12 +37,48 @@
#include "animBundleNode.h" #include "animBundleNode.h"
#include "animChannelMatrixXfmTable.h" #include "animChannelMatrixXfmTable.h"
#include "pvector.h" #include "pvector.h"
#include "cmath.h"
#include "deg_2_rad.h"
#include "string_utils.h"
#include "pandaIOSystem.h" #include "pandaIOSystem.h"
#include "pandaLogger.h" #include "pandaLogger.h"
#include <assimp/postprocess.h> #include <assimp/postprocess.h>
#ifndef AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0
#endif
#ifndef AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0
#endif
#ifndef AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0
#endif
#ifndef AI_MATKEY_GLTF_ALPHAMODE
#define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0
#endif
#ifndef AI_MATKEY_GLTF_ALPHACUTOFF
#define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0
#endif
// Older versions of Assimp used these glTF-specific keys instead.
#ifndef AI_MATKEY_BASE_COLOR
#define AI_MATKEY_BASE_COLOR AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR
#endif
#ifndef AI_MATKEY_METALLIC_FACTOR
#define AI_MATKEY_METALLIC_FACTOR AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR
#endif
#ifndef AI_MATKEY_ROUGHNESS_FACTOR
#define AI_MATKEY_ROUGHNESS_FACTOR AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR
#endif
using std::ostringstream; using std::ostringstream;
using std::stringstream; using std::stringstream;
using std::string; using std::string;
@ -265,7 +303,8 @@ load_texture(size_t index) {
} else { } else {
if (assimp_cat.is_debug()) { if (assimp_cat.is_debug()) {
assimp_cat.debug() assimp_cat.debug()
<< "Reading embedded raw texture with size " << tex.mWidth << "x" << tex.mHeight << "\n"; << "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); ptex->setup_2d_texture(tex.mWidth, tex.mHeight, Texture::T_unsigned_byte, Texture::F_rgba);
@ -292,16 +331,18 @@ load_texture(size_t index) {
* Converts an aiMaterial into a RenderState. * Converts an aiMaterial into a RenderState.
*/ */
void AssimpLoader:: void AssimpLoader::
load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, CPT(TextureAttrib) &tattr) { load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype,
TextureStage::Mode mode, CPT(TextureAttrib) &tattr,
CPT(TexMatrixAttrib) &tmattr) {
aiString path; aiString path;
aiTextureMapping mapping; aiTextureMapping mapping;
unsigned int uvindex; unsigned int uvindex;
float blend; float blend;
aiTextureOp op; aiTextureOp op;
aiTextureMapMode mapmode; aiTextureMapMode mapmode[3];
for (size_t i = 0; i < mat.GetTextureCount(ttype); ++i) { for (size_t i = 0; i < mat.GetTextureCount(ttype); ++i) {
mat.GetTexture(ttype, i, &path, &mapping, nullptr, &blend, &op, &mapmode); mat.GetTexture(ttype, i, &path, &mapping, nullptr, &blend, &op, mapmode);
if (AI_SUCCESS != mat.Get(AI_MATKEY_UVWSRC(ttype, i), uvindex)) { if (AI_SUCCESS != mat.Get(AI_MATKEY_UVWSRC(ttype, i), uvindex)) {
// If there's no texture coordinate set for this texture, assume that // If there's no texture coordinate set for this texture, assume that
@ -310,13 +351,23 @@ load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, CPT(Textur
uvindex = i; uvindex = i;
} }
stringstream str; if (ttype == aiTextureType_DIFFUSE && i == 1) {
str << uvindex; // The glTF 2 importer duplicates this slot in older versions of Assimp.
PT(TextureStage) stage = new TextureStage(str.str()); // Since glTF doesn't support multiple diffuse textures anyway, we check
if (uvindex > 0) { // for this old glTF-specific key, and if present, ignore this texture.
stage->set_texcoord_name(InternalName::get_texcoord_name(str.str())); aiColor4D col;
if (AI_SUCCESS == mat.Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR, col)) {
return;
}
} }
PT(Texture) ptex = nullptr;
std::string uvindex_str = format_string(uvindex);
PT(TextureStage) stage = new TextureStage(uvindex_str);
stage->set_mode(mode);
if (uvindex > 0) {
stage->set_texcoord_name(InternalName::get_texcoord_name(uvindex_str));
}
PT(Texture) ptex;
// I'm not sure if this is the right way to handle it, as I couldn't find // I'm not sure if this is the right way to handle it, as I couldn't find
// much information on embedded textures. // much information on embedded textures.
@ -355,7 +406,84 @@ load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, CPT(Textur
} }
if (ptex != nullptr) { if (ptex != nullptr) {
// Apply the mapping modes.
switch (mapmode[0]) {
case aiTextureMapMode_Wrap:
ptex->set_wrap_u(SamplerState::WM_repeat);
break;
case aiTextureMapMode_Clamp:
ptex->set_wrap_u(SamplerState::WM_clamp);
break;
case aiTextureMapMode_Decal:
ptex->set_wrap_u(SamplerState::WM_border_color);
ptex->set_border_color(LColor(0, 0, 0, 0));
break;
case aiTextureMapMode_Mirror:
ptex->set_wrap_u(SamplerState::WM_mirror);
break;
default:
break;
}
switch (mapmode[1]) {
case aiTextureMapMode_Wrap:
ptex->set_wrap_v(SamplerState::WM_repeat);
break;
case aiTextureMapMode_Clamp:
ptex->set_wrap_v(SamplerState::WM_clamp);
break;
case aiTextureMapMode_Decal:
ptex->set_wrap_v(SamplerState::WM_border_color);
ptex->set_border_color(LColor(0, 0, 0, 0));
break;
case aiTextureMapMode_Mirror:
ptex->set_wrap_v(SamplerState::WM_mirror);
break;
default:
break;
}
switch (mapmode[2]) {
case aiTextureMapMode_Wrap:
ptex->set_wrap_w(SamplerState::WM_repeat);
break;
case aiTextureMapMode_Clamp:
ptex->set_wrap_w(SamplerState::WM_clamp);
break;
case aiTextureMapMode_Decal:
ptex->set_wrap_w(SamplerState::WM_border_color);
ptex->set_border_color(LColor(0, 0, 0, 0));
break;
case aiTextureMapMode_Mirror:
ptex->set_wrap_w(SamplerState::WM_mirror);
break;
default:
break;
}
tattr = DCAST(TextureAttrib, tattr->add_on_stage(stage, ptex)); tattr = DCAST(TextureAttrib, tattr->add_on_stage(stage, ptex));
// Is there a texture transform?
aiUVTransform transform;
if (AI_SUCCESS == mat.Get(AI_MATKEY_UVTRANSFORM(ttype, i), transform)) {
// Reconstruct the original origin from the glTF file.
PN_stdfloat rcos, rsin;
csincos(-transform.mRotation, &rsin, &rcos);
transform.mTranslation.x -= (0.5 * transform.mScaling.x) * (-rcos + rsin + 1);
transform.mTranslation.y -= ((0.5 * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y;
LMatrix3 matrix =
LMatrix3::translate_mat(0, -1) *
LMatrix3::scale_mat(transform.mScaling.x, transform.mScaling.y) *
LMatrix3::rotate_mat(rad_2_deg(-transform.mRotation)) *
LMatrix3::translate_mat(transform.mTranslation.x, 1 + transform.mTranslation.y);
CPT(TransformState) cstate =
TransformState::make_mat3(matrix);
CPT(RenderAttrib) new_attr = (tmattr == nullptr)
? TexMatrixAttrib::make(stage, std::move(cstate))
: tmattr->add_stage(stage, std::move(cstate));
tmattr = DCAST(TexMatrixAttrib, std::move(new_attr));
}
} }
} }
} }
@ -369,7 +497,7 @@ load_material(size_t index) {
CPT(RenderState) state = RenderState::make_empty(); CPT(RenderState) state = RenderState::make_empty();
aiColor3D col; aiColor4D col;
bool have; bool have;
int ival; int ival;
PN_stdfloat fval; PN_stdfloat fval;
@ -379,7 +507,11 @@ load_material(size_t index) {
// First do the material attribute. // First do the material attribute.
PT(Material) pmat = new Material; PT(Material) pmat = new Material;
have = false; have = false;
if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_DIFFUSE, col)) { if (AI_SUCCESS == mat.Get(AI_MATKEY_BASE_COLOR, col)) {
pmat->set_base_color(LColor(col.r, col.g, col.b, col.a));
have = true;
}
else if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_DIFFUSE, col)) {
pmat->set_diffuse(LColor(col.r, col.g, col.b, 1)); pmat->set_diffuse(LColor(col.r, col.g, col.b, 1));
have = true; have = true;
} }
@ -391,6 +523,13 @@ load_material(size_t index) {
} }
have = true; have = true;
} }
//else {
// if (AI_SUCCESS == mat.Get(AI_MATKEY_SHININESS_STRENGTH, fval)) {
// pmat->set_specular(LColor(fval, fval, fval, 1));
// } else {
// pmat->set_specular(LColor(1, 1, 1, 1));
// }
//}
if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_AMBIENT, col)) { if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_AMBIENT, col)) {
pmat->set_specular(LColor(col.r, col.g, col.b, 1)); pmat->set_specular(LColor(col.r, col.g, col.b, 1));
have = true; have = true;
@ -406,6 +545,22 @@ load_material(size_t index) {
pmat->set_shininess(fval); pmat->set_shininess(fval);
have = true; have = true;
} }
if (AI_SUCCESS == mat.Get(AI_MATKEY_METALLIC_FACTOR, fval)) {
pmat->set_metallic(fval);
have = true;
}
if (AI_SUCCESS == mat.Get(AI_MATKEY_ROUGHNESS_FACTOR, fval)) {
pmat->set_roughness(fval);
have = true;
}
if (AI_SUCCESS == mat.Get(AI_MATKEY_REFRACTI, fval)) {
pmat->set_refractive_index(fval);
have = true;
}
else if (pmat->has_metallic()) {
// Default refractive index to 1.5 for PBR models
pmat->set_refractive_index(1.5);
}
if (have) { if (have) {
state = state->add_attrib(MaterialAttrib::make(pmat)); state = state->add_attrib(MaterialAttrib::make(pmat));
} }
@ -429,15 +584,44 @@ load_material(size_t index) {
} }
} }
// Alpha mode.
aiString alpha_mode;
if (AI_SUCCESS == mat.Get(AI_MATKEY_GLTF_ALPHAMODE, alpha_mode)) {
if (strcmp(alpha_mode.C_Str(), "MASK") == 0) {
PN_stdfloat cutoff = 0.5;
mat.Get(AI_MATKEY_GLTF_ALPHACUTOFF, cutoff);
state = state->add_attrib(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, cutoff));
}
else if (strcmp(alpha_mode.C_Str(), "BLEND") == 0) {
state = state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
}
}
// And let's not forget the textures! // And let's not forget the textures!
CPT(TextureAttrib) tattr = DCAST(TextureAttrib, TextureAttrib::make()); CPT(TextureAttrib) tattr = DCAST(TextureAttrib, TextureAttrib::make());
load_texture_stage(mat, aiTextureType_DIFFUSE, tattr); CPT(TexMatrixAttrib) tmattr;
load_texture_stage(mat, aiTextureType_LIGHTMAP, tattr); load_texture_stage(mat, aiTextureType_DIFFUSE, TextureStage::M_modulate, tattr, tmattr);
// Check for an ORM map, from the glTF/OBJ importer. glTF also puts it in the
// LIGHTMAP slot, despite only having the lightmap in the red channel, so we
// have to ignore it.
if (mat.GetTextureCount(aiTextureType_UNKNOWN) > 0) {
load_texture_stage(mat, aiTextureType_UNKNOWN, TextureStage::M_selector, tattr, tmattr);
} else {
load_texture_stage(mat, aiTextureType_LIGHTMAP, TextureStage::M_modulate, tattr, tmattr);
}
load_texture_stage(mat, aiTextureType_NORMALS, TextureStage::M_normal, tattr, tmattr);
load_texture_stage(mat, aiTextureType_EMISSIVE, TextureStage::M_emission, tattr, tmattr);
load_texture_stage(mat, aiTextureType_HEIGHT, TextureStage::M_height, tattr, tmattr);
if (tattr->get_num_on_stages() > 0) { if (tattr->get_num_on_stages() > 0) {
state = state->add_attrib(tattr); state = state->add_attrib(tattr);
} }
if (tmattr != nullptr) {
state = state->add_attrib(tmattr);
}
_mat_states[index] = state; _mat_states[index] = std::move(state);
} }
/** /**
@ -634,6 +818,10 @@ load_mesh(size_t index) {
aformat->add_column(InternalName::get_texcoord_name(out.str()), 3, Geom::NT_stdfloat, Geom::C_texcoord); aformat->add_column(InternalName::get_texcoord_name(out.str()), 3, Geom::NT_stdfloat, Geom::C_texcoord);
} }
} }
if (mesh.HasTangentsAndBitangents()) {
aformat->add_column(InternalName::get_tangent(), 3, Geom::NT_stdfloat, Geom::C_vector);
aformat->add_column(InternalName::get_binormal(), 3, Geom::NT_stdfloat, Geom::C_vector);
}
PT(GeomVertexArrayFormat) tb_aformat = new GeomVertexArrayFormat; PT(GeomVertexArrayFormat) tb_aformat = new GeomVertexArrayFormat;
tb_aformat->add_column(InternalName::make("transform_blend"), 1, Geom::NT_uint16, Geom::C_index); tb_aformat->add_column(InternalName::make("transform_blend"), 1, Geom::NT_uint16, Geom::C_index);
@ -737,7 +925,7 @@ load_mesh(size_t index) {
GeomVertexWriter vertex (vdata, InternalName::get_vertex()); GeomVertexWriter vertex (vdata, InternalName::get_vertex());
for (size_t i = 0; i < mesh.mNumVertices; ++i) { for (size_t i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D &vec = mesh.mVertices[i]; const aiVector3D &vec = mesh.mVertices[i];
vertex.add_data3(vec.x, vec.y, vec.z); vertex.set_data3(vec.x, vec.y, vec.z);
} }
// Now the normals, if any. // Now the normals, if any.
@ -745,7 +933,7 @@ load_mesh(size_t index) {
GeomVertexWriter normal (vdata, InternalName::get_normal()); GeomVertexWriter normal (vdata, InternalName::get_normal());
for (size_t i = 0; i < mesh.mNumVertices; ++i) { for (size_t i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D &vec = mesh.mNormals[i]; const aiVector3D &vec = mesh.mNormals[i];
normal.add_data3(vec.x, vec.y, vec.z); normal.set_data3(vec.x, vec.y, vec.z);
} }
} }
@ -754,7 +942,7 @@ load_mesh(size_t index) {
GeomVertexWriter color (vdata, InternalName::get_color()); GeomVertexWriter color (vdata, InternalName::get_color());
for (size_t i = 0; i < mesh.mNumVertices; ++i) { for (size_t i = 0; i < mesh.mNumVertices; ++i) {
const aiColor4D &col = mesh.mColors[0][i]; const aiColor4D &col = mesh.mColors[0][i];
color.add_data4(col.r, col.g, col.b, col.a); color.set_data4(col.r, col.g, col.b, col.a);
} }
} }
@ -764,7 +952,7 @@ load_mesh(size_t index) {
GeomVertexWriter texcoord0 (vdata, InternalName::get_texcoord()); GeomVertexWriter texcoord0 (vdata, InternalName::get_texcoord());
for (size_t i = 0; i < mesh.mNumVertices; ++i) { for (size_t i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D &vec = mesh.mTextureCoords[0][i]; const aiVector3D &vec = mesh.mTextureCoords[0][i];
texcoord0.add_data3(vec.x, vec.y, vec.z); texcoord0.set_data3(vec.x, vec.y, vec.z);
} }
for (unsigned int u = 1; u < num_uvs; ++u) { for (unsigned int u = 1; u < num_uvs; ++u) {
ostringstream out; ostringstream out;
@ -772,11 +960,23 @@ load_mesh(size_t index) {
GeomVertexWriter texcoord (vdata, InternalName::get_texcoord_name(out.str())); GeomVertexWriter texcoord (vdata, InternalName::get_texcoord_name(out.str()));
for (size_t i = 0; i < mesh.mNumVertices; ++i) { for (size_t i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D &vec = mesh.mTextureCoords[u][i]; const aiVector3D &vec = mesh.mTextureCoords[u][i];
texcoord.add_data3(vec.x, vec.y, vec.z); texcoord.set_data3(vec.x, vec.y, vec.z);
} }
} }
} }
// Now the tangents and bitangents, if any.
if (mesh.HasTangentsAndBitangents()) {
GeomVertexWriter tangent (vdata, InternalName::get_tangent());
GeomVertexWriter binormal (vdata, InternalName::get_binormal());
for (size_t i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D &tvec = mesh.mTangents[i];
const aiVector3D &bvec = mesh.mBitangents[i];
tangent.set_data3(tvec.x, tvec.y, tvec.z);
binormal.set_data3(bvec.x, bvec.y, bvec.z);
}
}
// Now the transform blend table // Now the transform blend table
if (character) { if (character) {
GeomVertexWriter transform_blend (vdata, InternalName::get_transform_blend()); GeomVertexWriter transform_blend (vdata, InternalName::get_transform_blend());
@ -787,7 +987,7 @@ load_mesh(size_t index) {
for (size_t j = 0; j < bone_weights[i].size(); ++j) { for (size_t j = 0; j < bone_weights[i].size(); ++j) {
tblend.add_transform(bone_weights[i][j].joint_vertex_xform, bone_weights[i][j].weight); tblend.add_transform(bone_weights[i][j].joint_vertex_xform, bone_weights[i][j].weight);
} }
transform_blend.add_data1i(tbtable->add_blend(tblend)); transform_blend.set_data1i(tbtable->add_blend(tblend));
} }
tbtable->set_rows(SparseArray::lower_on(vdata->get_num_rows())); tbtable->set_rows(SparseArray::lower_on(vdata->get_num_rows()));
@ -868,10 +1068,16 @@ load_node(const aiNode &node, PandaNode *parent, bool under_joint) {
bool prune = false; bool prune = false;
if (node.mNumMeshes == 0) { if (node.mNumMeshes == 0) {
pnode = new PandaNode(name); if (parent == _root && assimp_collapse_dummy_root_node && !under_joint &&
(name.empty() || name[0] == '$' || name == "RootNode" || name == "ROOT" || name == "Root" || (name.size() > 2 && name[0] == '<' && name[name.size() - 1] == '>') || name == _root->get_name())) {
// Collapse root node.
pnode = _root;
} else {
pnode = new PandaNode(name);
// Possibly prune this if this is a joint or under a joint. // Possibly prune this if this is a joint or under a joint.
prune = under_joint; prune = under_joint;
}
} }
else if (node.mNumMeshes == 1) { else if (node.mNumMeshes == 1) {
size_t meshIndex = node.mMeshes[0]; size_t meshIndex = node.mMeshes[0];
@ -933,7 +1139,47 @@ load_node(const aiNode &node, PandaNode *parent, bool under_joint) {
} }
} }
parent->add_child(pnode); if (parent != pnode) {
parent->add_child(pnode);
}
if (node.mMetaData != nullptr) {
for (unsigned i = 0; i < node.mMetaData->mNumProperties; ++i) {
const aiMetadataEntry &entry = node.mMetaData->mValues[i];
std::string value;
switch (entry.mType) {
//case AI_BOOL:
// value = (*static_cast<bool *>(entry.mData)) ? "1" : "";
// break;
case (aiMetadataType)1: // AI_INT32
value = format_string(*static_cast<int32_t *>(entry.mData));
break;
case AI_UINT64:
value = format_string(*static_cast<uint64_t *>(entry.mData));
break;
case AI_FLOAT:
value = format_string(*static_cast<float *>(entry.mData));
break;
case AI_AISTRING:
{
const aiString *str = static_cast<const aiString *>(entry.mData);
value = std::string(str->data, str->length);
}
break;
default:
// Special case because AI_DOUBLE was added in Assimp 4.0 with the same
// value as AI_AISTRING. Defined as if so that we don't get a duplicate
// case error with moder ncompilers.
if (entry.mType == (aiMetadataType)4) {
value = format_string(*static_cast<double *>(entry.mData));
break;
}
continue;
}
const aiString &key = node.mMetaData->mKeys[i];
pnode->set_tag(std::string(key.data, key.length), std::move(value));
}
}
// Load in the transformation matrix. // Load in the transformation matrix.
const aiMatrix4x4 &t = node.mTransformation; const aiMatrix4x4 &t = node.mTransformation;

View File

@ -18,6 +18,7 @@
#include "filename.h" #include "filename.h"
#include "modelRoot.h" #include "modelRoot.h"
#include "texture.h" #include "texture.h"
#include "textureStage.h"
#include "pmap.h" #include "pmap.h"
#include <assimp/scene.h> #include <assimp/scene.h>
@ -71,7 +72,9 @@ private:
const aiNode *find_node(const aiNode &root, const aiString &name); const aiNode *find_node(const aiNode &root, const aiString &name);
void load_texture(size_t index); void load_texture(size_t index);
void load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, CPT(TextureAttrib) &tattr); void load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype,
TextureStage::Mode mode, CPT(TextureAttrib) &tattr,
CPT(TexMatrixAttrib) &tmattr);
void load_material(size_t index); void load_material(size_t index);
void create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *parent, const aiNode &node); void create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *parent, const aiNode &node);
void create_anim_channel(const aiAnimation &anim, AnimBundle *bundle, AnimGroup *parent, const aiNode &node); void create_anim_channel(const aiAnimation &anim, AnimBundle *bundle, AnimGroup *parent, const aiNode &node);

View File

@ -52,7 +52,7 @@ ConfigVariableBool assimp_fix_infacing_normals
ConfigVariableBool assimp_optimize_meshes ConfigVariableBool assimp_optimize_meshes
("assimp-optimize-meshes", true, ("assimp-optimize-meshes", true,
PRC_DESC("Removes the number of draw calls by unifying geometry with the same " PRC_DESC("Reduces the number of draw calls by unifying geometry with the same "
"materials. Especially effective in conjunction with " "materials. Especially effective in conjunction with "
"assimp-optimize-graph and assimp-remove-redundant-materials.")); "assimp-optimize-graph and assimp-remove-redundant-materials."));
@ -86,6 +86,13 @@ ConfigVariableDouble assimp_smooth_normal_angle
"normals. Note that you may need to clear the model-cache after " "normals. Note that you may need to clear the model-cache after "
"changing this.")); "changing this."));
ConfigVariableBool assimp_collapse_dummy_root_node
("assimp-collapse-dummy-root-node", false,
PRC_DESC("If set to true, collapses the root node that Assimp creates, if it "
"appears to be a synthetic dummy root node and contains no meshes. "
"This variable is new as of Panda3D 1.10.13 and will become true by "
"default as of Panda3D 1.11.0."));
/** /**
* Initializes the library. This must be called at least once before any of * 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 * the functions or classes in this library can be used. Normally it will be

View File

@ -33,6 +33,7 @@ extern ConfigVariableBool assimp_optimize_graph;
extern ConfigVariableBool assimp_flip_winding_order; extern ConfigVariableBool assimp_flip_winding_order;
extern ConfigVariableBool assimp_gen_normals; extern ConfigVariableBool assimp_gen_normals;
extern ConfigVariableDouble assimp_smooth_normal_angle; extern ConfigVariableDouble assimp_smooth_normal_angle;
extern ConfigVariableBool assimp_collapse_dummy_root_node;
extern EXPCL_ASSIMP void init_libassimp(); extern EXPCL_ASSIMP void init_libassimp();

View File

@ -27,10 +27,11 @@ PandaIOStream(std::istream &stream) : _istream(stream) {
*/ */
size_t PandaIOStream:: size_t PandaIOStream::
FileSize() const { FileSize() const {
_istream.clear();
std::streampos cur = _istream.tellg(); std::streampos cur = _istream.tellg();
_istream.seekg(0, ios::end); _istream.seekg(0, ios::end);
std::streampos end = _istream.tellg(); std::streampos end = _istream.tellg();
_istream.seekg(cur, ios::beg); _istream.seekg(cur);
return end; return end;
} }
@ -47,8 +48,14 @@ Flush() {
*/ */
size_t PandaIOStream:: size_t PandaIOStream::
Read(void *buffer, size_t size, size_t count) { Read(void *buffer, size_t size, size_t count) {
_istream.read((char*) buffer, size * count); _istream.read((char *)buffer, size * count);
return _istream.gcount();
if (_istream.eof()) {
// Gracefully handle EOF.
_istream.clear(ios::eofbit);
}
return _istream.gcount() / size;
} }
/** /**

View File

@ -80,10 +80,11 @@ init_libptloader() {
LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr(); LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr();
init_liblwo(); init_liblwo();
init_libflt();
FltToEggConverter *flt = new FltToEggConverter; FltToEggConverter *flt = new FltToEggConverter;
reg->register_type(new LoaderFileTypePandatool(flt)); reg->register_type(new LoaderFileTypePandatool(flt));
init_libflt();
LwoToEggConverter *lwo = new LwoToEggConverter; LwoToEggConverter *lwo = new LwoToEggConverter;
reg->register_type(new LoaderFileTypePandatool(lwo)); reg->register_type(new LoaderFileTypePandatool(lwo));