fix problems with large meshes

This commit is contained in:
David Rose 2011-02-28 18:12:12 +00:00
parent 3462cbe372
commit 8cfb6d4f83
3 changed files with 150 additions and 1 deletions

View File

@ -24,6 +24,7 @@
#include "geomVertexData.h"
#include "geomVertexFormat.h"
#include "geomPoints.h"
#include "geomTriangles.h"
#include "geomVertexWriter.h"
#include "look_at.h"
@ -477,6 +478,148 @@ generate_vis_points() const {
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

View File

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

View File

@ -142,7 +142,7 @@ process_pfm(const Filename &input_filename, PfmFile &file) {
}
if (_got_vis_filename) {
NodePath mesh = file.generate_vis_points();
NodePath mesh = file.generate_vis_mesh();
if (_got_vistex_filename) {
PT(Texture) tex = TexturePool::load_texture(_vistex_filename);
if (tex == NULL) {
@ -150,6 +150,9 @@ process_pfm(const Filename &input_filename, PfmFile &file) {
} else {
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.reparent_to(_mesh_root);