Browse Source

fix problems with large meshes

David Rose 15 years ago
parent
commit
8cfb6d4f83

+ 143 - 0
pandatool/src/pfmprogs/pfmFile.cxx

@@ -24,6 +24,7 @@
 #include "geomVertexData.h"
 #include "geomVertexData.h"
 #include "geomVertexFormat.h"
 #include "geomVertexFormat.h"
 #include "geomPoints.h"
 #include "geomPoints.h"
+#include "geomTriangles.h"
 #include "geomVertexWriter.h"
 #include "geomVertexWriter.h"
 #include "look_at.h"
 #include "look_at.h"
 
 
@@ -477,6 +478,148 @@ generate_vis_points() const {
   return NodePath(gnode);
   return NodePath(gnode);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::generate_vis_mesh
+//       Access: Public
+//  Description: Creates a triangle mesh with the points of the pfm as
+//               3-d coordinates in space, and texture coordinates
+//               ranging from 0 .. 1 based on the position within the
+//               pfm grid.
+////////////////////////////////////////////////////////////////////
+NodePath PfmFile::
+generate_vis_mesh() const {
+  nassertr(is_valid(), NodePath());
+  
+  PT(GeomNode) gnode = new GeomNode("");
+
+  PT(Geom) geom1 = make_vis_mesh_geom(false);
+  gnode->add_geom(geom1);
+
+  PT(Geom) geom2 = make_vis_mesh_geom(true);
+  gnode->add_geom(geom2);
+
+  return NodePath(gnode);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PfmFile::make_vis_mesh_geom
+//       Access: Private
+//  Description: Returns a triangle mesh for the pfm.  If inverted is
+//               true, the mesh is facing the opposite direction.
+////////////////////////////////////////////////////////////////////
+PT(Geom) PfmFile::
+make_vis_mesh_geom(bool inverted) const {
+  PT(GeomVertexData) vdata = new GeomVertexData
+    ("mesh", GeomVertexFormat::get_v3n3t2(),
+     Geom::UH_static);
+  int num_vertices = _x_size * _y_size;
+  vdata->set_num_rows(num_vertices);
+  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
+  GeomVertexWriter normal(vdata, InternalName::get_normal());
+  GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
+
+  for (int yi = 0; yi < _y_size; ++yi) {
+    for (int xi = 0; xi < _x_size; ++xi) {
+      vertex.add_data3f(get_point(xi, yi));
+      texcoord.add_data2f(float(xi) / float(_x_size - 1),
+                          float(yi) / float(_y_size - 1));
+
+      // Calculate the normal based on two neighboring vertices.
+      LPoint3f v[3];
+      v[0] = get_point(xi, yi);
+      if (xi + 1 < _x_size) {
+        v[1] = get_point(xi + 1, yi);
+      } else {
+        v[1] = v[0];
+        v[0] = get_point(xi - 1, yi);
+      }
+
+      if (yi + 1 < _y_size) {
+        v[2] = get_point(xi, yi + 1);
+      } else {
+        v[2] = v[0];
+        v[0] = get_point(xi, yi - 1);
+      }
+
+      LVector3f n = LVector3f::zero();
+      for (int i = 0; i < 3; ++i) {
+        const LPoint3f &v0 = v[i];
+        const LPoint3f &v1 = v[(i + 1) % 3];
+        n[0] += v0[1] * v1[2] - v0[2] * v1[1];
+        n[1] += v0[2] * v1[0] - v0[0] * v1[2];
+        n[2] += v0[0] * v1[1] - v0[1] * v1[0];
+      }
+      n.normalize();
+      if (inverted) {
+        n = -n;
+      }
+      normal.add_data3f(n);
+    }
+  }
+  
+  PT(Geom) geom = new Geom(vdata);
+  PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static);
+
+  if (num_vertices > 0xffff) {
+    // We need 32-bit indices.
+    tris->set_index_type(Geom::NT_uint32);
+  }
+
+  // We get direct access to the vertices data so we can speed things
+  // up by pre-specifying the number of vertices.  Need a better
+  // interface to do this same thing using the high-level access
+  // methods.
+  int num_indices = (_x_size - 1) * (_y_size - 1) * 6;
+
+  PT(GeomVertexArrayData) indices = tris->modify_vertices();
+  indices->set_num_rows(num_indices);
+  GeomVertexWriter index(indices, 0);
+
+  int actual_num_indices = 0;
+  for (int yi = 0; yi < _y_size - 1; ++yi) {
+    for (int xi = 0; xi < _x_size - 1; ++xi) {
+
+      if (_zero_special) {
+        if (get_point(xi, yi) == LPoint3f::zero() ||
+            get_point(xi, yi + 1) == LPoint3f::zero() ||
+            get_point(xi + 1, yi + 1) == LPoint3f::zero() ||
+            get_point(xi + 1, yi) == LPoint3f::zero()) {
+          continue;
+        }
+      }
+
+      int vi0 = ((xi) + (yi) * _x_size);
+      int vi1 = ((xi) + (yi + 1) * _x_size);
+      int vi2 = ((xi + 1) + (yi + 1) * _x_size);
+      int vi3 = ((xi + 1) + (yi) * _x_size);
+
+      if (inverted) {
+        index.add_data1i(vi2);
+        index.add_data1i(vi0);
+        index.add_data1i(vi1);
+        
+        index.add_data1i(vi3);
+        index.add_data1i(vi0);
+        index.add_data1i(vi2);
+      } else {
+        index.add_data1i(vi2);
+        index.add_data1i(vi1);
+        index.add_data1i(vi0);
+        
+        index.add_data1i(vi3);
+        index.add_data1i(vi2);
+        index.add_data1i(vi0);
+      }
+
+      actual_num_indices += 6;
+    }
+  }
+  indices->set_num_rows(actual_num_indices);
+  geom->add_primitive(tris);
+
+  return geom;
+}
+
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PfmFile::compute_sample_point
 //     Function: PfmFile::compute_sample_point

+ 3 - 0
pandatool/src/pfmprogs/pfmFile.h

@@ -58,8 +58,11 @@ public:
   PT(BoundingHexahedron) compute_planar_bounds(double point_dist, double sample_radius) const;
   PT(BoundingHexahedron) compute_planar_bounds(double point_dist, double sample_radius) const;
   
   
   NodePath generate_vis_points() const;
   NodePath generate_vis_points() const;
+  NodePath generate_vis_mesh() const;
 
 
 private:
 private:
+  PT(Geom) make_vis_mesh_geom(bool inverted) const;
+
   void compute_sample_point(LPoint3f &result,
   void compute_sample_point(LPoint3f &result,
                             double x, double y, double sample_radius) const;
                             double x, double y, double sample_radius) const;
   void box_filter_region(LPoint3f &result,
   void box_filter_region(LPoint3f &result,

+ 4 - 1
pandatool/src/pfmprogs/pfmTrans.cxx

@@ -142,7 +142,7 @@ process_pfm(const Filename &input_filename, PfmFile &file) {
   }
   }
 
 
   if (_got_vis_filename) {
   if (_got_vis_filename) {
-    NodePath mesh = file.generate_vis_points();
+    NodePath mesh = file.generate_vis_mesh();
     if (_got_vistex_filename) {
     if (_got_vistex_filename) {
       PT(Texture) tex = TexturePool::load_texture(_vistex_filename);
       PT(Texture) tex = TexturePool::load_texture(_vistex_filename);
       if (tex == NULL) {
       if (tex == NULL) {
@@ -150,6 +150,9 @@ process_pfm(const Filename &input_filename, PfmFile &file) {
       } else {
       } else {
         mesh.set_texture(tex);
         mesh.set_texture(tex);
       }
       }
+      if (tex->has_alpha(tex->get_format())) {
+        mesh.set_transparency(TransparencyAttrib::M_dual);
+      }
     }
     }
     mesh.set_name(input_filename.get_basename_wo_extension());
     mesh.set_name(input_filename.get_basename_wo_extension());
     mesh.reparent_to(_mesh_root);
     mesh.reparent_to(_mesh_root);