|
@@ -1,4 +1,4 @@
|
|
|
-// Filename: EggLoader.cxx
|
|
|
|
|
|
|
+// Filename: eggLoader.cxx
|
|
|
// Created by: drose (26Feb02)
|
|
// Created by: drose (26Feb02)
|
|
|
//
|
|
//
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
@@ -19,26 +19,25 @@
|
|
|
#include "pandabase.h"
|
|
#include "pandabase.h"
|
|
|
|
|
|
|
|
#include "eggLoader.h"
|
|
#include "eggLoader.h"
|
|
|
|
|
+#include "eggRenderState.h"
|
|
|
#include "egg_parametrics.h"
|
|
#include "egg_parametrics.h"
|
|
|
#include "config_egg2pg.h"
|
|
#include "config_egg2pg.h"
|
|
|
#include "nodePath.h"
|
|
#include "nodePath.h"
|
|
|
#include "renderState.h"
|
|
#include "renderState.h"
|
|
|
#include "transformState.h"
|
|
#include "transformState.h"
|
|
|
-#include "textureAttrib.h"
|
|
|
|
|
-#include "textureApplyAttrib.h"
|
|
|
|
|
#include "texturePool.h"
|
|
#include "texturePool.h"
|
|
|
#include "billboardEffect.h"
|
|
#include "billboardEffect.h"
|
|
|
-#include "cullFaceAttrib.h"
|
|
|
|
|
-#include "cullBinAttrib.h"
|
|
|
|
|
-#include "transparencyAttrib.h"
|
|
|
|
|
#include "decalEffect.h"
|
|
#include "decalEffect.h"
|
|
|
-#include "depthTestAttrib.h"
|
|
|
|
|
-#include "depthWriteAttrib.h"
|
|
|
|
|
-#include "materialAttrib.h"
|
|
|
|
|
-#include "texMatrixAttrib.h"
|
|
|
|
|
#include "colorAttrib.h"
|
|
#include "colorAttrib.h"
|
|
|
|
|
+#include "textureAttrib.h"
|
|
|
#include "materialPool.h"
|
|
#include "materialPool.h"
|
|
|
#include "geomNode.h"
|
|
#include "geomNode.h"
|
|
|
|
|
+#include "qpgeomVertexFormat.h"
|
|
|
|
|
+#include "qpgeomVertexArrayFormat.h"
|
|
|
|
|
+#include "qpgeomVertexData.h"
|
|
|
|
|
+#include "qpgeomVertexIterator.h"
|
|
|
|
|
+#include "qpgeom.h"
|
|
|
|
|
+#include "qpgeomTriangles.h"
|
|
|
#include "sequenceNode.h"
|
|
#include "sequenceNode.h"
|
|
|
#include "switchNode.h"
|
|
#include "switchNode.h"
|
|
|
#include "portalNode.h"
|
|
#include "portalNode.h"
|
|
@@ -150,13 +149,13 @@ void EggLoader::
|
|
|
build_graph() {
|
|
build_graph() {
|
|
|
_deferred_nodes.clear();
|
|
_deferred_nodes.clear();
|
|
|
|
|
|
|
|
- // First, bin up the LOD nodes.
|
|
|
|
|
- EggBinner binner;
|
|
|
|
|
- binner.make_bins(&_data);
|
|
|
|
|
-
|
|
|
|
|
- // Then load up all of the textures.
|
|
|
|
|
|
|
+ // First, load up all of the textures.
|
|
|
load_textures();
|
|
load_textures();
|
|
|
|
|
|
|
|
|
|
+ // Then bin up the polysets and LOD nodes.
|
|
|
|
|
+ EggBinner binner(*this);
|
|
|
|
|
+ binner.make_bins(&_data);
|
|
|
|
|
+
|
|
|
// Now build up the scene graph.
|
|
// Now build up the scene graph.
|
|
|
_root = new ModelRoot(_data.get_egg_filename().get_basename());
|
|
_root = new ModelRoot(_data.get_egg_filename().get_basename());
|
|
|
make_node(&_data, _root);
|
|
make_node(&_data, _root);
|
|
@@ -1276,61 +1275,6 @@ make_texture_stage(const EggTexture *egg_tex) {
|
|
|
return stage;
|
|
return stage;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: EggLoader::get_material_attrib
|
|
|
|
|
-// Access: Private
|
|
|
|
|
-// Description: Returns a RenderAttrib suitable for enabling the
|
|
|
|
|
-// material indicated by the given EggMaterial, and with
|
|
|
|
|
-// the indicated backface flag.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-CPT(RenderAttrib) EggLoader::
|
|
|
|
|
-get_material_attrib(const EggMaterial *egg_mat, bool bface) {
|
|
|
|
|
- Materials &materials = bface ? _materials_bface : _materials;
|
|
|
|
|
-
|
|
|
|
|
- // First, check whether we've seen this material before.
|
|
|
|
|
- Materials::const_iterator mi;
|
|
|
|
|
- mi = materials.find(egg_mat);
|
|
|
|
|
- if (mi != materials.end()) {
|
|
|
|
|
- return (*mi).second;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Ok, this is the first time we've seen this particular
|
|
|
|
|
- // EggMaterial. Create a new Material that matches it.
|
|
|
|
|
- PT(Material) mat = new Material;
|
|
|
|
|
- if (egg_mat->has_diff()) {
|
|
|
|
|
- mat->set_diffuse(egg_mat->get_diff());
|
|
|
|
|
- // By default, ambient is the same as diffuse, if diffuse is
|
|
|
|
|
- // specified but ambient is not.
|
|
|
|
|
- mat->set_ambient(egg_mat->get_diff());
|
|
|
|
|
- }
|
|
|
|
|
- if (egg_mat->has_amb()) {
|
|
|
|
|
- mat->set_ambient(egg_mat->get_amb());
|
|
|
|
|
- }
|
|
|
|
|
- if (egg_mat->has_emit()) {
|
|
|
|
|
- mat->set_emission(egg_mat->get_emit());
|
|
|
|
|
- }
|
|
|
|
|
- if (egg_mat->has_spec()) {
|
|
|
|
|
- mat->set_specular(egg_mat->get_spec());
|
|
|
|
|
- }
|
|
|
|
|
- if (egg_mat->has_shininess()) {
|
|
|
|
|
- mat->set_shininess(egg_mat->get_shininess());
|
|
|
|
|
- }
|
|
|
|
|
- if (egg_mat->has_local()) {
|
|
|
|
|
- mat->set_local(egg_mat->get_local());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- mat->set_twoside(bface);
|
|
|
|
|
-
|
|
|
|
|
- // Now get a global Material pointer, shared with other models.
|
|
|
|
|
- const Material *shared_mat = MaterialPool::get_material(mat);
|
|
|
|
|
-
|
|
|
|
|
- // And create a MaterialAttrib for this Material.
|
|
|
|
|
- CPT(RenderAttrib) mt = MaterialAttrib::make(shared_mat);
|
|
|
|
|
- materials.insert(Materials::value_type(egg_mat, mt));
|
|
|
|
|
-
|
|
|
|
|
- return mt;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: EggLoader::setup_bucket
|
|
// Function: EggLoader::setup_bucket
|
|
@@ -1363,315 +1307,12 @@ setup_bucket(BuilderBucket &bucket, EggLoader::BakeInUVs &bake_in_uvs,
|
|
|
bucket.set_name(egg_prim->get_name());
|
|
bucket.set_name(egg_prim->get_name());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Assign the appropriate properties to the bucket.
|
|
|
|
|
-
|
|
|
|
|
- // The various EggRenderMode properties can be defined directly at
|
|
|
|
|
- // the primitive, at a group above the primitive, or an a texture
|
|
|
|
|
- // applied to the primitive. The EggNode::determine_*() functions
|
|
|
|
|
- // can find the right pointer to the level at which this is actually
|
|
|
|
|
- // defined for a given primitive.
|
|
|
|
|
- EggRenderMode::AlphaMode am = EggRenderMode::AM_unspecified;
|
|
|
|
|
- EggRenderMode::DepthWriteMode dwm = EggRenderMode::DWM_unspecified;
|
|
|
|
|
- EggRenderMode::DepthTestMode dtm = EggRenderMode::DTM_unspecified;
|
|
|
|
|
- EggRenderMode::VisibilityMode vm = EggRenderMode::VM_unspecified;
|
|
|
|
|
- bool implicit_alpha = false;
|
|
|
|
|
- bool has_draw_order = false;
|
|
|
|
|
- int draw_order = 0;
|
|
|
|
|
- bool has_bin = false;
|
|
|
|
|
- string bin;
|
|
|
|
|
-
|
|
|
|
|
- EggRenderMode *render_mode;
|
|
|
|
|
- render_mode = egg_prim->determine_alpha_mode();
|
|
|
|
|
- if (render_mode != (EggRenderMode *)NULL) {
|
|
|
|
|
- am = render_mode->get_alpha_mode();
|
|
|
|
|
- }
|
|
|
|
|
- render_mode = egg_prim->determine_depth_write_mode();
|
|
|
|
|
- if (render_mode != (EggRenderMode *)NULL) {
|
|
|
|
|
- dwm = render_mode->get_depth_write_mode();
|
|
|
|
|
- }
|
|
|
|
|
- render_mode = egg_prim->determine_depth_test_mode();
|
|
|
|
|
- if (render_mode != (EggRenderMode *)NULL) {
|
|
|
|
|
- dtm = render_mode->get_depth_test_mode();
|
|
|
|
|
- }
|
|
|
|
|
- render_mode = egg_prim->determine_visibility_mode();
|
|
|
|
|
- if (render_mode != (EggRenderMode *)NULL) {
|
|
|
|
|
- vm = render_mode->get_visibility_mode();
|
|
|
|
|
- }
|
|
|
|
|
- render_mode = egg_prim->determine_draw_order();
|
|
|
|
|
- if (render_mode != (EggRenderMode *)NULL) {
|
|
|
|
|
- has_draw_order = true;
|
|
|
|
|
- draw_order = render_mode->get_draw_order();
|
|
|
|
|
- }
|
|
|
|
|
- render_mode = egg_prim->determine_bin();
|
|
|
|
|
- if (render_mode != (EggRenderMode *)NULL) {
|
|
|
|
|
- has_bin = true;
|
|
|
|
|
- bin = render_mode->get_bin();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- bucket.add_attrib(TextureAttrib::make_off());
|
|
|
|
|
- int num_textures = egg_prim->get_num_textures();
|
|
|
|
|
- CPT(RenderAttrib) texture_attrib = NULL;
|
|
|
|
|
- CPT(RenderAttrib) tex_gen_attrib = NULL;
|
|
|
|
|
- CPT(RenderAttrib) tex_mat_attrib = NULL;
|
|
|
|
|
- TexMats tex_mats;
|
|
|
|
|
-
|
|
|
|
|
- for (int i = 0; i < num_textures; i++) {
|
|
|
|
|
- PT_EggTexture egg_tex = egg_prim->get_texture(i);
|
|
|
|
|
-
|
|
|
|
|
- const TextureDef &def = _textures[egg_tex];
|
|
|
|
|
- if (def._texture != (const RenderAttrib *)NULL) {
|
|
|
|
|
- if (texture_attrib == (RenderAttrib *)NULL) {
|
|
|
|
|
- texture_attrib = def._texture;
|
|
|
|
|
- } else {
|
|
|
|
|
- texture_attrib = texture_attrib->compose(def._texture);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // If neither the primitive nor the texture specified an alpha
|
|
|
|
|
- // mode, assume it should be alpha'ed if the texture has an
|
|
|
|
|
- // alpha channel (unless the texture environment type is one
|
|
|
|
|
- // that doesn't apply its alpha to the result).
|
|
|
|
|
- if (am == EggRenderMode::AM_unspecified) {
|
|
|
|
|
- const TextureAttrib *tex_attrib = DCAST(TextureAttrib, def._texture);
|
|
|
|
|
- Texture *tex = tex_attrib->get_texture();
|
|
|
|
|
- nassertv(tex != (Texture *)NULL);
|
|
|
|
|
- int num_components = tex->get_num_components();
|
|
|
|
|
- if (egg_tex->has_alpha_channel(num_components)) {
|
|
|
|
|
- switch (egg_tex->get_env_type()) {
|
|
|
|
|
- case EggTexture::ET_decal:
|
|
|
|
|
- case EggTexture::ET_add:
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- implicit_alpha = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Check for a texgen attrib.
|
|
|
|
|
- bool has_tex_gen = false;
|
|
|
|
|
- if (egg_tex->get_tex_gen() != EggTexture::TG_unspecified) {
|
|
|
|
|
- has_tex_gen = true;
|
|
|
|
|
- if (tex_gen_attrib == (const RenderAttrib *)NULL) {
|
|
|
|
|
- tex_gen_attrib = TexGenAttrib::make();
|
|
|
|
|
- }
|
|
|
|
|
- tex_gen_attrib = DCAST(TexGenAttrib, tex_gen_attrib)->
|
|
|
|
|
- add_stage(def._stage, get_tex_gen(egg_tex));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Record the texture's associated texture matrix, so we can see
|
|
|
|
|
- // if we can safely bake it into the UV's. (We need to get the
|
|
|
|
|
- // complete list of textures that share this same set of UV's
|
|
|
|
|
- // per each unique texture matrix. Whew!)
|
|
|
|
|
- CPT(InternalName) uv_name;
|
|
|
|
|
- if (egg_tex->has_uv_name() && egg_tex->get_uv_name() != string("default")) {
|
|
|
|
|
- uv_name = InternalName::get_texcoord_name(egg_tex->get_uv_name());
|
|
|
|
|
- } else {
|
|
|
|
|
- uv_name = InternalName::get_texcoord();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (has_tex_gen) {
|
|
|
|
|
- // If the texture has a texgen mode, we will always apply its
|
|
|
|
|
- // texture transform, never bake it in. In fact, we don't
|
|
|
|
|
- // even care about its UV's in this case, since we won't be
|
|
|
|
|
- // using them.
|
|
|
|
|
- tex_mat_attrib = apply_tex_mat(tex_mat_attrib, def._stage, egg_tex);
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- // Otherwise, we need to record that there is at least one
|
|
|
|
|
- // texture on this particular UV name and with this particular
|
|
|
|
|
- // texture matrix. If there are no other textures, or if all
|
|
|
|
|
- // of the other textures use the same texture matrix, then
|
|
|
|
|
- // tex_mats[uv_name].size() will remain 1 (which tells us we
|
|
|
|
|
- // can bake in the texture matrix to the UV's). On the other
|
|
|
|
|
- // hand, if there is another texture on the same uv name but
|
|
|
|
|
- // with a different transform, it will increase
|
|
|
|
|
- // tex_mats[uv_name].size() to at least 2, indicating we can't
|
|
|
|
|
- // bake in the texture matrix.
|
|
|
|
|
- tex_mats[uv_name][egg_tex->get_transform()].push_back(&def);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // These parametric primitive types can't have their UV's baked in,
|
|
|
|
|
- // so if we have one of these we always need to apply the texture
|
|
|
|
|
- // matrix as a separate attribute, regardless of how many textures
|
|
|
|
|
- // share the particular UV set.
|
|
|
|
|
- bool needs_tex_mat = (egg_prim->is_of_type(EggCurve::get_class_type()) ||
|
|
|
|
|
- egg_prim->is_of_type(EggSurface::get_class_type()));
|
|
|
|
|
-
|
|
|
|
|
- // Now that we've visited all of the textures in the above loop, we
|
|
|
|
|
- // can go back and see how many of them share the same UV name and
|
|
|
|
|
- // texture matrix.
|
|
|
|
|
- TexMats::const_iterator tmi;
|
|
|
|
|
- for (tmi = tex_mats.begin(); tmi != tex_mats.end(); ++tmi) {
|
|
|
|
|
- const InternalName *uv_name = (*tmi).first;
|
|
|
|
|
- const TexMatTransforms &tmt = (*tmi).second;
|
|
|
|
|
-
|
|
|
|
|
- if (tmt.size() == 1 && !needs_tex_mat) {
|
|
|
|
|
- // Only one unique transform sharing this set of UV's. We can
|
|
|
|
|
- // bake in the transform!
|
|
|
|
|
- const TexMatTextures &tmtex = (*tmt.begin()).second;
|
|
|
|
|
-
|
|
|
|
|
- // The first EggTexture on the list is sufficient, since we know
|
|
|
|
|
- // they all have the same transform.
|
|
|
|
|
- nassertv(!tmtex.empty());
|
|
|
|
|
- TexMatTextures::const_iterator tmtexi = tmtex.begin();
|
|
|
|
|
- const EggTexture *egg_tex = (*tmtexi)->_egg_tex;
|
|
|
|
|
- if (egg_tex->has_transform()) {
|
|
|
|
|
- // If there's no transform, it's an identity matrix; don't
|
|
|
|
|
- // bother recording it. Of course, it would do no harm to
|
|
|
|
|
- // record it if we felt like it.
|
|
|
|
|
- bake_in_uvs[uv_name] = egg_tex;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- // Multiple transforms on this UV set, or a geometry type that
|
|
|
|
|
- // doesn't support baking in UV's. We have to apply the
|
|
|
|
|
- // texture matrix to each stage.
|
|
|
|
|
- TexMatTransforms::const_iterator tmti;
|
|
|
|
|
- for (tmti = tmt.begin(); tmti != tmt.end(); ++tmti) {
|
|
|
|
|
- const TexMatTextures &tmtex = (*tmti).second;
|
|
|
|
|
- TexMatTextures::const_iterator tmtexi;
|
|
|
|
|
- for (tmtexi = tmtex.begin(); tmtexi != tmtex.end(); ++tmtexi) {
|
|
|
|
|
- const EggTexture *egg_tex = (*tmtexi)->_egg_tex;
|
|
|
|
|
- TextureStage *stage = (*tmtexi)->_stage;
|
|
|
|
|
-
|
|
|
|
|
- tex_mat_attrib = apply_tex_mat(tex_mat_attrib, stage, egg_tex);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (texture_attrib != (RenderAttrib *)NULL) {
|
|
|
|
|
- bucket.add_attrib(texture_attrib);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (tex_gen_attrib != (RenderAttrib *)NULL) {
|
|
|
|
|
- bucket.add_attrib(tex_gen_attrib);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (tex_mat_attrib != (RenderAttrib *)NULL) {
|
|
|
|
|
- bucket.add_attrib(tex_mat_attrib);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (egg_prim->has_material()) {
|
|
|
|
|
- CPT(RenderAttrib) mt =
|
|
|
|
|
- get_material_attrib(egg_prim->get_material(),
|
|
|
|
|
- egg_prim->get_bface_flag());
|
|
|
|
|
- bucket.add_attrib(mt);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // Also check the color of the primitive to see if we should assume
|
|
|
|
|
- // alpha based on the alpha values specified in the egg file.
|
|
|
|
|
- if (am == EggRenderMode::AM_unspecified) {
|
|
|
|
|
- if (egg_prim->has_color()) {
|
|
|
|
|
- if (egg_prim->get_color()[3] != 1.0) {
|
|
|
|
|
- implicit_alpha = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- EggPrimitive::const_iterator vi;
|
|
|
|
|
- for (vi = egg_prim->begin();
|
|
|
|
|
- !implicit_alpha && vi != egg_prim->end();
|
|
|
|
|
- ++vi) {
|
|
|
|
|
- if ((*vi)->has_color()) {
|
|
|
|
|
- if ((*vi)->get_color()[3] != 1.0) {
|
|
|
|
|
- implicit_alpha = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (implicit_alpha) {
|
|
|
|
|
- am = EggRenderMode::AM_on;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (am == EggRenderMode::AM_on &&
|
|
|
|
|
- egg_alpha_mode != EggRenderMode::AM_unspecified) {
|
|
|
|
|
- // Alpha type "on" means to get the default transparency type.
|
|
|
|
|
- am = egg_alpha_mode;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- switch (am) {
|
|
|
|
|
- case EggRenderMode::AM_on:
|
|
|
|
|
- case EggRenderMode::AM_blend:
|
|
|
|
|
- bucket.add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ EggRenderState render_state(*this);
|
|
|
|
|
+ render_state.fill_state(egg_prim);
|
|
|
|
|
|
|
|
- case EggRenderMode::AM_blend_no_occlude:
|
|
|
|
|
- bucket.add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
|
|
|
|
- bucket.add_attrib(DepthWriteAttrib::make(DepthWriteAttrib::M_off));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case EggRenderMode::AM_ms:
|
|
|
|
|
- bucket.add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_multisample));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case EggRenderMode::AM_ms_mask:
|
|
|
|
|
- bucket.add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_multisample_mask));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case EggRenderMode::AM_binary:
|
|
|
|
|
- bucket.add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_binary));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case EggRenderMode::AM_dual:
|
|
|
|
|
- bucket.add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_dual));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- switch (dwm) {
|
|
|
|
|
- case EggRenderMode::DWM_on:
|
|
|
|
|
- bucket.add_attrib(DepthWriteAttrib::make(DepthWriteAttrib::M_on));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case EggRenderMode::DWM_off:
|
|
|
|
|
- bucket.add_attrib(DepthWriteAttrib::make(DepthWriteAttrib::M_off));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- switch (dtm) {
|
|
|
|
|
- case EggRenderMode::DTM_on:
|
|
|
|
|
- bucket.add_attrib(DepthTestAttrib::make(DepthTestAttrib::M_less));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case EggRenderMode::DTM_off:
|
|
|
|
|
- bucket.add_attrib(DepthTestAttrib::make(DepthTestAttrib::M_none));
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- default:
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- switch (vm) {
|
|
|
|
|
- case EggRenderMode::VM_hidden:
|
|
|
|
|
- bucket._hidden = true;
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case EggRenderMode::VM_normal:
|
|
|
|
|
- default:
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (has_bin) {
|
|
|
|
|
- bucket.add_attrib(CullBinAttrib::make(bin, draw_order));
|
|
|
|
|
-
|
|
|
|
|
- } else if (has_draw_order) {
|
|
|
|
|
- bucket.add_attrib(CullBinAttrib::make("fixed", draw_order));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- if (egg_prim->get_bface_flag()) {
|
|
|
|
|
- // The primitive is marked with backface culling disabled--we want
|
|
|
|
|
- // to see both sides.
|
|
|
|
|
- bucket.add_attrib(CullFaceAttrib::make(CullFaceAttrib::M_cull_none));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ bucket._state = render_state._state;
|
|
|
|
|
+ bucket._hidden = render_state._hidden;
|
|
|
|
|
+ bake_in_uvs = render_state._bake_in_uvs;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1683,9 +1324,7 @@ setup_bucket(BuilderBucket &bucket, EggLoader::BakeInUVs &bake_in_uvs,
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
PandaNode *EggLoader::
|
|
PandaNode *EggLoader::
|
|
|
make_node(EggNode *egg_node, PandaNode *parent) {
|
|
make_node(EggNode *egg_node, PandaNode *parent) {
|
|
|
- if (egg_node->is_of_type(EggPrimitive::get_class_type())) {
|
|
|
|
|
- return make_node(DCAST(EggPrimitive, egg_node), parent);
|
|
|
|
|
- } else if (egg_node->is_of_type(EggBin::get_class_type())) {
|
|
|
|
|
|
|
+ if (egg_node->is_of_type(EggBin::get_class_type())) {
|
|
|
return make_node(DCAST(EggBin, egg_node), parent);
|
|
return make_node(DCAST(EggBin, egg_node), parent);
|
|
|
} else if (egg_node->is_of_type(EggGroup::get_class_type())) {
|
|
} else if (egg_node->is_of_type(EggGroup::get_class_type())) {
|
|
|
return make_node(DCAST(EggGroup, egg_node), parent);
|
|
return make_node(DCAST(EggGroup, egg_node), parent);
|
|
@@ -1698,6 +1337,7 @@ make_node(EggNode *egg_node, PandaNode *parent) {
|
|
|
return (PandaNode *)NULL;
|
|
return (PandaNode *)NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: EggLoader::make_node (EggPrimitive)
|
|
// Function: EggLoader::make_node (EggPrimitive)
|
|
|
// Access: Private
|
|
// Access: Private
|
|
@@ -1727,6 +1367,7 @@ make_node(EggPrimitive *egg_prim, PandaNode *parent) {
|
|
|
}
|
|
}
|
|
|
return (PandaNode *)NULL;
|
|
return (PandaNode *)NULL;
|
|
|
}
|
|
}
|
|
|
|
|
+*/
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: EggLoader::make_node (EggBin)
|
|
// Function: EggLoader::make_node (EggBin)
|
|
@@ -1735,41 +1376,149 @@ make_node(EggPrimitive *egg_prim, PandaNode *parent) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
PandaNode *EggLoader::
|
|
PandaNode *EggLoader::
|
|
|
make_node(EggBin *egg_bin, PandaNode *parent) {
|
|
make_node(EggBin *egg_bin, PandaNode *parent) {
|
|
|
- // Presently, an EggBin can only mean an LOD node (i.e. a parent of
|
|
|
|
|
- // one or more EggGroups with LOD specifications). Later it might
|
|
|
|
|
- // mean other things as well.
|
|
|
|
|
|
|
+ // An EggBin might mean an LOD node (i.e. a parent of one or more
|
|
|
|
|
+ // EggGroups with LOD specifications), or it might mean a polyset
|
|
|
|
|
+ // node (a parent of one or more similar EggPrimitives).
|
|
|
|
|
+ switch (egg_bin->get_bin_number()) {
|
|
|
|
|
+ case EggBinner::BN_polyset:
|
|
|
|
|
+ return make_polyset(egg_bin, parent);
|
|
|
|
|
+
|
|
|
|
|
+ case EggBinner::BN_lod:
|
|
|
|
|
+ return make_lod(egg_bin, parent);
|
|
|
|
|
|
|
|
- nassertr((EggBinner::BinNumber)egg_bin->get_bin_number() == EggBinner::BN_lod, NULL);
|
|
|
|
|
|
|
+ case EggBinner::BN_none:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Shouldn't get here.
|
|
|
|
|
+ return (PandaNode *)NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: EggLoader::make_polyset
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+PandaNode *EggLoader::
|
|
|
|
|
+make_polyset(EggBin *egg_bin, PandaNode *parent) {
|
|
|
|
|
+ if (egg_bin->empty()) {
|
|
|
|
|
+ // If there are no children--no primitives--never mind.
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // We know that all of the primitives in the bin have the same
|
|
|
|
|
+ // vertex pool and same render state, so we can get that information
|
|
|
|
|
+ // from the first primitive.
|
|
|
|
|
+ EggGroup::const_iterator ci = egg_bin->begin();
|
|
|
|
|
+ nassertr(ci != egg_bin->end(), NULL);
|
|
|
|
|
+ CPT(EggPrimitive) first_prim = DCAST(EggPrimitive, (*ci));
|
|
|
|
|
+ nassertr(first_prim != (EggPrimitive *)NULL, NULL);
|
|
|
|
|
+ const EggRenderState *render_state;
|
|
|
|
|
+ DCAST_INTO_R(render_state, first_prim->get_user_data(EggRenderState::get_class_type()), NULL);
|
|
|
|
|
+
|
|
|
|
|
+ if (render_state->_hidden && egg_suppress_hidden) {
|
|
|
|
|
+ // Eat this polyset.
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!use_qpgeom) {
|
|
|
|
|
+ // In the old Geom system, just send each primitive to the
|
|
|
|
|
+ // Builder.
|
|
|
|
|
+ for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
|
|
|
|
+ EggPrimitive *egg_prim;
|
|
|
|
|
+ DCAST_INTO_R(egg_prim, (*ci), NULL);
|
|
|
|
|
+ make_nonindexed_primitive(egg_prim, parent, NULL, _comp_verts_maker);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Convert the primitives' vertex pool to a GeomVertexData.
|
|
|
|
|
+ PT(qpGeomVertexData) vertex_data =
|
|
|
|
|
+ make_vertex_data(first_prim->get_pool(), first_prim->get_vertex_to_node());
|
|
|
|
|
+ nassertr(vertex_data != (qpGeomVertexData *)NULL, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ // And now create a Geom to hold the primitives.
|
|
|
|
|
+ PT(qpGeom) geom = new qpGeom;
|
|
|
|
|
+ geom->set_vertex_data(vertex_data);
|
|
|
|
|
+
|
|
|
|
|
+ // Automatically triangulate any higher-order polygons we might have.
|
|
|
|
|
+ egg_bin->triangulate_polygons(true);
|
|
|
|
|
+
|
|
|
|
|
+ // Now create a handful of GeomPrimitives corresponding to the
|
|
|
|
|
+ // various types of primitives we have.
|
|
|
|
|
+ Primitives primitives;
|
|
|
|
|
+ for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
|
|
|
|
+ EggPrimitive *egg_prim;
|
|
|
|
|
+ DCAST_INTO_R(egg_prim, (*ci), NULL);
|
|
|
|
|
+ make_primitive(egg_prim, primitives);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!primitives.empty()) {
|
|
|
|
|
+ // Add each new primitive to the Geom.
|
|
|
|
|
+ Primitives::const_iterator pi;
|
|
|
|
|
+ for (pi = primitives.begin(); pi != primitives.end(); ++pi) {
|
|
|
|
|
+ qpGeomPrimitive *primitive = (*pi).second;
|
|
|
|
|
+ geom->add_primitive(primitive);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Now, is our parent node a GeomNode, or just an ordinary
|
|
|
|
|
+ // PandaNode? If it's a GeomNode, we can add the new Geom directly
|
|
|
|
|
+ // to our parent; otherwise, we need to create a new node.
|
|
|
|
|
+ if (parent->is_geom_node() && !render_state->_hidden) {
|
|
|
|
|
+ DCAST(GeomNode, parent)->add_geom(geom, render_state->_state);
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ PT(GeomNode) geom_node = new GeomNode(egg_bin->get_name());
|
|
|
|
|
+ if (render_state->_hidden) {
|
|
|
|
|
+ parent->add_stashed(geom_node);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ parent->add_child(geom_node);
|
|
|
|
|
+ }
|
|
|
|
|
+ geom_node->add_geom(geom, render_state->_state);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: EggLoader::make_lod
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+PandaNode *EggLoader::
|
|
|
|
|
+make_lod(EggBin *egg_bin, PandaNode *parent) {
|
|
|
LODNode *lod_node = new LODNode(egg_bin->get_name());
|
|
LODNode *lod_node = new LODNode(egg_bin->get_name());
|
|
|
|
|
|
|
|
pvector<LODInstance> instances;
|
|
pvector<LODInstance> instances;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
EggGroup::const_iterator ci;
|
|
EggGroup::const_iterator ci;
|
|
|
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
|
for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
|
|
|
LODInstance instance(*ci);
|
|
LODInstance instance(*ci);
|
|
|
instances.push_back(instance);
|
|
instances.push_back(instance);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Now that we've created all of our children, put them in the
|
|
// Now that we've created all of our children, put them in the
|
|
|
// proper order and tell the LOD node about them.
|
|
// proper order and tell the LOD node about them.
|
|
|
sort(instances.begin(), instances.end());
|
|
sort(instances.begin(), instances.end());
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!instances.empty()) {
|
|
if (!instances.empty()) {
|
|
|
// Set up the LOD node's center. All of the children should have
|
|
// Set up the LOD node's center. All of the children should have
|
|
|
// the same center, because that's how we binned them.
|
|
// the same center, because that's how we binned them.
|
|
|
lod_node->set_center(LCAST(float, instances[0]._d->_center));
|
|
lod_node->set_center(LCAST(float, instances[0]._d->_center));
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
for (size_t i = 0; i < instances.size(); i++) {
|
|
for (size_t i = 0; i < instances.size(); i++) {
|
|
|
// Create the children in the proper order within the scene graph.
|
|
// Create the children in the proper order within the scene graph.
|
|
|
const LODInstance &instance = instances[i];
|
|
const LODInstance &instance = instances[i];
|
|
|
make_node(instance._egg_node, lod_node);
|
|
make_node(instance._egg_node, lod_node);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// All of the children should have the same center, because that's
|
|
// All of the children should have the same center, because that's
|
|
|
// how we binned them.
|
|
// how we binned them.
|
|
|
nassertr(lod_node->get_center().almost_equal
|
|
nassertr(lod_node->get_center().almost_equal
|
|
|
(LCAST(float, instance._d->_center), 0.01), NULL);
|
|
(LCAST(float, instance._d->_center), 0.01), NULL);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// Tell the LOD node about this child's switching distances.
|
|
// Tell the LOD node about this child's switching distances.
|
|
|
lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out);
|
|
lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out);
|
|
|
}
|
|
}
|
|
@@ -1891,8 +1640,21 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
- // A normal group; just create a normal node, and traverse.
|
|
|
|
|
- node = new PandaNode(egg_group->get_name());
|
|
|
|
|
|
|
+ // A normal group; just create a normal node, and traverse. But
|
|
|
|
|
+ // if all of the children of this group are polysets, anticipate
|
|
|
|
|
+ // this for the benefit of smaller grouping, and create a single
|
|
|
|
|
+ // GeomNode for all of the children.
|
|
|
|
|
+ bool all_polysets = false;
|
|
|
|
|
+ bool any_hidden = false;
|
|
|
|
|
+ if (use_qpgeom) {
|
|
|
|
|
+ check_for_polysets(egg_group, all_polysets, any_hidden);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (all_polysets && !any_hidden) {
|
|
|
|
|
+ node = new GeomNode(egg_group->get_name());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ node = new PandaNode(egg_group->get_name());
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
EggGroup::const_iterator ci;
|
|
EggGroup::const_iterator ci;
|
|
|
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
|
|
for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
|
|
@@ -2030,6 +1792,175 @@ make_node(EggGroupNode *egg_group, PandaNode *parent) {
|
|
|
return node;
|
|
return node;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: EggLoader::check_for_polysets
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Sets all_polysets true if all of the children of this
|
|
|
|
|
+// node represent a polyset. Sets any_hidden true if
|
|
|
|
|
+// any of those polysets are flagged hidden.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void EggLoader::
|
|
|
|
|
+check_for_polysets(EggGroup *egg_group, bool &all_polysets, bool &any_hidden) {
|
|
|
|
|
+ all_polysets = (!egg_group->empty());
|
|
|
|
|
+ any_hidden = false;
|
|
|
|
|
+
|
|
|
|
|
+ EggGroup::const_iterator ci;
|
|
|
|
|
+ for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
|
|
|
|
|
+ if ((*ci)->is_of_type(EggBin::get_class_type())) {
|
|
|
|
|
+ EggBin *egg_bin = DCAST(EggBin, (*ci));
|
|
|
|
|
+ if (egg_bin->get_bin_number() == EggBinner::BN_polyset) {
|
|
|
|
|
+ // We know that all of the primitives in the bin have the same
|
|
|
|
|
+ // render state, so we can get that information from the first
|
|
|
|
|
+ // primitive.
|
|
|
|
|
+ EggGroup::const_iterator bci = egg_bin->begin();
|
|
|
|
|
+ nassertv(bci != egg_bin->end());
|
|
|
|
|
+ const EggPrimitive *first_prim;
|
|
|
|
|
+ DCAST_INTO_V(first_prim, (*bci));
|
|
|
|
|
+ const EggRenderState *render_state;
|
|
|
|
|
+ DCAST_INTO_V(render_state, first_prim->get_user_data(EggRenderState::get_class_type()));
|
|
|
|
|
+
|
|
|
|
|
+ if (render_state->_hidden) {
|
|
|
|
|
+ any_hidden = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ all_polysets = false;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ all_polysets = false;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: EggLoader::make_vertex_data
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Creates a GeomVertexData structure from the vertex
|
|
|
|
|
+// pool, for the indicated transform space. If a
|
|
|
|
|
+// GeomVertexData has already been created for this
|
|
|
|
|
+// transform, just returns it.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+PT(qpGeomVertexData) EggLoader::
|
|
|
|
|
+make_vertex_data(EggVertexPool *vertex_pool, const LMatrix4d &transform) {
|
|
|
|
|
+ VertexPoolTransform vpt;
|
|
|
|
|
+ vpt._vertex_pool = vertex_pool;
|
|
|
|
|
+ vpt._transform = transform;
|
|
|
|
|
+
|
|
|
|
|
+ VertexPoolData::iterator di;
|
|
|
|
|
+ di = _vertex_pool_data.find(vpt);
|
|
|
|
|
+ if (di != _vertex_pool_data.end()) {
|
|
|
|
|
+ return (*di).second;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Decide on the format for the vertices.
|
|
|
|
|
+ PT(qpGeomVertexArrayFormat) array_format = new qpGeomVertexArrayFormat;
|
|
|
|
|
+ array_format->add_data_type
|
|
|
|
|
+ (InternalName::get_vertex(), vertex_pool->get_num_dimensions(),
|
|
|
|
|
+ qpGeomVertexDataType::NT_float);
|
|
|
|
|
+
|
|
|
|
|
+ if (vertex_pool->has_normals()) {
|
|
|
|
|
+ array_format->add_data_type
|
|
|
|
|
+ (InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (vertex_pool->has_colors()) {
|
|
|
|
|
+ array_format->add_data_type
|
|
|
|
|
+ (InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ vector_string uv_names;
|
|
|
|
|
+ vertex_pool->get_uv_names(uv_names);
|
|
|
|
|
+ vector_string::const_iterator ni;
|
|
|
|
|
+ for (ni = uv_names.begin(); ni != uv_names.end(); ++ni) {
|
|
|
|
|
+ string name = (*ni);
|
|
|
|
|
+ if (name == "default") {
|
|
|
|
|
+ name = string();
|
|
|
|
|
+ }
|
|
|
|
|
+ array_format->add_data_type
|
|
|
|
|
+ (InternalName::get_texcoord_name(name), 2,
|
|
|
|
|
+ qpGeomVertexDataType::NT_float);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ CPT(qpGeomVertexFormat) format =
|
|
|
|
|
+ qpGeomVertexFormat::register_format(new qpGeomVertexFormat(array_format));
|
|
|
|
|
+
|
|
|
|
|
+ // Now create a new GeomVertexData using the indicated format.
|
|
|
|
|
+ PT(qpGeomVertexData) vertex_data = new qpGeomVertexData(format);
|
|
|
|
|
+
|
|
|
|
|
+ // And fill the data from the vertex pool.
|
|
|
|
|
+ EggVertexPool::const_iterator vi;
|
|
|
|
|
+ for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
|
|
|
|
|
+ qpGeomVertexIterator gvi(vertex_data);
|
|
|
|
|
+ EggVertex *vertex = (*vi);
|
|
|
|
|
+ gvi.set_vertex(vertex->get_index());
|
|
|
|
|
+
|
|
|
|
|
+ gvi.set_data_type(InternalName::get_vertex());
|
|
|
|
|
+ gvi.set_data4(LCAST(float, vertex->get_pos4()));
|
|
|
|
|
+
|
|
|
|
|
+ if (vertex->has_normal()) {
|
|
|
|
|
+ gvi.set_data_type(InternalName::get_normal());
|
|
|
|
|
+ gvi.set_data3(LCAST(float, vertex->get_normal()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (vertex->has_color()) {
|
|
|
|
|
+ gvi.set_data_type(InternalName::get_color());
|
|
|
|
|
+ gvi.set_data4(vertex->get_color());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ EggVertex::const_uv_iterator uvi;
|
|
|
|
|
+ for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
|
|
|
|
|
+ EggVertexUV *uv = (*uvi);
|
|
|
|
|
+ string name = uv->get_name();
|
|
|
|
|
+ if (name == "default") {
|
|
|
|
|
+ name = string();
|
|
|
|
|
+ }
|
|
|
|
|
+ gvi.set_data_type(InternalName::get_texcoord_name(name));
|
|
|
|
|
+ gvi.set_data2(LCAST(float, uv->get_uv()));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bool inserted = _vertex_pool_data.insert
|
|
|
|
|
+ (VertexPoolData::value_type(vpt, vertex_data)).second;
|
|
|
|
|
+ nassertr(inserted, vertex_data);
|
|
|
|
|
+
|
|
|
|
|
+ return vertex_data;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: EggLoader::make_primitive
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Creates a GeomPrimitive corresponding to the
|
|
|
|
|
+// indicated EggPrimitive, and adds it to the set.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void EggLoader::
|
|
|
|
|
+make_primitive(EggPrimitive *egg_prim, EggLoader::Primitives &primitives) {
|
|
|
|
|
+ PT(qpGeomPrimitive) primitive;
|
|
|
|
|
+ if (egg_prim->is_of_type(EggPolygon::get_class_type())) {
|
|
|
|
|
+ if (egg_prim->size() == 3) {
|
|
|
|
|
+ primitive = new qpGeomTriangles;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (primitive == NULL) {
|
|
|
|
|
+ // Don't know how to make this kind of primitive.
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Insert the primitive into the set, but if we already have a
|
|
|
|
|
+ // primitive of that type, reset the pointer to that one instead.
|
|
|
|
|
+ pair<Primitives::iterator, bool> result =
|
|
|
|
|
+ primitives.insert(Primitives::value_type(primitive->get_type(), primitive));
|
|
|
|
|
+ primitive = (*result.first).second;
|
|
|
|
|
+
|
|
|
|
|
+ // Now add the vertices.
|
|
|
|
|
+ EggPrimitive::const_iterator vi;
|
|
|
|
|
+ for (vi = egg_prim->begin(); vi != egg_prim->end(); ++vi) {
|
|
|
|
|
+ primitive->add_vertex((*vi)->get_index());
|
|
|
|
|
+ }
|
|
|
|
|
+ primitive->close_primitive();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: EggLoader::set_portal_polygon
|
|
// Function: EggLoader::set_portal_polygon
|
|
|
// Access: Private
|
|
// Access: Private
|
|
@@ -3086,84 +3017,5 @@ get_combine_operand(const EggTexture *egg_tex,
|
|
|
return TextureStage::CO_undefined;
|
|
return TextureStage::CO_undefined;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: EggLoader::get_tex_gen
|
|
|
|
|
-// Access: Private, Static
|
|
|
|
|
-// Description: Extracts the tex_gen from the given egg texture,
|
|
|
|
|
-// and returns its corresponding TexGenAttrib mode.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-TexGenAttrib::Mode EggLoader::
|
|
|
|
|
-get_tex_gen(const EggTexture *egg_tex) {
|
|
|
|
|
- switch (egg_tex->get_tex_gen()) {
|
|
|
|
|
- case EggTexture::TG_unspecified:
|
|
|
|
|
- return TexGenAttrib::M_off;
|
|
|
|
|
-
|
|
|
|
|
- case EggTexture::TG_eye_sphere_map:
|
|
|
|
|
- return TexGenAttrib::M_eye_sphere_map;
|
|
|
|
|
-
|
|
|
|
|
- case EggTexture::TG_world_cube_map:
|
|
|
|
|
- return TexGenAttrib::M_world_cube_map;
|
|
|
|
|
-
|
|
|
|
|
- case EggTexture::TG_eye_cube_map:
|
|
|
|
|
- return TexGenAttrib::M_eye_cube_map;
|
|
|
|
|
-
|
|
|
|
|
- case EggTexture::TG_world_normal:
|
|
|
|
|
- return TexGenAttrib::M_world_normal;
|
|
|
|
|
-
|
|
|
|
|
- case EggTexture::TG_eye_normal:
|
|
|
|
|
- return TexGenAttrib::M_eye_normal;
|
|
|
|
|
-
|
|
|
|
|
- case EggTexture::TG_world_position:
|
|
|
|
|
- return TexGenAttrib::M_world_position;
|
|
|
|
|
-
|
|
|
|
|
- case EggTexture::TG_object_position:
|
|
|
|
|
- return TexGenAttrib::M_object_position;
|
|
|
|
|
-
|
|
|
|
|
- case EggTexture::TG_eye_position:
|
|
|
|
|
- return TexGenAttrib::M_eye_position;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- return TexGenAttrib::M_off;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: EggLoader::apply_tex_mat
|
|
|
|
|
-// Access: Private, Static
|
|
|
|
|
-// Description: Applies the texture matrix from the indicated egg
|
|
|
|
|
-// texture to the given TexMatrixAttrib, and returns the
|
|
|
|
|
-// new attrib.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-CPT(RenderAttrib) EggLoader::
|
|
|
|
|
-apply_tex_mat(CPT(RenderAttrib) tex_mat_attrib,
|
|
|
|
|
- TextureStage *stage, const EggTexture *egg_tex) {
|
|
|
|
|
- if (egg_tex->has_transform()) {
|
|
|
|
|
- const LMatrix3d &tex_mat = egg_tex->get_transform();
|
|
|
|
|
- LMatrix4f mat4(tex_mat(0, 0), tex_mat(0, 1), 0.0f, tex_mat(0, 2),
|
|
|
|
|
- tex_mat(1, 0), tex_mat(1, 1), 0.0f, tex_mat(1, 2),
|
|
|
|
|
- 0.0f, 0.0f, 1.0f, 0.0f,
|
|
|
|
|
- tex_mat(2, 0), tex_mat(2, 1), 0.0f, tex_mat(2, 2));
|
|
|
|
|
- CPT(TransformState) transform;
|
|
|
|
|
-
|
|
|
|
|
- LVecBase3f scale, shear, hpr, translate;
|
|
|
|
|
- if (decompose_matrix(mat4, scale, shear, hpr, translate)) {
|
|
|
|
|
- // If the texture matrix can be represented componentwise, do
|
|
|
|
|
- // so.
|
|
|
|
|
- transform = TransformState::make_pos_hpr_scale_shear
|
|
|
|
|
- (translate, hpr, scale, shear);
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- // Otherwise, make a matrix transform.
|
|
|
|
|
- transform = TransformState::make_mat(mat4);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (tex_mat_attrib == (const RenderAttrib *)NULL) {
|
|
|
|
|
- tex_mat_attrib = TexMatrixAttrib::make();
|
|
|
|
|
- }
|
|
|
|
|
- tex_mat_attrib = DCAST(TexMatrixAttrib, tex_mat_attrib)->
|
|
|
|
|
- add_stage(stage, transform);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return tex_mat_attrib;
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
|
|
|