From 20e9703887524e25c18bd4c15ebfbc56ea70d854 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 4 Apr 2005 22:58:35 +0000 Subject: [PATCH] handle use_qpgeom on more internal things --- panda/src/collide/collisionInvSphere.cxx | 2 +- panda/src/collide/collisionPlane.cxx | 2 +- panda/src/collide/collisionPolygon.cxx | 2 +- panda/src/collide/collisionSphere.cxx | 2 +- panda/src/collide/collisionTube.cxx | 2 +- panda/src/distort/projectionScreen.cxx | 378 ++++++++++----- panda/src/egg/eggVertexPool.cxx | 22 + panda/src/egg/eggVertexPool.h | 1 + panda/src/egg2pg/eggBinner.cxx | 15 +- panda/src/egg2pg/eggBinner.h | 2 + panda/src/egg2pg/eggLoader.cxx | 40 +- panda/src/framework/windowFramework.cxx | 2 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 4 + panda/src/gobj/geom.cxx | 11 + panda/src/gobj/geom.h | 1 + panda/src/gobj/lens.cxx | 286 ++++++++--- panda/src/gobj/lens.h | 4 + panda/src/gobj/qpgeom.I | 34 -- panda/src/gobj/qpgeom.cxx | 92 +++- panda/src/gobj/qpgeom.h | 9 +- panda/src/gobj/qpgeomLines.cxx | 11 + panda/src/gobj/qpgeomLines.h | 1 + panda/src/gobj/qpgeomLinestrips.cxx | 11 + panda/src/gobj/qpgeomLinestrips.h | 2 + panda/src/gobj/qpgeomPoints.cxx | 11 + panda/src/gobj/qpgeomPoints.h | 1 + panda/src/gobj/qpgeomPrimitive.cxx | 13 + panda/src/gobj/qpgeomPrimitive.h | 2 + panda/src/gobj/qpgeomVertexData.cxx | 6 + panda/src/grutil/cardMaker.cxx | 90 +++- panda/src/grutil/lineSegs.I | 11 +- panda/src/grutil/lineSegs.cxx | 193 +++++--- panda/src/grutil/lineSegs.h | 6 +- panda/src/grutil/multitexReducer.cxx | 87 +++- panda/src/parametrics/ropeNode.cxx | 4 + panda/src/parametrics/sheetNode.cxx | 179 ++++--- panda/src/pgraph/cullTraverser.cxx | 72 ++- panda/src/pgraph/cullTraverser.h | 2 + panda/src/pgraph/geomNode.I | 21 - panda/src/pgraph/geomNode.cxx | 25 +- panda/src/pgraph/geomNode.h | 2 +- panda/src/pgraph/geomTransformer.cxx | 16 +- panda/src/pgui/pgFrameStyle.cxx | 453 +++++++++++++----- panda/src/text/dynamicTextGlyph.cxx | 8 +- panda/src/text/textNode.cxx | 6 +- 45 files changed, 1558 insertions(+), 586 deletions(-) diff --git a/panda/src/collide/collisionInvSphere.cxx b/panda/src/collide/collisionInvSphere.cxx index 7b2e62e31e..7087da9c92 100644 --- a/panda/src/collide/collisionInvSphere.cxx +++ b/panda/src/collide/collisionInvSphere.cxx @@ -310,7 +310,7 @@ fill_viz_geom() { if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("collision", qpGeomVertexFormat::get_v3cp(), + ("collision", qpGeomVertexFormat::get_v3(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); diff --git a/panda/src/collide/collisionPlane.cxx b/panda/src/collide/collisionPlane.cxx index 9ccf9456a6..cf23336a5c 100644 --- a/panda/src/collide/collisionPlane.cxx +++ b/panda/src/collide/collisionPlane.cxx @@ -327,7 +327,7 @@ fill_viz_geom() { if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("collision", qpGeomVertexFormat::get_v3cp(), + ("collision", qpGeomVertexFormat::get_v3(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index 138d721f7b..360b135bc7 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/panda/src/collide/collisionPolygon.cxx @@ -819,7 +819,7 @@ draw_polygon(GeomNode *viz_geom_node, GeomNode *bounds_viz_geom_node, if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("collision", qpGeomVertexFormat::get_v3cp(), + ("collision", qpGeomVertexFormat::get_v3(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); diff --git a/panda/src/collide/collisionSphere.cxx b/panda/src/collide/collisionSphere.cxx index 8c1f09b8ec..bdf00ccb75 100644 --- a/panda/src/collide/collisionSphere.cxx +++ b/panda/src/collide/collisionSphere.cxx @@ -329,7 +329,7 @@ fill_viz_geom() { if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("collision", qpGeomVertexFormat::get_v3cp(), + ("collision", qpGeomVertexFormat::get_v3(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); diff --git a/panda/src/collide/collisionTube.cxx b/panda/src/collide/collisionTube.cxx index 278dd2e756..a59b626b47 100644 --- a/panda/src/collide/collisionTube.cxx +++ b/panda/src/collide/collisionTube.cxx @@ -393,7 +393,7 @@ fill_viz_geom() { if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("collision", qpGeomVertexFormat::get_v3cp(), + ("collision", qpGeomVertexFormat::get_v3(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); diff --git a/panda/src/distort/projectionScreen.cxx b/panda/src/distort/projectionScreen.cxx index c04ae41fd2..88d221e28f 100644 --- a/panda/src/distort/projectionScreen.cxx +++ b/panda/src/distort/projectionScreen.cxx @@ -23,6 +23,11 @@ #include "transformState.h" #include "workingNodePath.h" #include "switchNode.h" +#include "qpgeom.h" +#include "qpgeomTristrips.h" +#include "qpgeomVertexWriter.h" +#include "qpgeomVertexReader.h" +#include "qpgeomVertexRewriter.h" TypeHandle ProjectionScreen::_type_handle; @@ -193,88 +198,144 @@ generate_screen(const NodePath &projector, const string &screen_name, NodePath this_np(this); rel_mat = projector.get_mat(this_np); + // Create a GeomNode to hold this mesh. + PT(GeomNode) geom_node = new GeomNode(screen_name); + // Now compute all the vertices for the screen. These are arranged // in order from left to right and bottom to top. int num_verts = num_x_verts * num_y_verts; Lens *lens = projector_node->get_lens(); float t = (distance - lens->get_near()) / (lens->get_far() - lens->get_near()); - PTA_Vertexf coords; - PTA_Normalf norms; - coords.reserve(num_verts); float x_scale = 2.0f / (num_x_verts - 1); float y_scale = 2.0f / (num_y_verts - 1); - - for (int yi = 0; yi < num_y_verts; yi++) { - for (int xi = 0; xi < num_x_verts; xi++) { - LPoint2f film = LPoint2f((float)xi * x_scale - 1.0f, - (float)yi * y_scale - 1.0f); - // Reduce the image by the fill ratio. - film *= fill_ratio; + if (use_qpgeom) { + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("projectionScreen", qpGeomVertexFormat::get_v3n3(), + qpGeomUsageHint::UH_dynamic); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + qpGeomVertexWriter normal(vdata, InternalName::get_normal()); + + for (int yi = 0; yi < num_y_verts; yi++) { + for (int xi = 0; xi < num_x_verts; xi++) { + LPoint2f film = LPoint2f((float)xi * x_scale - 1.0f, + (float)yi * y_scale - 1.0f); + + // Reduce the image by the fill ratio. + film *= fill_ratio; + + LPoint3f near_point, far_point; + lens->extrude(film, near_point, far_point); + LPoint3f point = near_point + t * (far_point - near_point); + + // Normals aren't often needed on projection screens, but you + // never know. + LVector3f norm; + lens->extrude_vec(film, norm); - LPoint3f near_point, far_point; - lens->extrude(film, near_point, far_point); - LPoint3f point = near_point + t * (far_point - near_point); - - // Normals aren't often needed on projection screens, but you - // never know. - LVector3f normal; - lens->extrude_vec(film, normal); - - coords.push_back(point * rel_mat); - norms.push_back(-normalize(normal * rel_mat)); + vertex.add_data3f(point * rel_mat); + normal.add_data3f(-normalize(norm * rel_mat)); + } } - } - nassertr((int)coords.size() == num_verts, NULL); + nassertr(vdata->get_num_vertices() == num_verts, NULL); - // Now synthesize a triangle mesh. We run triangle strips - // horizontally across the grid. - int num_tstrips = (num_y_verts-1); - int tstrip_length = 2*(num_x_verts-1)+2; - - PTA_int lengths; - PTA_ushort vindex; - - // Set the lengths array. we are creating num_tstrips t-strips, - // each of which has tstrip_length vertices. - lengths.reserve(num_tstrips); - int n; - for (n = 0; n < num_tstrips; n++) { - lengths.push_back(tstrip_length); - } - nassertr((int)lengths.size() == num_tstrips, NULL); - - // Now fill up the index array into the vertices. This lays out the - // order of the vertices in each t-strip. - vindex.reserve(num_tstrips * tstrip_length); - n = 0; - int ti, si; - for (ti = 1; ti < num_y_verts; ti++) { - vindex.push_back(ti * num_x_verts); - for (si = 1; si < num_x_verts; si++) { - vindex.push_back((ti - 1) * num_x_verts + (si-1)); - vindex.push_back(ti * num_x_verts + si); + // Now synthesize a triangle mesh. We run triangle strips + // horizontally across the grid. + PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static); + // Fill up the index array into the vertices. This lays out the + // order of the vertices in each tristrip. + int ti, si; + for (ti = 1; ti < num_y_verts; ti++) { + strip->add_vertex(ti * num_x_verts); + for (si = 1; si < num_x_verts; si++) { + strip->add_vertex((ti - 1) * num_x_verts + (si-1)); + strip->add_vertex(ti * num_x_verts + si); + } + strip->add_vertex((ti - 1) * num_x_verts + (num_x_verts-1)); + strip->close_primitive(); } - vindex.push_back((ti - 1) * num_x_verts + (num_x_verts-1)); + + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(strip); + + geom_node->add_geom(geom); + + } else { + PTA_Vertexf coords; + PTA_Normalf norms; + coords.reserve(num_verts); + + for (int yi = 0; yi < num_y_verts; yi++) { + for (int xi = 0; xi < num_x_verts; xi++) { + LPoint2f film = LPoint2f((float)xi * x_scale - 1.0f, + (float)yi * y_scale - 1.0f); + + // Reduce the image by the fill ratio. + film *= fill_ratio; + + LPoint3f near_point, far_point; + lens->extrude(film, near_point, far_point); + LPoint3f point = near_point + t * (far_point - near_point); + + // Normals aren't often needed on projection screens, but you + // never know. + LVector3f normal; + lens->extrude_vec(film, normal); + + coords.push_back(point * rel_mat); + norms.push_back(-normalize(normal * rel_mat)); + } + } + nassertr((int)coords.size() == num_verts, NULL); + + // Now synthesize a triangle mesh. We run triangle strips + // horizontally across the grid. + int num_tstrips = (num_y_verts-1); + int tstrip_length = 2*(num_x_verts-1)+2; + + PTA_int lengths; + PTA_ushort vindex; + + // Set the lengths array. we are creating num_tstrips t-strips, + // each of which has tstrip_length vertices. + lengths.reserve(num_tstrips); + int n; + for (n = 0; n < num_tstrips; n++) { + lengths.push_back(tstrip_length); + } + nassertr((int)lengths.size() == num_tstrips, NULL); + + // Now fill up the index array into the vertices. This lays out the + // order of the vertices in each t-strip. + vindex.reserve(num_tstrips * tstrip_length); + n = 0; + int ti, si; + for (ti = 1; ti < num_y_verts; ti++) { + vindex.push_back(ti * num_x_verts); + for (si = 1; si < num_x_verts; si++) { + vindex.push_back((ti - 1) * num_x_verts + (si-1)); + vindex.push_back(ti * num_x_verts + si); + } + vindex.push_back((ti - 1) * num_x_verts + (num_x_verts-1)); + } + nassertr((int)vindex.size() == num_tstrips * tstrip_length, NULL); + + GeomTristrip *geom = new GeomTristrip; + geom->set_num_prims(num_tstrips); + geom->set_lengths(lengths); + + geom->set_coords(coords, G_PER_VERTEX, vindex); + geom->set_normals(norms, G_PER_VERTEX, vindex); + + // Make it white. + PTA_Colorf colors; + colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); + geom->set_colors(colors, G_OVERALL); + + geom_node->add_geom(geom); } - nassertr((int)vindex.size() == num_tstrips * tstrip_length, NULL); - - GeomTristrip *geom = new GeomTristrip; - geom->set_num_prims(num_tstrips); - geom->set_lengths(lengths); - - geom->set_coords(coords, G_PER_VERTEX, vindex); - geom->set_normals(norms, G_PER_VERTEX, vindex); - - // Make it white. - PTA_Colorf colors; - colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); - geom->set_colors(colors, G_OVERALL); - - // Now create a GeomNode to hold this mesh. - PT(GeomNode) geom_node = new GeomNode(screen_name); - geom_node->add_geom(geom); _stale = true; ++_last_screen; @@ -535,55 +596,106 @@ recompute_geom(Geom *geom, const LMatrix4f &rel_mat) { 0.0f,-0.5f, 0.0f, 0.5f, 0.5f, 1.0f); - PTA_TexCoordf uvs; - PTA_ushort color_index; Lens *lens = _projector_node->get_lens(); nassertv(lens != (Lens *)NULL); const LMatrix3f &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv; - // Iterate through all the vertices in the Geom. - int num_vertices = geom->get_num_vertices(); - Geom::VertexIterator vi = geom->make_vertex_iterator(); + if (geom->is_of_type(qpGeom::get_class_type())) { + qpGeom *qpgeom = DCAST(qpGeom, geom); + // Iterate through all the vertices in the Geom. - for (int i = 0; i < num_vertices; i++) { - const Vertexf &vert = geom->get_next_vertex(vi); - - // For each vertex, project to the film plane. - LPoint2f film(0.0, 0.0); - bool good = lens->project(vert * rel_mat, film); - - // Now the lens gives us coordinates in the range [-1, 1]. - // Rescale these to [0, 1]. - uvs.push_back(film * to_uv); - - // If we have vignette color in effect, color the vertex according - // to whether it fell in front of the lens or not. - if (_vignette_on) { - color_index.push_back(good ? 1 : 0); + CPT(qpGeomVertexData) vdata = qpgeom->get_vertex_data(); + if (!vdata->has_column(_texcoord_name)) { + // We need to add a new column for the new texcoords. + vdata = vdata->replace_column + (_texcoord_name, 2, qpGeomVertexColumn::NT_float32, + qpGeomVertexColumn::C_texcoord, qpGeomUsageHint::UH_dynamic, true); + qpgeom->set_vertex_data(vdata); + } + if (_vignette_on && !vdata->has_column(InternalName::get_color())) { + // We need to add a column for color. + vdata = vdata->replace_column + (InternalName::get_color(), 1, qpGeomVertexColumn::NT_packed_dabc, + qpGeomVertexColumn::C_color, qpGeomUsageHint::UH_dynamic, true); + qpgeom->set_vertex_data(vdata); } - } - // Now set the UV's. If the geom already has indexed UV's, we need - // to make a new index for the geom. - geom->remove_texcoords(_texcoord_name); - if (!geom->are_texcoords_indexed()) { - // Simple case: no indexing needed. - geom->set_texcoords(_texcoord_name, uvs); + qpGeomVertexWriter texcoord(qpgeom->modify_vertex_data(), _texcoord_name); + qpGeomVertexWriter color(qpgeom->modify_vertex_data()); + qpGeomVertexReader vertex(qpgeom->get_vertex_data(), InternalName::get_vertex()); + + if (_vignette_on) { + color.set_column(InternalName::get_color()); + } + + while (!vertex.is_at_end()) { + Vertexf vert = vertex.get_data3f(); + + // For each vertex, project to the film plane. + LPoint2f film(0.0, 0.0); + bool good = lens->project(vert * rel_mat, film); + + // Now the lens gives us coordinates in the range [-1, 1]. + // Rescale these to [0, 1]. + texcoord.set_data2f(film * to_uv); + + // If we have vignette color in effect, color the vertex according + // to whether it fell in front of the lens or not. + if (_vignette_on) { + if (good) { + color.set_data4f(_frame_color); + } else { + color.set_data4f(_vignette_color); + } + } + } } else { - // Harder case: we need to make up an index. But this isn't - // terribly hard. - PTA_ushort index = PTA_ushort::empty_array(num_vertices); + // Iterate through all the vertices in the Geom. + PTA_TexCoordf uvs; + PTA_ushort color_index; + int num_vertices = geom->get_num_vertices(); + Geom::VertexIterator vi = geom->make_vertex_iterator(); + for (int i = 0; i < num_vertices; i++) { - index[i] = i; + const Vertexf &vert = geom->get_next_vertex(vi); + + // For each vertex, project to the film plane. + LPoint2f film(0.0, 0.0); + bool good = lens->project(vert * rel_mat, film); + + // Now the lens gives us coordinates in the range [-1, 1]. + // Rescale these to [0, 1]. + uvs.push_back(film * to_uv); + + // If we have vignette color in effect, color the vertex according + // to whether it fell in front of the lens or not. + if (_vignette_on) { + color_index.push_back(good ? 1 : 0); + } } - geom->set_texcoords(_texcoord_name, uvs, index); - } + // Now set the UV's. If the geom already has indexed UV's, we need + // to make a new index for the geom. + geom->remove_texcoords(_texcoord_name); + if (!geom->are_texcoords_indexed()) { + // Simple case: no indexing needed. + geom->set_texcoords(_texcoord_name, uvs); + + } else { + // Harder case: we need to make up an index. But this isn't + // terribly hard. + PTA_ushort index = PTA_ushort::empty_array(num_vertices); + for (int i = 0; i < num_vertices; i++) { + index[i] = i; + } + geom->set_texcoords(_texcoord_name, uvs, index); + } - if (_vignette_on) { - geom->set_colors(_colors, G_PER_VERTEX, color_index); + if (_vignette_on) { + geom->set_colors(_colors, G_PER_VERTEX, color_index); + } } } @@ -702,29 +814,49 @@ make_mesh_geom_node(const WorkingNodePath &np, const NodePath &camera, //////////////////////////////////////////////////////////////////// PT(Geom) ProjectionScreen:: make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4f &rel_mat) { - Geom *new_geom = geom->make_copy(); - PT(Geom) result = new_geom; + if (geom->is_of_type(qpGeom::get_class_type())) { + PT(qpGeom) new_geom = new qpGeom(*DCAST(qpGeom, geom)); - PTA_Vertexf coords; - GeomBindType bind; - PTA_ushort vindex; + qpGeomVertexRewriter vertex(new_geom->modify_vertex_data(), + InternalName::get_vertex()); + while (!vertex.is_at_end()) { + Vertexf vert = vertex.get_data3f(); + + // Project each vertex into the film plane, but use three + // dimensions so the Z coordinate remains meaningful. + LPoint3f film(0.0f, 0.0f, 0.0f); + lens->project(vert * rel_mat, film); + + vertex.set_data3f(film); + } - new_geom->get_coords(coords, bind, vindex); + return new_geom.p(); + + } else { + Geom *new_geom = geom->make_copy(); + PT(Geom) result = new_geom; - PTA_Vertexf new_coords; - new_coords.reserve(coords.size()); - for (int i = 0; i < (int)coords.size(); i++) { - const Vertexf &vert = coords[i]; + PTA_Vertexf coords; + GeomBindType bind; + PTA_ushort vindex; + + new_geom->get_coords(coords, bind, vindex); + + PTA_Vertexf new_coords; + new_coords.reserve(coords.size()); + for (int i = 0; i < (int)coords.size(); i++) { + const Vertexf &vert = coords[i]; + + // Project each vertex into the film plane, but use three + // dimensions so the Z coordinate remains meaningful. + LPoint3f film(0.0f, 0.0f, 0.0f); + lens->project(vert * rel_mat, film); + + new_coords.push_back(film); + } + + new_geom->set_coords(new_coords, bind, vindex); - // Project each vertex into the film plane, but use three - // dimensions so the Z coordinate remains meaningful. - LPoint3f film(0.0f, 0.0f, 0.0f); - lens->project(vert * rel_mat, film); - - new_coords.push_back(film); + return result; } - - new_geom->set_coords(new_coords, bind, vindex); - - return result; } diff --git a/panda/src/egg/eggVertexPool.cxx b/panda/src/egg/eggVertexPool.cxx index 1896d10594..4572f4176e 100644 --- a/panda/src/egg/eggVertexPool.cxx +++ b/panda/src/egg/eggVertexPool.cxx @@ -250,6 +250,28 @@ has_colors() const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: EggVertexPool::has_nonwhite_colors +// Access: Public +// Description: Returns true if any vertex in the pool has a color +// defined other than white, false if no vertices have +// colors, or if all colors are white. +//////////////////////////////////////////////////////////////////// +bool EggVertexPool:: +has_nonwhite_colors() const { + IndexVertices::const_iterator ivi; + for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) { + EggVertex *vertex = (*ivi).second; + if (vertex->has_color() && + (vertex->get_color() != Colorf(1.0, 1.0, 1.0, 1.0) || + !vertex->_drgbas.empty())) { + return true; + } + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: EggVertexPool::has_uvs // Access: Public diff --git a/panda/src/egg/eggVertexPool.h b/panda/src/egg/eggVertexPool.h index bde4db7376..c468cdf907 100644 --- a/panda/src/egg/eggVertexPool.h +++ b/panda/src/egg/eggVertexPool.h @@ -96,6 +96,7 @@ PUBLISHED: int get_num_dimensions() const; bool has_normals() const; bool has_colors() const; + bool has_nonwhite_colors() const; bool has_uvs() const; void get_uv_names(vector_string &uv_names) const; diff --git a/panda/src/egg2pg/eggBinner.cxx b/panda/src/egg2pg/eggBinner.cxx index b8b7db3aa9..270e253926 100644 --- a/panda/src/egg2pg/eggBinner.cxx +++ b/panda/src/egg2pg/eggBinner.cxx @@ -19,6 +19,8 @@ #include "eggBinner.h" #include "eggRenderState.h" #include "eggPrimitive.h" +#include "eggNurbsSurface.h" +#include "eggNurbsCurve.h" #include "eggSwitchCondition.h" #include "eggGroup.h" #include "dcast.h" @@ -58,7 +60,13 @@ prepare_node(EggNode *node) { //////////////////////////////////////////////////////////////////// int EggBinner:: get_bin_number(const EggNode *node) { - if (node->is_of_type(EggPrimitive::get_class_type())) { + if (node->is_of_type(EggNurbsSurface::get_class_type())) { + return (int)BN_nurbs_surface; + + } else if (node->is_of_type(EggNurbsCurve::get_class_type())) { + return (int)BN_nurbs_curve; + + } else if (node->is_of_type(EggPrimitive::get_class_type())) { return (int)BN_polyset; } else if (node->is_of_type(EggGroup::get_class_type())) { @@ -115,6 +123,11 @@ sorts_less(int bin_number, const EggNode *a, const EggNode *b) { // Group LOD nodes in order by switching center. return (swda._center.compare_to(swdb._center) < 0); } + + case BN_nurbs_surface: + case BN_nurbs_curve: + // Nurbs curves and surfaces are always binned individually. + return a < b; case BN_none: break; diff --git a/panda/src/egg2pg/eggBinner.h b/panda/src/egg2pg/eggBinner.h index 6192661ac9..5af327f251 100644 --- a/panda/src/egg2pg/eggBinner.h +++ b/panda/src/egg2pg/eggBinner.h @@ -43,6 +43,8 @@ public: BN_none = 0, BN_polyset, BN_lod, + BN_nurbs_surface, + BN_nurbs_curve, }; EggBinner(EggLoader &loader); diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index a4675511dd..ebbe885f8b 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -420,7 +420,7 @@ make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent, int nindex = comp_verts_maker.add_normal(egg_prim->get_normal(), - egg_prim->_dnormals, mat); + egg_prim->_dnormals, mat); bprim.set_normal(nindex); } @@ -428,7 +428,7 @@ make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent, if (egg_prim->has_color() && !egg_false_color) { int cindex = comp_verts_maker.add_color(egg_prim->get_color(), - egg_prim->_drgbas); + egg_prim->_drgbas); bprim.set_color(cindex); } @@ -1541,6 +1541,28 @@ make_node(EggBin *egg_bin, PandaNode *parent) { case EggBinner::BN_lod: return make_lod(egg_bin, parent); + case EggBinner::BN_nurbs_surface: + { + nassertr(!egg_bin->empty(), NULL); + EggNode *child = egg_bin->get_first_child(); + EggNurbsSurface *egg_nurbs; + DCAST_INTO_R(egg_nurbs, child, NULL); + const LMatrix4d &mat = egg_nurbs->get_vertex_to_node(); + make_nurbs_surface(egg_nurbs, parent, mat); + } + return NULL; + + case EggBinner::BN_nurbs_curve: + { + nassertr(!egg_bin->empty(), NULL); + EggNode *child = egg_bin->get_first_child(); + EggNurbsCurve *egg_nurbs; + DCAST_INTO_R(egg_nurbs, child, NULL); + const LMatrix4d &mat = egg_nurbs->get_vertex_to_node(); + make_nurbs_curve(egg_nurbs, parent, mat); + } + return NULL; + case EggBinner::BN_none: break; } @@ -1929,7 +1951,8 @@ make_vertex_data(const EggRenderState *render_state, qpGeomVertexColumn::NT_float32, qpGeomVertexColumn::C_vector); } - if (vertex_pool->has_colors()) { + bool has_colors = vertex_pool->has_nonwhite_colors(); + if (has_colors) { array_format->add_column (InternalName::get_color(), 1, qpGeomVertexColumn::NT_packed_dabc, qpGeomVertexColumn::C_color); @@ -1994,7 +2017,7 @@ make_vertex_data(const EggRenderState *render_state, InternalName::get_normal(), 3); } } - if (vertex->has_color()) { + if (has_colors && vertex->has_color()) { EggMorphColorList::const_iterator mci; for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) { slider_names.insert((*mci).get_name()); @@ -2090,7 +2113,7 @@ make_vertex_data(const EggRenderState *render_state, } } - if (vertex->has_color()) { + if (has_colors && vertex->has_color()) { gvw.set_column(InternalName::get_color()); gvw.add_data4f(vertex->get_color()); @@ -2372,13 +2395,8 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags, //egg2pg_cat.debug() << "make_sphere radius: " << radius << "\n"; vi = vertices.begin(); EggVertex *clr_vtx = (*vi); - if (clr_vtx->has_color()) { - color = clr_vtx->get_color(); - } else { - color = Colorf(1.0,1.0,1.0,1.0); - } + color = clr_vtx->get_color(); success = true; - } } return success; diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index c8046b174b..61b87feec1 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -1060,7 +1060,7 @@ load_image_as_model(const Filename &filename) { if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - (string(), qpGeomVertexFormat::get_v3cpt2(), + (string(), qpGeomVertexFormat::get_v3t2(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 9fcf92dee6..f2890083ff 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2324,6 +2324,10 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger, GLP(EnableClientState)(GL_COLOR_ARRAY); } else { GLP(DisableClientState)(GL_COLOR_ARRAY); + + // Since we don't have per-vertex color, the implicit color is + // white. + GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f); } // Now set up each of the active texture coordinate stages--or at diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index 90a325c920..5e6dcc2b5a 100644 --- a/panda/src/gobj/geom.cxx +++ b/panda/src/gobj/geom.cxx @@ -329,6 +329,17 @@ transform_vertices(const LMatrix4f &mat) { set_coords(new_coords, index); } +//////////////////////////////////////////////////////////////////// +// Function: Geom::check_valid +// Access: Published +// Description: This is only here temporarily; it has meaning at the +// qpGeom level. +//////////////////////////////////////////////////////////////////// +bool Geom:: +check_valid() const { + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Geom::set_coords // Access: Published diff --git a/panda/src/gobj/geom.h b/panda/src/gobj/geom.h index 95c4bd8983..a972e674f1 100644 --- a/panda/src/gobj/geom.h +++ b/panda/src/gobj/geom.h @@ -136,6 +136,7 @@ public: PUBLISHED: virtual void transform_vertices(const LMatrix4f &mat); + virtual bool check_valid() const; void set_coords(const PTA_Vertexf &coords, const PTA_ushort &vindex = PTA_ushort()); diff --git a/panda/src/gobj/lens.cxx b/panda/src/gobj/lens.cxx index adb9edc8ab..fd42d66198 100644 --- a/panda/src/gobj/lens.cxx +++ b/panda/src/gobj/lens.cxx @@ -21,6 +21,9 @@ #include "compose_matrix.h" #include "look_at.h" #include "geomLinestrip.h" +#include "qpgeom.h" +#include "qpgeomLinestrips.h" +#include "qpgeomVertexWriter.h" #include "boundingHexahedron.h" #include "indent.h" #include "config_gobj.h" @@ -67,8 +70,7 @@ operator = (const Lens ©) { _user_flags = copy._user_flags; _comp_flags = 0; - // We don't copy the _geom_coords array. That's unique to each - // Lens. + // We don't copy the _geom_data. That's unique to each Lens. } //////////////////////////////////////////////////////////////////// @@ -873,74 +875,137 @@ PT(Geom) Lens:: make_geometry() { // The default behavior for make_geometry() will be to draw a // hexahedron around the eight vertices of the frustum. If the lens - // is non-linear, the hexahedron will be curved; in this case, we'll + // is non-linear, the hexahedron will be curved; in that case, we'll // subdivide the lines into several segments to get an approximation // of the curve. - // First, define all the points we'll use in this Geom. That's one - // point at each corner of the near and far planes (and possibly - // more points along the edges). - int num_segments = define_geom_coords(); - if (num_segments == 0) { - // Can't do a frustum. - _geom_coords.clear(); - return (Geom *)NULL; + if (use_qpgeom) { + // First, define all the points we'll use in this Geom. That's one + // point at each corner of the near and far planes (and possibly + // more points along the edges). + int num_segments = define_geom_data(); + if (num_segments == 0) { + // Can't do a frustum. + _geom_data.clear(); + return (Geom *)NULL; + } + + // Now string together the line segments. + PT(qpGeomLinestrips) line = new qpGeomLinestrips(qpGeomUsageHint::UH_static); + + // Draw a frame around the near plane. + int i, si; + for (i = 0; i < 4; ++i) { + for (si = 0; si < num_segments; ++si) { + line->add_vertex(i * 2 + si * (4 * 2) + 0); + } + } + line->add_vertex(0); + line->close_primitive(); + + // Draw a frame around the far plane. + for (i = 0; i < 4; ++i) { + for (si = 0; si < num_segments; ++si) { + line->add_vertex(i * 2 + si * (4 * 2) + 1); + } + } + line->add_vertex(1); + line->close_primitive(); + + // Draw connecting lines at the corners. + line->add_vertex(0 * 2 + 0); + line->add_vertex(0 * 2 + 1); + line->close_primitive(); + + line->add_vertex(1 * 2 + 0); + line->add_vertex(1 * 2 + 1); + line->close_primitive(); + + line->add_vertex(2 * 2 + 0); + line->add_vertex(2 * 2 + 1); + line->close_primitive(); + + line->add_vertex(3 * 2 + 0); + line->add_vertex(3 * 2 + 1); + line->close_primitive(); + + // And one more line for the viewing axis. + line->add_vertex(num_segments * (4 * 2) + 0); + line->add_vertex(num_segments * (4 * 2) + 1); + line->close_primitive(); + + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(_geom_data); + geom->add_primitive(line); + + return geom.p(); + + } else { + // First, define all the points we'll use in this Geom. That's one + // point at each corner of the near and far planes (and possibly + // more points along the edges). + int num_segments = define_geom_coords(); + if (num_segments == 0) { + // Can't do a frustum. + _geom_coords.clear(); + return (Geom *)NULL; + } + + // Now string together the line segments. + PTA_ushort vindex; + PTA_int lengths; + PTA_Colorf colors; + + int num_points = num_segments * 4; + + // Draw a frame around the near plane. + int i; + for (i = 0; i < num_points; i++) { + vindex.push_back(i * num_segments * 2); + } + vindex.push_back(0); + lengths.push_back(num_points + 1); + + // Draw a frame around the far plane. + for (i = 0; i < num_points; i++) { + vindex.push_back(i * num_segments * 2 + 1); + } + vindex.push_back(1); + lengths.push_back(num_points + 1); + + // Draw connecting lines at the corners. + vindex.push_back(0); + vindex.push_back(1); + lengths.push_back(2); + + vindex.push_back(num_segments * 2 + 0); + vindex.push_back(num_segments * 2+ 1); + lengths.push_back(2); + + vindex.push_back(num_segments * 4 + 0); + vindex.push_back(num_segments * 4 + 1); + lengths.push_back(2); + + vindex.push_back(num_segments * 6 + 0); + vindex.push_back(num_segments * 6 + 1); + lengths.push_back(2); + + // And one more line for the viewing axis. + vindex.push_back(num_segments * 8 + 0); + vindex.push_back(num_segments * 8 + 1); + lengths.push_back(2); + + // We just specify overall color. + colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); + + GeomLinestrip *gline = new GeomLinestrip; + gline->set_coords(_geom_coords, vindex); + gline->set_colors(colors, G_OVERALL); + gline->set_lengths(lengths); + gline->set_num_prims(lengths.size()); + + return gline; } - - // Now string together the line segments. - PTA_ushort vindex; - PTA_int lengths; - PTA_Colorf colors; - - int num_points = num_segments * 4; - - // Draw a frame around the near plane. - int i; - for (i = 0; i < num_points; i++) { - vindex.push_back(i * num_segments * 2); - } - vindex.push_back(0); - lengths.push_back(num_points + 1); - - // Draw a frame around the far plane. - for (i = 0; i < num_points; i++) { - vindex.push_back(i * num_segments * 2 + 1); - } - vindex.push_back(1); - lengths.push_back(num_points + 1); - - // Draw connecting lines at the corners. - vindex.push_back(0); - vindex.push_back(1); - lengths.push_back(2); - - vindex.push_back(num_segments * 2 + 0); - vindex.push_back(num_segments * 2+ 1); - lengths.push_back(2); - - vindex.push_back(num_segments * 4 + 0); - vindex.push_back(num_segments * 4 + 1); - lengths.push_back(2); - - vindex.push_back(num_segments * 6 + 0); - vindex.push_back(num_segments * 6 + 1); - lengths.push_back(2); - - // And one more line for the viewing axis. - vindex.push_back(num_segments * 8 + 0); - vindex.push_back(num_segments * 8 + 1); - lengths.push_back(2); - - // We just specify overall color. - colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); - - GeomLinestrip *gline = new GeomLinestrip; - gline->set_coords(_geom_coords, vindex); - gline->set_colors(colors, G_OVERALL); - gline->set_lengths(lengths); - gline->set_num_prims(lengths.size()); - - return gline; } //////////////////////////////////////////////////////////////////// @@ -1070,6 +1135,18 @@ throw_change_event() { define_geom_coords(); } } + if (!_geom_data.is_null()) { + if (_geom_data->get_ref_count() == 1) { + // No one's using the data any more (there are no references to + // it other than this one), so don't bother to recompute it; + // just release it. + _geom_data.clear(); + } else { + // Someone still has a handle to the data, so recompute it for + // them. + define_geom_data(); + } + } } //////////////////////////////////////////////////////////////////// @@ -1659,6 +1736,83 @@ define_geom_coords() { return num_segments; } +//////////////////////////////////////////////////////////////////// +// Function: Lens::define_geom_data +// Access: Private +// Description: Adjusts (or defines for the first time) all the +// vertices in the _geom_data to match the properties of +// the lens. This will update the visual representation +// of the lens's frustum to match the changing +// parameters. Returns the number of line segments per +// edge. +//////////////////////////////////////////////////////////////////// +int Lens:: +define_geom_data() { + int num_segments = 1; + if (!is_linear()) { + num_segments = 10; + } + + if (_geom_data == (qpGeomVertexData *)NULL) { + _geom_data = new qpGeomVertexData + ("lens", qpGeomVertexFormat::get_v3(), + qpGeomUsageHint::UH_dynamic); + } + + qpGeomVertexWriter vertex(_geom_data, InternalName::get_vertex()); + LPoint3f near_point, far_point; + for (int si = 0; si < num_segments; si++) { + float t = 2.0f * (float)si / (float)num_segments; + + // Upper left, top edge. + LPoint2f p1(-1.0f + t, 1.0f); + if (!extrude(p1, near_point, far_point)) { + // Hey, this point is off the lens! Can't do a frustum. + return 0; + } + vertex.add_data3f(near_point); + vertex.add_data3f(far_point); + + // Upper right, right edge. + LPoint2f p2(1.0f, 1.0f - t); + if (!extrude(p2, near_point, far_point)) { + // Hey, this point is off the lens! Can't do a frustum. + return 0; + } + vertex.add_data3f(near_point); + vertex.add_data3f(far_point); + + // Lower right, bottom edge. + LPoint2f p3(1.0f - t, -1.0f); + if (!extrude(p3, near_point, far_point)) { + // Hey, this point is off the lens! Can't do a frustum. + return 0; + } + vertex.add_data3f(near_point); + vertex.add_data3f(far_point); + + // Lower left, left edge. + LPoint2f p4(-1.0f, -1.0f + t); + if (!extrude(p4, near_point, far_point)) { + // Hey, this point is off the lens! Can't do a frustum. + return 0; + } + vertex.add_data3f(near_point); + vertex.add_data3f(far_point); + } + + // Finally, add one more pair for the viewing axis. + LPoint3f near_axis = LPoint3f::origin(_cs) + LVector3f::forward(_cs) * _near_distance; + LPoint3f far_axis = LPoint3f::origin(_cs) + LVector3f::forward(_cs) * _far_distance; + const LMatrix4f &lens_mat = get_lens_mat(); + near_axis = near_axis * lens_mat; + far_axis = far_axis * lens_mat; + vertex.add_data3f(near_axis); + vertex.add_data3f(far_axis); + + return num_segments; +} + //////////////////////////////////////////////////////////////////// // Function: Lens::build_shear_mat // Access: Private, Static diff --git a/panda/src/gobj/lens.h b/panda/src/gobj/lens.h index 29816c7f2f..a44a50d9ee 100644 --- a/panda/src/gobj/lens.h +++ b/panda/src/gobj/lens.h @@ -25,6 +25,8 @@ #include "luse.h" #include "geom.h" #include "updateSeq.h" +#include "qpgeomVertexData.h" +#include "pointerTo.h" class BoundingVolume; @@ -182,6 +184,7 @@ protected: private: static void resequence_fov_triad(char &newest, char &older_a, char &older_b); int define_geom_coords(); + int define_geom_data(); static void build_shear_mat(LMatrix4f &shear_mat, const LPoint3f &cul, const LPoint3f &cur, const LPoint3f &cll, const LPoint3f &clr); @@ -252,6 +255,7 @@ protected: char _focal_length_seq, _fov_seq, _film_size_seq; PTA_Vertexf _geom_coords; + PT(qpGeomVertexData) _geom_data; public: virtual void write_datagram(BamWriter *manager, Datagram &dg); diff --git a/panda/src/gobj/qpgeom.I b/panda/src/gobj/qpgeom.I index a30cd65474..0746a75c65 100644 --- a/panda/src/gobj/qpgeom.I +++ b/panda/src/gobj/qpgeom.I @@ -107,40 +107,6 @@ modify_primitive(int i) { return cdata->_primitives[i]; } -//////////////////////////////////////////////////////////////////// -// Function: qpGeom::set_primitive -// Access: Published -// Description: Replaces the ith GeomPrimitive object stored within -// the Geom with the new object. -//////////////////////////////////////////////////////////////////// -INLINE void qpGeom:: -set_primitive(int i, const qpGeomPrimitive *primitive) { - clear_cache(); - CDWriter cdata(_cycler); - nassertv(i >= 0 && i < (int)cdata->_primitives.size()); - - // All primitives within a particular Geom must have the same - // primitive type. - nassertv(cdata->_primitive_type == qpGeomPrimitive::PT_none || - cdata->_primitive_type == primitive->get_primitive_type()); - if (cdata->_got_usage_hint && - cdata->_primitives[i]->get_usage_hint() != primitive->get_usage_hint()) { - if (cdata->_primitives[i]->get_usage_hint() < primitive->get_usage_hint()) { - // If we're reducing the usage hint, we might also be reducing - // the minimum usage hit. - cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint()); - } else { // (cdata->_primitives[i]->get_usage_hint() > primitive->get_usage_hint()) - // If we're increasing it, we might have to rederive the minimum. - if (cdata->_usage_hint == cdata->_primitives[i]->get_usage_hint()) { - cdata->_got_usage_hint = false; - } - } - } - cdata->_primitives[i] = (qpGeomPrimitive *)primitive; - cdata->_primitive_type = primitive->get_primitive_type(); - cdata->_modified = qpGeom::get_next_modified(); -} - //////////////////////////////////////////////////////////////////// // Function: qpGeom::get_modified // Access: Published diff --git a/panda/src/gobj/qpgeom.cxx b/panda/src/gobj/qpgeom.cxx index 4664d6edc7..f399675230 100644 --- a/panda/src/gobj/qpgeom.cxx +++ b/panda/src/gobj/qpgeom.cxx @@ -133,12 +133,49 @@ modify_vertex_data() { //////////////////////////////////////////////////////////////////// void qpGeom:: set_vertex_data(const qpGeomVertexData *data) { + nassertv(check_will_be_valid(data)); clear_cache(); CDWriter cdata(_cycler); cdata->_data = (qpGeomVertexData *)data; mark_bound_stale(); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::set_primitive +// Access: Published +// Description: Replaces the ith GeomPrimitive object stored within +// the Geom with the new object. +//////////////////////////////////////////////////////////////////// +void qpGeom:: +set_primitive(int i, const qpGeomPrimitive *primitive) { + clear_cache(); + CDWriter cdata(_cycler); + nassertv(i >= 0 && i < (int)cdata->_primitives.size()); + nassertv(primitive->check_valid(cdata->_data)); + + // All primitives within a particular Geom must have the same + // fundamental primitive type (triangles, points, or lines). + nassertv(cdata->_primitive_type == qpGeomPrimitive::PT_none || + cdata->_primitive_type == primitive->get_primitive_type()); + + if (cdata->_got_usage_hint && + cdata->_primitives[i]->get_usage_hint() != primitive->get_usage_hint()) { + if (cdata->_primitives[i]->get_usage_hint() < primitive->get_usage_hint()) { + // If we're reducing the usage hint, we might also be reducing + // the minimum usage hit. + cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint()); + } else { // (cdata->_primitives[i]->get_usage_hint() > primitive->get_usage_hint()) + // If we're increasing it, we might have to rederive the minimum. + if (cdata->_usage_hint == cdata->_primitives[i]->get_usage_hint()) { + cdata->_got_usage_hint = false; + } + } + } + cdata->_primitives[i] = (qpGeomPrimitive *)primitive; + cdata->_primitive_type = primitive->get_primitive_type(); + cdata->_modified = qpGeom::get_next_modified(); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeom::add_primitive // Access: Published @@ -151,8 +188,11 @@ void qpGeom:: add_primitive(const qpGeomPrimitive *primitive) { clear_cache(); CDWriter cdata(_cycler); + + nassertv(primitive->check_valid(cdata->_data)); + // All primitives within a particular Geom must have the same - // primitive type. + // fundamental primitive type (triangles, points, or lines). nassertv(cdata->_primitive_type == qpGeomPrimitive::PT_none || cdata->_primitive_type == primitive->get_primitive_type()); @@ -340,6 +380,30 @@ munge_geom(const qpGeomMunger *munger, } } +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::check_valid +// Access: Published +// Description: Verifies that the all of the primitives within the +// geom reference vertices that actually exist within +// the geom's GeomVertexData. Returns true if the geom +// appears to be valid, false otherwise. +//////////////////////////////////////////////////////////////////// +bool qpGeom:: +check_valid() const { + CDReader cdata(_cycler); + + Primitives::const_iterator pi; + for (pi = cdata->_primitives.begin(); + pi != cdata->_primitives.end(); + ++pi) { + if (!(*pi)->check_valid(cdata->_data)) { + return false; + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeom::output // Access: Published @@ -523,6 +587,32 @@ recompute_bound() { return bound; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeom::check_will_be_valid +// Access: Private +// Description: Verifies that the all of the primitives within the +// geom reference vertices that actually exist within +// the indicated GeomVertexData (presumably in +// preparation for assigning the geom to use this data). +// Returns true if the data appears to be valid, false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool qpGeom:: +check_will_be_valid(const qpGeomVertexData *vertex_data) const { + CDReader cdata(_cycler); + + Primitives::const_iterator pi; + for (pi = cdata->_primitives.begin(); + pi != cdata->_primitives.end(); + ++pi) { + if (!(*pi)->check_valid(vertex_data)) { + return false; + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeom::reset_usage_hint // Access: Private diff --git a/panda/src/gobj/qpgeom.h b/panda/src/gobj/qpgeom.h index 40635baf20..3576cb6155 100644 --- a/panda/src/gobj/qpgeom.h +++ b/panda/src/gobj/qpgeom.h @@ -76,7 +76,7 @@ PUBLISHED: INLINE int get_num_primitives() const; INLINE const qpGeomPrimitive *get_primitive(int i) const; INLINE qpGeomPrimitive *modify_primitive(int i); - INLINE void set_primitive(int i, const qpGeomPrimitive *primitive); + void set_primitive(int i, const qpGeomPrimitive *primitive); void add_primitive(const qpGeomPrimitive *primitive); void remove_primitive(int i); void clear_primitives(); @@ -84,11 +84,15 @@ PUBLISHED: int get_num_bytes() const; INLINE UpdateSeq get_modified() const; + // Temporarily virtual. virtual void transform_vertices(const LMatrix4f &mat); void munge_geom(const qpGeomMunger *munger, CPT(qpGeom) &result, CPT(qpGeomVertexData) &data) const; + // Temporarily virtual. + virtual bool check_valid() const; + void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; @@ -109,6 +113,9 @@ public: protected: virtual BoundingVolume *recompute_bound(); +private: + bool check_will_be_valid(const qpGeomVertexData *vertex_data) const; + private: typedef pvector Primitives; diff --git a/panda/src/gobj/qpgeomLines.cxx b/panda/src/gobj/qpgeomLines.cxx index 8b6457b734..0666b2cd67 100644 --- a/panda/src/gobj/qpgeomLines.cxx +++ b/panda/src/gobj/qpgeomLines.cxx @@ -94,6 +94,17 @@ get_num_vertices_per_primitive() const { return 2; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomLines::get_min_num_vertices_per_primitive +// Access: Public, Virtual +// Description: Returns the minimum number of vertices that must be +// added before close_primitive() may legally be called. +//////////////////////////////////////////////////////////////////// +int qpGeomLines:: +get_min_num_vertices_per_primitive() const { + return 2; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomLines::draw // Access: Public, Virtual diff --git a/panda/src/gobj/qpgeomLines.h b/panda/src/gobj/qpgeomLines.h index 7fd9c031be..7ab7ac37eb 100644 --- a/panda/src/gobj/qpgeomLines.h +++ b/panda/src/gobj/qpgeomLines.h @@ -39,6 +39,7 @@ public: virtual PrimitiveType get_primitive_type() const; virtual int get_num_vertices_per_primitive() const; + virtual int get_min_num_vertices_per_primitive() const; public: virtual void draw(GraphicsStateGuardianBase *gsg) const; diff --git a/panda/src/gobj/qpgeomLinestrips.cxx b/panda/src/gobj/qpgeomLinestrips.cxx index 6c45b92b88..e256243709 100644 --- a/panda/src/gobj/qpgeomLinestrips.cxx +++ b/panda/src/gobj/qpgeomLinestrips.cxx @@ -79,6 +79,17 @@ get_primitive_type() const { return PT_lines; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomLinestrips::get_min_num_vertices_per_primitive +// Access: Public, Virtual +// Description: Returns the minimum number of vertices that must be +// added before close_primitive() may legally be called. +//////////////////////////////////////////////////////////////////// +int qpGeomLinestrips:: +get_min_num_vertices_per_primitive() const { + return 2; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomLinestrips::draw // Access: Public, Virtual diff --git a/panda/src/gobj/qpgeomLinestrips.h b/panda/src/gobj/qpgeomLinestrips.h index e42e48c162..1ddf612a76 100644 --- a/panda/src/gobj/qpgeomLinestrips.h +++ b/panda/src/gobj/qpgeomLinestrips.h @@ -38,6 +38,8 @@ public: virtual PT(qpGeomPrimitive) make_copy() const; virtual PrimitiveType get_primitive_type() const; + virtual int get_min_num_vertices_per_primitive() const; + public: virtual void draw(GraphicsStateGuardianBase *gsg) const; diff --git a/panda/src/gobj/qpgeomPoints.cxx b/panda/src/gobj/qpgeomPoints.cxx index 97bd339a46..c4b220a409 100644 --- a/panda/src/gobj/qpgeomPoints.cxx +++ b/panda/src/gobj/qpgeomPoints.cxx @@ -94,6 +94,17 @@ get_num_vertices_per_primitive() const { return 1; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPoints::get_min_num_vertices_per_primitive +// Access: Public, Virtual +// Description: Returns the minimum number of vertices that must be +// added before close_primitive() may legally be called. +//////////////////////////////////////////////////////////////////// +int qpGeomPoints:: +get_min_num_vertices_per_primitive() const { + return 1; +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomPoints::draw // Access: Public, Virtual diff --git a/panda/src/gobj/qpgeomPoints.h b/panda/src/gobj/qpgeomPoints.h index 6fe7fd7739..8453721630 100644 --- a/panda/src/gobj/qpgeomPoints.h +++ b/panda/src/gobj/qpgeomPoints.h @@ -39,6 +39,7 @@ public: virtual PrimitiveType get_primitive_type() const; virtual int get_num_vertices_per_primitive() const; + virtual int get_min_num_vertices_per_primitive() const; public: virtual void draw(GraphicsStateGuardianBase *gsg) const; diff --git a/panda/src/gobj/qpgeomPrimitive.cxx b/panda/src/gobj/qpgeomPrimitive.cxx index 64530e0760..d77223727a 100644 --- a/panda/src/gobj/qpgeomPrimitive.cxx +++ b/panda/src/gobj/qpgeomPrimitive.cxx @@ -462,6 +462,19 @@ get_num_bytes() const { cdata->_ends.size() * sizeof(int) + sizeof(qpGeomPrimitive); } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomPrimitive::check_valid +// Access: Published +// Description: Verifies that the primitive only references vertices +// that actually exist within the indicated +// GeomVertexData. Returns true if the primitive +// appears to be valid, false otherwise. +//////////////////////////////////////////////////////////////////// +bool qpGeomPrimitive:: +check_valid(const qpGeomVertexData *vertex_data) const { + return get_max_vertex() < vertex_data->get_num_vertices(); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomPrimitive::output // Access: Published, Virtual diff --git a/panda/src/gobj/qpgeomPrimitive.h b/panda/src/gobj/qpgeomPrimitive.h index f9ec63fc95..037ae7e23a 100644 --- a/panda/src/gobj/qpgeomPrimitive.h +++ b/panda/src/gobj/qpgeomPrimitive.h @@ -139,6 +139,8 @@ PUBLISHED: INLINE int get_data_size_bytes() const; INLINE UpdateSeq get_modified() const; + bool check_valid(const qpGeomVertexData *vertex_data) const; + virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level) const; diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx index 57c06b033d..67dd6e95fc 100644 --- a/panda/src/gobj/qpgeomVertexData.cxx +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -590,6 +590,9 @@ convert_to(const qpGeomVertexFormat *new_format) const { // Access: Published // Description: Returns a new GeomVertexData object with the color // table modified in-place to apply the indicated scale. +// +// If the vertex data does not include a color column, a +// new one will not be added. //////////////////////////////////////////////////////////////////// CPT(qpGeomVertexData) qpGeomVertexData:: scale_color(const LVecBase4f &color_scale) const { @@ -665,6 +668,9 @@ scale_color(const LVecBase4f &color_scale, int num_components, // Access: Published // Description: Returns a new GeomVertexData object with the color // data modified in-place with the new value. +// +// If the vertex data does not include a color column, a +// new one will not be added. //////////////////////////////////////////////////////////////////// CPT(qpGeomVertexData) qpGeomVertexData:: set_color(const Colorf &color) const { diff --git a/panda/src/grutil/cardMaker.cxx b/panda/src/grutil/cardMaker.cxx index 09a336778f..60b5211c93 100644 --- a/panda/src/grutil/cardMaker.cxx +++ b/panda/src/grutil/cardMaker.cxx @@ -22,6 +22,9 @@ #include "transformState.h" #include "colorAttrib.h" #include "sceneGraphReducer.h" +#include "qpgeom.h" +#include "qpgeomTristrips.h" +#include "qpgeomVertexWriter.h" //////////////////////////////////////////////////////////////////// @@ -55,39 +58,82 @@ generate() { } PT(GeomNode) gnode = new GeomNode(get_name()); - Geom *geom = new GeomTristrip; - gnode->add_geom(geom); float left = _frame[0]; float right = _frame[1]; float bottom = _frame[2]; float top = _frame[3]; - PTA_int lengths=PTA_int::empty_array(0); - lengths.push_back(4); + if (use_qpgeom) { + CPT(qpGeomVertexFormat) format; + if (_has_uvs) { + format = qpGeomVertexFormat::get_v3cpt2(); + } else { + format = qpGeomVertexFormat::get_v3cp(); + } - PTA_Vertexf verts; - verts.push_back(Vertexf::rfu(left, 0.0f, top)); - verts.push_back(Vertexf::rfu(left, 0.0f, bottom)); - verts.push_back(Vertexf::rfu(right, 0.0f, top)); - verts.push_back(Vertexf::rfu(right, 0.0f, bottom)); + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("card", format, qpGeomUsageHint::UH_static); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + qpGeomVertexWriter color(vdata, InternalName::get_color()); - geom->set_num_prims(1); - geom->set_lengths(lengths); + vertex.add_data3f(Vertexf::rfu(left, 0.0f, top)); + vertex.add_data3f(Vertexf::rfu(left, 0.0f, bottom)); + vertex.add_data3f(Vertexf::rfu(right, 0.0f, top)); + vertex.add_data3f(Vertexf::rfu(right, 0.0f, bottom)); - geom->set_coords(verts); + color.add_data4f(_color); + color.add_data4f(_color); + color.add_data4f(_color); + color.add_data4f(_color); - PTA_Colorf colors; - colors.push_back(_color); - geom->set_colors(colors, G_OVERALL); + if (_has_uvs) { + qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); + texcoord.add_data2f(_ll[0], _ur[1]); + texcoord.add_data2f(_ll[0], _ll[1]); + texcoord.add_data2f(_ur[0], _ur[1]); + texcoord.add_data2f(_ur[0], _ll[1]); + } - if (_has_uvs) { - PTA_TexCoordf uvs; - uvs.push_back(TexCoordf(_ll[0], _ur[1])); - uvs.push_back(TexCoordf(_ll[0], _ll[1])); - uvs.push_back(TexCoordf(_ur[0], _ur[1])); - uvs.push_back(TexCoordf(_ur[0], _ll[1])); - geom->set_texcoords(uvs, G_PER_VERTEX); + PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static); + strip->add_next_vertices(4); + + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(strip); + + gnode->add_geom(geom); + + } else { + Geom *geom = new GeomTristrip; + gnode->add_geom(geom); + + PTA_int lengths = PTA_int::empty_array(0); + lengths.push_back(4); + + PTA_Vertexf verts; + verts.push_back(Vertexf::rfu(left, 0.0f, top)); + verts.push_back(Vertexf::rfu(left, 0.0f, bottom)); + verts.push_back(Vertexf::rfu(right, 0.0f, top)); + verts.push_back(Vertexf::rfu(right, 0.0f, bottom)); + + geom->set_num_prims(1); + geom->set_lengths(lengths); + + geom->set_coords(verts); + + PTA_Colorf colors; + colors.push_back(_color); + geom->set_colors(colors, G_OVERALL); + + if (_has_uvs) { + PTA_TexCoordf uvs; + uvs.push_back(TexCoordf(_ll[0], _ur[1])); + uvs.push_back(TexCoordf(_ll[0], _ll[1])); + uvs.push_back(TexCoordf(_ur[0], _ur[1])); + uvs.push_back(TexCoordf(_ur[0], _ll[1])); + geom->set_texcoords(uvs, G_PER_VERTEX); + } } return gnode.p(); diff --git a/panda/src/grutil/lineSegs.I b/panda/src/grutil/lineSegs.I index 59cf02b811..a03a577a92 100644 --- a/panda/src/grutil/lineSegs.I +++ b/panda/src/grutil/lineSegs.I @@ -133,15 +133,14 @@ draw_to(float x, float y, float z) { // created with the color and thickness established by // calls to set_color() and set_thick(). // -// If frame_accurate is true, the line segments will be -// created as a frame-accurate index, so that later -// calls to set_vertex or set_vertex_color will be -// visually correct. +// If dynamic is true, the line segments will be created +// with the dynamic Geom setting, optimizing them for +// runtime vertex animation. //////////////////////////////////////////////////////////////////// INLINE GeomNode *LineSegs:: -create(bool frame_accurate) { +create(bool dynamic) { GeomNode *gnode = new GeomNode(get_name()); - return create(gnode, frame_accurate); + return create(gnode, dynamic); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/grutil/lineSegs.cxx b/panda/src/grutil/lineSegs.cxx index 9b9adf1ce1..ceedff6302 100644 --- a/panda/src/grutil/lineSegs.cxx +++ b/panda/src/grutil/lineSegs.cxx @@ -19,6 +19,10 @@ #include "lineSegs.h" #include "renderState.h" #include "renderModeAttrib.h" +#include "qpgeom.h" +#include "qpgeomLinestrips.h" +#include "qpgeomPoints.h" +#include "qpgeomVertexWriter.h" //////////////////////////////////////////////////////////////////// // Function: LineSegs::Constructor @@ -140,86 +144,141 @@ get_current_position() { // thickness established by calls to set_color() and // set_thick(). // -// If frame_accurate is true, the line segments will be -// created as a frame-accurate index, so that later -// calls to set_vertex or set_vertex_color will be -// visually correct. +// If dynamic is true, the line segments will be created +// with the dynamic Geom setting, optimizing them for +// runtime vertex animation. //////////////////////////////////////////////////////////////////// GeomNode *LineSegs:: -create(GeomNode *previous, bool) { +create(GeomNode *previous, bool dynamic) { if (!_list.empty()) { _created_verts.clear(); _created_colors.clear(); - - // One array each for the indices into these arrays for points - // and lines, and one for our line-segment lengths array. - PTA_ushort point_index; - PTA_ushort line_index; - PTA_int lengths; - - // Now fill up the arrays. - int v = 0; - LineList::const_iterator ll; - SegmentList::const_iterator sl; - - for (ll = _list.begin(); ll != _list.end(); ll++) { - const SegmentList &segs = (*ll); - - if (segs.size() < 2) { - point_index.push_back(v); - } else { - lengths.push_back(segs.size()); - } - - for (sl = segs.begin(); sl != segs.end(); sl++) { - if (segs.size() >= 2) { - line_index.push_back(v); - } - _created_verts.push_back((*sl)._point); - _created_colors.push_back((*sl)._color); - v++; - nassertr(v == (int)_created_verts.size(), previous); - } - } - + _created_data = NULL; + CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _thick); CPT(RenderState) state = RenderState::make(thick); - // Now create the lines. - if (line_index.size() > 0) { - // Create a new Geom and add the line segments. - Geom *geom; - if (line_index.size() <= 2) { - // Here's a special case: just one line segment. - GeomLine *geom_line = new GeomLine; - geom_line->set_num_prims(1); - geom = geom_line; + if (use_qpgeom) { + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("lineSegs", qpGeomVertexFormat::get_v3cp(), + dynamic ? qpGeomUsageHint::UH_dynamic : qpGeomUsageHint::UH_static); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + qpGeomVertexWriter color(vdata, InternalName::get_color()); - } else { - // The more normal case: multiple line segments, connected - // end-to-end like a series of linestrips. - GeomLinestrip *geom_linestrip = new GeomLinestrip; - geom_linestrip->set_num_prims(lengths.size()); - geom_linestrip->set_lengths(lengths); - geom = geom_linestrip; + PT(qpGeomLinestrips) lines = new qpGeomLinestrips(qpGeomUsageHint::UH_static); + PT(qpGeomPoints) points = new qpGeomPoints(qpGeomUsageHint::UH_static); + + int v = 0; + LineList::const_iterator ll; + SegmentList::const_iterator sl; + + for (ll = _list.begin(); ll != _list.end(); ll++) { + const SegmentList &segs = (*ll); + + if (segs.size() < 2) { + // A segment of length 1 is just a point. + for (sl = segs.begin(); sl != segs.end(); sl++) { + points->add_vertex(v); + vertex.add_data3f((*sl)._point); + color.add_data4f((*sl)._color); + v++; + } + points->close_primitive(); + + } else { + // A segment of length 2 or more is a line segment or + // segments. + for (sl = segs.begin(); sl != segs.end(); sl++) { + lines->add_vertex(v); + vertex.add_data3f((*sl)._point); + color.add_data4f((*sl)._color); + v++; + } + lines->close_primitive(); + } } - geom->set_colors(_created_colors, G_PER_VERTEX, line_index); - geom->set_coords(_created_verts, line_index); + if (lines->get_num_vertices() != 0) { + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(lines); + previous->add_geom(geom, state); + } + if (points->get_num_vertices() != 0) { + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(points); + previous->add_geom(geom, state); + } - previous->add_geom(geom, state); - } + } else { + // One array each for the indices into these arrays for points + // and lines, and one for our line-segment lengths array. + PTA_ushort point_index; + PTA_ushort line_index; + PTA_int lengths; + + // Now fill up the arrays. + int v = 0; + LineList::const_iterator ll; + SegmentList::const_iterator sl; + + for (ll = _list.begin(); ll != _list.end(); ll++) { + const SegmentList &segs = (*ll); + + if (segs.size() < 2) { + point_index.push_back(v); + } else { + lengths.push_back(segs.size()); + } + + for (sl = segs.begin(); sl != segs.end(); sl++) { + if (segs.size() >= 2) { + line_index.push_back(v); + } + _created_verts.push_back((*sl)._point); + _created_colors.push_back((*sl)._color); + v++; + nassertr(v == (int)_created_verts.size(), previous); + } + } + + // Now create the lines. + if (line_index.size() > 0) { + // Create a new Geom and add the line segments. + Geom *geom; + if (line_index.size() <= 2) { + // Here's a special case: just one line segment. + GeomLine *geom_line = new GeomLine; + geom_line->set_num_prims(1); + geom = geom_line; + + } else { + // The more normal case: multiple line segments, connected + // end-to-end like a series of linestrips. + GeomLinestrip *geom_linestrip = new GeomLinestrip; + geom_linestrip->set_num_prims(lengths.size()); + geom_linestrip->set_lengths(lengths); + geom = geom_linestrip; + } + + geom->set_colors(_created_colors, G_PER_VERTEX, line_index); + geom->set_coords(_created_verts, line_index); + + previous->add_geom(geom, state); + } - // And now create the points. - if (point_index.size() > 0) { - // Create a new Geom and add the points. - GeomPoint *geom = new GeomPoint; - - geom->set_num_prims(point_index.size()); - geom->set_colors(_created_colors, G_PER_VERTEX, point_index); - geom->set_coords(_created_verts, point_index); - - previous->add_geom(geom, state); + // And now create the points. + if (point_index.size() > 0) { + // Create a new Geom and add the points. + GeomPoint *geom = new GeomPoint; + + geom->set_num_prims(point_index.size()); + geom->set_colors(_created_colors, G_PER_VERTEX, point_index); + geom->set_coords(_created_verts, point_index); + + previous->add_geom(geom, state); + } } // And reset for next time. diff --git a/panda/src/grutil/lineSegs.h b/panda/src/grutil/lineSegs.h index 2f0b3b1b05..d474eae3be 100644 --- a/panda/src/grutil/lineSegs.h +++ b/panda/src/grutil/lineSegs.h @@ -27,6 +27,7 @@ #include "geomLine.h" #include "geomLinestrip.h" #include "geomNode.h" +#include "qpgeomVertexData.h" #include "namable.h" #include "pvector.h" @@ -58,8 +59,8 @@ PUBLISHED: const Vertexf &get_current_position(); bool is_empty(); - INLINE GeomNode *create(bool frame_accurate = false); - GeomNode *create(GeomNode *previous, bool frame_accurate = false); + INLINE GeomNode *create(bool dynamic = false); + GeomNode *create(GeomNode *previous, bool dynamic = false); // Functions to move the line vertices after they have been created. INLINE int get_num_vertices() const; @@ -93,6 +94,7 @@ private: PTA_Vertexf _created_verts; PTA_Colorf _created_colors; + PT(qpGeomVertexData) _created_data; }; #include "lineSegs.I" diff --git a/panda/src/grutil/multitexReducer.cxx b/panda/src/grutil/multitexReducer.cxx index 85761fa2ed..9fd9b56c42 100644 --- a/panda/src/grutil/multitexReducer.cxx +++ b/panda/src/grutil/multitexReducer.cxx @@ -37,6 +37,9 @@ #include "config_grutil.h" #include "config_gobj.h" #include "dcast.h" +#include "qpgeom.h" +#include "qpgeomVertexWriter.h" +#include "qpgeomVertexReader.h" //////////////////////////////////////////////////////////////////// // Function: MultitexReducer::Constructor @@ -804,25 +807,39 @@ transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name, GeomList::const_iterator gi; for (gi = geom_list.begin(); gi != geom_list.end(); ++gi) { const GeomInfo &geom_info = (*gi); - - PT(Geom) geom = - geom_info._geom_node->get_geom(geom_info._index)->make_copy(); + const Geom *orig_geom = geom_info._geom_node->get_geom(geom_info._index); - PTA_Vertexf coords = PTA_Vertexf::empty_array(0); - PTA_TexCoordf texcoords = geom->get_texcoords_array(_target_stage->get_texcoord_name()); - if (!texcoords.empty()) { - coords.reserve(texcoords.size()); - for (size_t i = 0; i < texcoords.size(); i++) { - const TexCoordf &tc = texcoords[i]; - Vertexf v(tc[0], 0.0f, tc[1]); - coords.push_back(v); + if (orig_geom->is_of_type(qpGeom::get_class_type())) { + PT(qpGeom) geom = new qpGeom(*DCAST(qpGeom, orig_geom)); + PT(qpGeomVertexData) vdata = geom->modify_vertex_data(); + + if (vdata->has_column(_target_stage->get_texcoord_name())) { + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + qpGeomVertexReader texcoord(vdata, _target_stage->get_texcoord_name()); + + while (!texcoord.is_at_end()) { + const LVecBase2f &tc = texcoord.get_data2f(); + vertex.set_data3f(tc[0], 0.0f, tc[1]); + } } - - geom->set_coords(coords, geom->get_texcoords_index(_target_stage->get_texcoord_name())); - if (texcoord_name != (const InternalName *)NULL) { - geom->set_texcoords(InternalName::get_texcoord(), - geom->get_texcoords_array(texcoord_name), - geom->get_texcoords_index(texcoord_name)); + + if (texcoord_name != (const InternalName *)NULL && + texcoord_name != InternalName::get_texcoord()) { + // Copy the texture coordinates from the indicated name over + // to the default name. + const qpGeomVertexColumn *column = + vdata->get_format()->get_column(texcoord_name); + vdata = vdata->replace_column + (InternalName::get_texcoord(), column->get_num_components(), + column->get_numeric_type(), column->get_contents(), + qpGeomUsageHint::UH_stream, true); + geom->set_vertex_data(vdata); + + qpGeomVertexReader from(vdata, texcoord_name); + qpGeomVertexWriter to(vdata, InternalName::get_texcoord()); + while (!from.is_at_end()) { + to.add_data2f(from.get_data2f()); + } } CPT(RenderState) geom_state = RenderState::make_empty(); @@ -839,6 +856,42 @@ transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name, } geom_node->add_geom(geom, geom_state); + + } else { + PT(Geom) geom = orig_geom->make_copy(); + + PTA_Vertexf coords = PTA_Vertexf::empty_array(0); + PTA_TexCoordf texcoords = geom->get_texcoords_array(_target_stage->get_texcoord_name()); + if (!texcoords.empty()) { + coords.reserve(texcoords.size()); + for (size_t i = 0; i < texcoords.size(); i++) { + const TexCoordf &tc = texcoords[i]; + Vertexf v(tc[0], 0.0f, tc[1]); + coords.push_back(v); + } + + geom->set_coords(coords, geom->get_texcoords_index(_target_stage->get_texcoord_name())); + if (texcoord_name != (const InternalName *)NULL) { + geom->set_texcoords(InternalName::get_texcoord(), + geom->get_texcoords_array(texcoord_name), + geom->get_texcoords_index(texcoord_name)); + } + + CPT(RenderState) geom_state = RenderState::make_empty(); + if (preserve_color) { + // Be sure to preserve whatever colors are on the geom. + const RenderAttrib *ca = geom_info._geom_net_state->get_attrib(ColorAttrib::get_class_type()); + if (ca != (const RenderAttrib *)NULL) { + geom_state = geom_state->add_attrib(ca); + } + const RenderAttrib *csa = geom_info._geom_net_state->get_attrib(ColorScaleAttrib::get_class_type()); + if (csa != (const RenderAttrib *)NULL) { + geom_state = geom_state->add_attrib(csa); + } + } + + geom_node->add_geom(geom, geom_state); + } } } } diff --git a/panda/src/parametrics/ropeNode.cxx b/panda/src/parametrics/ropeNode.cxx index a40831eaea..565e9e2340 100644 --- a/panda/src/parametrics/ropeNode.cxx +++ b/panda/src/parametrics/ropeNode.cxx @@ -30,6 +30,10 @@ #include "datagram.h" #include "datagramIterator.h" #include "pStatTimer.h" +#include "qpgeom.h" +#include "qpgeomLinestrips.h" +#include "qpgeomTristrips.h" +#include "qpgeomVertexWriter.h" TypeHandle RopeNode::_type_handle; diff --git a/panda/src/parametrics/sheetNode.cxx b/panda/src/parametrics/sheetNode.cxx index 4ba3a9aaee..a8adec2b8f 100644 --- a/panda/src/parametrics/sheetNode.cxx +++ b/panda/src/parametrics/sheetNode.cxx @@ -27,6 +27,9 @@ #include "datagram.h" #include "datagramIterator.h" #include "pStatTimer.h" +#include "qpgeom.h" +#include "qpgeomTristrips.h" +#include "qpgeomVertexWriter.h" TypeHandle SheetNode::_type_handle; @@ -261,82 +264,148 @@ do_recompute_bound(const NodePath &rel_to) { //////////////////////////////////////////////////////////////////// void SheetNode:: render_sheet(CullTraverser *trav, CullTraverserData &data, - NurbsSurfaceResult *result) { + NurbsSurfaceResult *result) { bool use_vertex_color = get_use_vertex_color(); - PTA_Vertexf verts; - PTA_Normalf normals; - PTA_TexCoordf uvs; - PTA_Colorf colors; - PTA_int lengths; - - // We define a series of triangle strips, parallel to the V - // direction. - int num_u_segments = result->get_num_u_segments(); int num_v_segments = result->get_num_v_segments(); int num_u_verts = get_num_u_subdiv() + 1; int num_v_verts = get_num_v_subdiv() + 1; - for (int ui = 0; ui < num_u_segments; ui++) { - for (int uni = 0; uni < num_u_verts; uni++) { - float u0 = (float)uni / (float)num_u_verts; - float u1 = (float)(uni + 1) / (float)num_u_verts; - float u0_tc = result->get_segment_u(ui, u0); - float u1_tc = result->get_segment_u(ui, u1); + if (use_qpgeom) { + CPT(qpGeomVertexFormat) format; + if (use_vertex_color) { + format = qpGeomVertexFormat::get_v3n3cpt2(); + } else { + format = qpGeomVertexFormat::get_v3n3t2(); + } + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("sheet", format, qpGeomUsageHint::UH_stream); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + qpGeomVertexWriter normal(vdata, InternalName::get_normal()); + qpGeomVertexWriter color(vdata, InternalName::get_color()); + qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); + + PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_stream); + for (int ui = 0; ui < num_u_segments; ui++) { + for (int uni = 0; uni < num_u_verts; uni++) { + float u0 = (float)uni / (float)num_u_verts; + float u1 = (float)(uni + 1) / (float)num_u_verts; + float u0_tc = result->get_segment_u(ui, u0); + float u1_tc = result->get_segment_u(ui, u1); - for (int vi = 0; vi < num_v_segments; vi++) { - for (int vni = 0; vni < num_v_verts; vni++) { - float v = (float)vni / (float)(num_v_verts - 1); - float v_tc = result->get_segment_v(vi, v); + for (int vi = 0; vi < num_v_segments; vi++) { + for (int vni = 0; vni < num_v_verts; vni++) { + float v = (float)vni / (float)(num_v_verts - 1); + float v_tc = result->get_segment_v(vi, v); - LPoint3f point; - LVector3f normal; - result->eval_segment_point(ui, vi, u0, v, point); - result->eval_segment_normal(ui, vi, u0, v, normal); - verts.push_back(point); - normals.push_back(normal); - uvs.push_back(TexCoordf(u0_tc, v_tc)); + LPoint3f point; + LVector3f norm; + result->eval_segment_point(ui, vi, u0, v, point); + result->eval_segment_normal(ui, vi, u0, v, norm); + vertex.add_data3f(point); + normal.add_data3f(norm); + texcoord.add_data2f(u0_tc, v_tc); - result->eval_segment_point(ui, vi, u1, v, point); - result->eval_segment_normal(ui, vi, u1, v, normal); - verts.push_back(point); - normals.push_back(normal); - uvs.push_back(TexCoordf(u1_tc, v_tc)); + result->eval_segment_point(ui, vi, u1, v, point); + result->eval_segment_normal(ui, vi, u1, v, norm); + vertex.add_data3f(point); + normal.add_data3f(norm); + texcoord.add_data2f(u1_tc, v_tc); - if (use_vertex_color) { - Colorf c0, c1; - result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4); - result->eval_segment_extended_points(ui, vi, u1, v, 0, &c1[0], 4); + if (use_vertex_color) { + Colorf c0, c1; + result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4); + result->eval_segment_extended_points(ui, vi, u1, v, 0, &c1[0], 4); - colors.push_back(c0); - colors.push_back(c1); + color.add_data4f(c0); + color.add_data4f(c1); + } } + strip->add_next_vertices(num_v_verts * 2); + strip->close_primitive(); } - lengths.push_back(num_v_verts * 2); } } - } - colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); - - PT(GeomTristrip) geom = new GeomTristrip; - geom->set_num_prims(lengths.size()); - geom->set_coords(verts); - geom->set_normals(normals, G_PER_VERTEX); - geom->set_texcoords(uvs, G_PER_VERTEX); + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(strip); + + CullableObject *object = new CullableObject(geom, data._state, + data._render_transform); + trav->get_cull_handler()->record_object(object); - if (use_vertex_color) { - geom->set_colors(colors, G_PER_VERTEX); } else { + PTA_Vertexf verts; + PTA_Normalf normals; + PTA_TexCoordf uvs; + PTA_Colorf colors; + PTA_int lengths; + + // We define a series of triangle strips, parallel to the V + // direction. + + for (int ui = 0; ui < num_u_segments; ui++) { + for (int uni = 0; uni < num_u_verts; uni++) { + float u0 = (float)uni / (float)num_u_verts; + float u1 = (float)(uni + 1) / (float)num_u_verts; + float u0_tc = result->get_segment_u(ui, u0); + float u1_tc = result->get_segment_u(ui, u1); + + for (int vi = 0; vi < num_v_segments; vi++) { + for (int vni = 0; vni < num_v_verts; vni++) { + float v = (float)vni / (float)(num_v_verts - 1); + float v_tc = result->get_segment_v(vi, v); + + LPoint3f point; + LVector3f normal; + result->eval_segment_point(ui, vi, u0, v, point); + result->eval_segment_normal(ui, vi, u0, v, normal); + verts.push_back(point); + normals.push_back(normal); + uvs.push_back(TexCoordf(u0_tc, v_tc)); + + result->eval_segment_point(ui, vi, u1, v, point); + result->eval_segment_normal(ui, vi, u1, v, normal); + verts.push_back(point); + normals.push_back(normal); + uvs.push_back(TexCoordf(u1_tc, v_tc)); + + if (use_vertex_color) { + Colorf c0, c1; + result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4); + result->eval_segment_extended_points(ui, vi, u1, v, 0, &c1[0], 4); + + colors.push_back(c0); + colors.push_back(c1); + } + } + lengths.push_back(num_v_verts * 2); + } + } + } + colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); - geom->set_colors(colors, G_OVERALL); - } - geom->set_lengths(lengths); - CullableObject *object = new CullableObject(geom, data._state, - data._render_transform); - trav->get_cull_handler()->record_object(object); + PT(GeomTristrip) geom = new GeomTristrip; + geom->set_num_prims(lengths.size()); + geom->set_coords(verts); + geom->set_normals(normals, G_PER_VERTEX); + geom->set_texcoords(uvs, G_PER_VERTEX); + + if (use_vertex_color) { + geom->set_colors(colors, G_PER_VERTEX); + } else { + colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); + geom->set_colors(colors, G_OVERALL); + } + geom->set_lengths(lengths); + + CullableObject *object = new CullableObject(geom, data._state, + data._render_transform); + trav->get_cull_handler()->record_object(object); + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index e66d4fa9a7..c238dc883c 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -33,6 +33,9 @@ #include "boundingHexahedron.h" #include "geomSphere.h" #include "portalClipper.h" +#include "qpgeom.h" +#include "qpgeomTristrips.h" +#include "qpgeomVertexWriter.h" PStatCollector CullTraverser::_nodes_pcollector("Nodes"); PStatCollector CullTraverser::_geom_nodes_pcollector("Nodes:GeomNodes"); @@ -293,15 +296,47 @@ make_bounds_viz(const BoundingVolume &vol) { } else if (vol.is_of_type(BoundingSphere::get_class_type())) { const BoundingSphere *sphere = DCAST(BoundingSphere, &vol); - - geom = new GeomSphere; - PTA_Vertexf verts; - LPoint3f center = sphere->get_center(); - verts.push_back(center); - center[0] += sphere->get_radius(); - verts.push_back(center); - geom->set_coords(verts); - geom->set_num_prims(1); + + if (use_qpgeom) { + static const int num_slices = 16; + static const int num_stacks = 8; + + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("collision", qpGeomVertexFormat::get_v3(), + qpGeomUsageHint::UH_stream); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + + PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_stream); + for (int sl = 0; sl < num_slices; ++sl) { + float longitude0 = (float)sl / (float)num_slices; + float longitude1 = (float)(sl + 1) / (float)num_slices; + vertex.add_data3f(compute_point(sphere, 0.0, longitude0)); + for (int st = 1; st < num_stacks; ++st) { + float latitude = (float)st / (float)num_stacks; + vertex.add_data3f(compute_point(sphere, latitude, longitude0)); + vertex.add_data3f(compute_point(sphere, latitude, longitude1)); + } + vertex.add_data3f(compute_point(sphere, 1.0, longitude0)); + + strip->add_next_vertices(num_stacks * 2); + strip->close_primitive(); + } + + PT(qpGeom) qpgeom = new qpGeom; + qpgeom->set_vertex_data(vdata); + qpgeom->add_primitive(strip); + geom = qpgeom.p(); + + } else { + geom = new GeomSphere; + PTA_Vertexf verts; + LPoint3f center = sphere->get_center(); + verts.push_back(center); + center[0] += sphere->get_radius(); + verts.push_back(center); + geom->set_coords(verts); + geom->set_num_prims(1); + } } else { pgraph_cat.warning() @@ -312,6 +347,25 @@ make_bounds_viz(const BoundingVolume &vol) { return geom; } +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::compute_point +// Access: Private, Static +// Description: Returns a point on the surface of the sphere. +// latitude and longitude range from 0.0 to 1.0. +//////////////////////////////////////////////////////////////////// +Vertexf CullTraverser:: +compute_point(const BoundingSphere *sphere, + float latitude, float longitude) { + float s1, c1; + csincos(latitude * MathNumbers::pi_f, &s1, &c1); + + float s2, c2; + csincos(longitude * 2.0f * MathNumbers::pi_f, &s2, &c2); + + Vertexf p(s1 * c2, s1 * s2, c1); + return p * sphere->get_radius() + sphere->get_center(); +} + //////////////////////////////////////////////////////////////////// // Function: CullTraverser::get_bounds_outer_viz_state // Access: Private, Static diff --git a/panda/src/pgraph/cullTraverser.h b/panda/src/pgraph/cullTraverser.h index eb46cbb213..a3f216905c 100644 --- a/panda/src/pgraph/cullTraverser.h +++ b/panda/src/pgraph/cullTraverser.h @@ -94,6 +94,8 @@ public: private: void show_bounds(CullTraverserData &data); PT(Geom) make_bounds_viz(const BoundingVolume &vol); + static Vertexf compute_point(const BoundingSphere *sphere, + float latitude, float longitude); CPT(RenderState) get_bounds_outer_viz_state(); CPT(RenderState) get_bounds_inner_viz_state(); CPT(RenderState) get_depth_offset_state(); diff --git a/panda/src/pgraph/geomNode.I b/panda/src/pgraph/geomNode.I index bbd6c565ba..eb4e609120 100644 --- a/panda/src/pgraph/geomNode.I +++ b/panda/src/pgraph/geomNode.I @@ -121,27 +121,6 @@ set_geom_state(int n, const RenderState *state) { cdata->_geoms[n]._state = state; } -//////////////////////////////////////////////////////////////////// -// Function: GeomNode::add_geom -// Access: Published -// Description: Adds a new Geom to the node. The geom is given the -// indicated state (which may be -// RenderState::make_empty(), to completely inherit its -// state from the scene graph). -// -// The return value is the index number of the new Geom. -//////////////////////////////////////////////////////////////////// -INLINE int GeomNode:: -add_geom(Geom *geom, const RenderState *state) { - nassertr(geom != (Geom *)NULL, -1); - nassertr(state != (RenderState *)NULL, -1); - CDWriter cdata(_cycler); - - cdata->_geoms.push_back(GeomEntry(geom, state)); - mark_bound_stale(); - return cdata->_geoms.size() - 1; -} - //////////////////////////////////////////////////////////////////// // Function: GeomNode::remove_geom // Access: Published diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index 3ce403edd0..ba7ec052ae 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -405,6 +405,28 @@ get_legal_collide_mask() const { return CollideMask::all_on(); } +//////////////////////////////////////////////////////////////////// +// Function: GeomNode::add_geom +// Access: Published +// Description: Adds a new Geom to the node. The geom is given the +// indicated state (which may be +// RenderState::make_empty(), to completely inherit its +// state from the scene graph). +// +// The return value is the index number of the new Geom. +//////////////////////////////////////////////////////////////////// +int GeomNode:: +add_geom(Geom *geom, const RenderState *state) { + nassertr(geom != (Geom *)NULL, -1); + nassertr(geom->check_valid(), -1); + nassertr(state != (RenderState *)NULL, -1); + CDWriter cdata(_cycler); + + cdata->_geoms.push_back(GeomEntry(geom, state)); + mark_bound_stale(); + return cdata->_geoms.size() - 1; +} + //////////////////////////////////////////////////////////////////// // Function: GeomNode::add_geoms_from // Access: Published @@ -415,15 +437,16 @@ void GeomNode:: add_geoms_from(const GeomNode *other) { CDReader cdata_other(other->_cycler); CDWriter cdata(_cycler); + mark_bound_stale(); Geoms::const_iterator gi; for (gi = cdata_other->_geoms.begin(); gi != cdata_other->_geoms.end(); ++gi) { const GeomEntry &entry = (*gi); + nassertv(entry._geom->check_valid()); cdata->_geoms.push_back(entry); } - mark_bound_stale(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/geomNode.h b/panda/src/pgraph/geomNode.h index 38f2daea68..be3cc9d8a0 100644 --- a/panda/src/pgraph/geomNode.h +++ b/panda/src/pgraph/geomNode.h @@ -62,7 +62,7 @@ PUBLISHED: INLINE const RenderState *get_geom_state(int n) const; INLINE void set_geom_state(int n, const RenderState *state); - INLINE int add_geom(Geom *geom, const RenderState *state = RenderState::make_empty()); + int add_geom(Geom *geom, const RenderState *state = RenderState::make_empty()); void add_geoms_from(const GeomNode *other); INLINE void remove_geom(int n); INLINE void remove_all_geoms(); diff --git a/panda/src/pgraph/geomTransformer.cxx b/panda/src/pgraph/geomTransformer.cxx index 569e38c635..c3223e6b2a 100644 --- a/panda/src/pgraph/geomTransformer.cxx +++ b/panda/src/pgraph/geomTransformer.cxx @@ -324,7 +324,13 @@ set_color(Geom *geom, const Colorf &color) { CPT(qpGeomVertexData) &new_data = _qpfcolors[sc]; if (new_data.is_null()) { // We have not yet converted these colors. Do so now. - new_data = sc._vertex_data->set_color(color); + if (sc._vertex_data->has_column(InternalName::get_color())) { + new_data = sc._vertex_data->set_color(color); + } else { + new_data = sc._vertex_data->set_color + (color, 1, qpGeomVertexColumn::NT_packed_dabc, + qpGeomVertexColumn::C_color); + } } qpgeom->set_vertex_data(new_data); @@ -399,7 +405,13 @@ transform_colors(Geom *geom, const LVecBase4f &scale) { CPT(qpGeomVertexData) &new_data = _qptcolors[sc]; if (new_data.is_null()) { // We have not yet converted these colors. Do so now. - new_data = sc._vertex_data->scale_color(scale); + if (sc._vertex_data->has_column(InternalName::get_color())) { + new_data = sc._vertex_data->scale_color(scale); + } else { + new_data = sc._vertex_data->set_color + (scale, 1, qpGeomVertexColumn::NT_packed_dabc, + qpGeomVertexColumn::C_color); + } } qpgeom->set_vertex_data(new_data); diff --git a/panda/src/pgui/pgFrameStyle.cxx b/panda/src/pgui/pgFrameStyle.cxx index 6312cd71fc..0c36205748 100644 --- a/panda/src/pgui/pgFrameStyle.cxx +++ b/panda/src/pgui/pgFrameStyle.cxx @@ -26,6 +26,10 @@ #include "nodePath.h" #include "textureAttrib.h" #include "renderState.h" +#include "shadeModelAttrib.h" +#include "qpgeom.h" +#include "qpgeomTristrips.h" +#include "qpgeomVertexWriter.h" // Specifies the UV range of textures applied to the frame. Maybe // we'll have a reason to make this a parameter of the frame style one @@ -170,49 +174,98 @@ generate_into(const NodePath &parent, const LVecBase4f &frame) { PT(PandaNode) PGFrameStyle:: generate_flat_geom(const LVecBase4f &frame) { PT(GeomNode) gnode = new GeomNode("flat"); - Geom *geom = new GeomTristrip; - gnode->add_geom(geom); float left = frame[0]; float right = frame[1]; float bottom = frame[2]; float top = frame[3]; - PTA_int lengths; - lengths.push_back(4); + if (use_qpgeom) { + CPT(qpGeomVertexFormat) format; + if (has_texture()) { + format = qpGeomVertexFormat::get_v3cpt2(); + } else { + format = qpGeomVertexFormat::get_v3cp(); + } - PTA_Vertexf verts; - verts.push_back(Vertexf(left, 0.0f, top)); - verts.push_back(Vertexf(left, 0.0f, bottom)); - verts.push_back(Vertexf(right, 0.0f, top)); - verts.push_back(Vertexf(right, 0.0f, bottom)); + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("PGFrame", format, qpGeomUsageHint::UH_static); - geom->set_num_prims(1); - geom->set_lengths(lengths); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + vertex.add_data3f(left, 0.0f, top); + vertex.add_data3f(left, 0.0f, bottom); + vertex.add_data3f(right, 0.0f, top); + vertex.add_data3f(right, 0.0f, bottom); - geom->set_coords(verts); - - PTA_Colorf colors; - colors.push_back(_color); - geom->set_colors(colors, G_OVERALL); - - if (has_texture()) { - // Generate UV's. - left = uv_range[0]; - right = uv_range[1]; - bottom = uv_range[2]; - top = uv_range[3]; + if (has_texture()) { + // Generate UV's. + left = uv_range[0]; + right = uv_range[1]; + bottom = uv_range[2]; + top = uv_range[3]; - PTA_TexCoordf uvs; - uvs.push_back(TexCoordf(left, top)); - uvs.push_back(TexCoordf(left, bottom)); - uvs.push_back(TexCoordf(right, top)); - uvs.push_back(TexCoordf(right, bottom)); - geom->set_texcoords(uvs, G_PER_VERTEX); + qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); + texcoord.add_data2f(left, top); + texcoord.add_data2f(left, bottom); + texcoord.add_data2f(right, top); + texcoord.add_data2f(right, bottom); + } - CPT(RenderState) state = - RenderState::make(TextureAttrib::make(get_texture())); - gnode->set_geom_state(0, state); + PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static); + strip->add_next_vertices(4); + strip->close_primitive(); + + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(strip); + gnode->add_geom(geom); + + if (has_texture()) { + CPT(RenderState) state = + RenderState::make(TextureAttrib::make(get_texture())); + gnode->set_geom_state(0, state); + } + + } else { + Geom *geom = new GeomTristrip; + gnode->add_geom(geom); + + PTA_int lengths; + lengths.push_back(4); + + PTA_Vertexf verts; + verts.push_back(Vertexf(left, 0.0f, top)); + verts.push_back(Vertexf(left, 0.0f, bottom)); + verts.push_back(Vertexf(right, 0.0f, top)); + verts.push_back(Vertexf(right, 0.0f, bottom)); + + geom->set_num_prims(1); + geom->set_lengths(lengths); + + geom->set_coords(verts); + + PTA_Colorf colors; + colors.push_back(_color); + geom->set_colors(colors, G_OVERALL); + + if (has_texture()) { + // Generate UV's. + left = uv_range[0]; + right = uv_range[1]; + bottom = uv_range[2]; + top = uv_range[3]; + + PTA_TexCoordf uvs; + uvs.push_back(TexCoordf(left, top)); + uvs.push_back(TexCoordf(left, bottom)); + uvs.push_back(TexCoordf(right, top)); + uvs.push_back(TexCoordf(right, bottom)); + geom->set_texcoords(uvs, G_PER_VERTEX); + + CPT(RenderState) state = + RenderState::make(TextureAttrib::make(get_texture())); + gnode->set_geom_state(0, state); + } } return gnode.p(); @@ -328,52 +381,109 @@ generate_bevel_geom(const LVecBase4f &frame, bool in) { min(_color[2] * top_color_scale, 1.0f), _color[3]); - // Now make the tristrips. - Geom *geom = new GeomTristrip; - gnode->add_geom(geom); - - PTA_int lengths; - PTA_Vertexf verts; - PTA_Colorf colors; + if (use_qpgeom) { + CPT(qpGeomVertexFormat) format = qpGeomVertexFormat::get_v3cp(); + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("PGFrame", format, qpGeomUsageHint::UH_static); - // Tristrip 1. - lengths.push_back(8); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + qpGeomVertexWriter color(vdata, InternalName::get_color()); + + PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static); + // Tristrip 1. + vertex.add_data3f(right, 0.0f, bottom); + vertex.add_data3f(inner_right, 0.0f, inner_bottom); + vertex.add_data3f(left, 0.0f, bottom); + vertex.add_data3f(inner_left, 0.0f, inner_bottom); + vertex.add_data3f(left, 0.0f, top); + vertex.add_data3f(inner_left, 0.0f, inner_top); + vertex.add_data3f(right, 0.0f, top); + vertex.add_data3f(inner_right, 0.0f, inner_top); + color.add_data4f(cbottom); + color.add_data4f(cbottom); + color.add_data4f(cbottom); + color.add_data4f(cbottom); + color.add_data4f(cleft); + color.add_data4f(cleft); + color.add_data4f(ctop); + color.add_data4f(ctop); + + strip->add_next_vertices(8); + strip->close_primitive(); + + // Tristrip 2. + vertex.add_data3f(right, 0.0f, bottom); + vertex.add_data3f(right, 0.0f, top); + vertex.add_data3f(inner_right, 0.0f, inner_bottom); + vertex.add_data3f(inner_right, 0.0f, inner_top); + vertex.add_data3f(inner_left, 0.0f, inner_bottom); + vertex.add_data3f(inner_left, 0.0f, inner_top); + color.add_data4f(cright); + color.add_data4f(cright); + color.add_data4f(cright); + color.add_data4f(cright); + color.add_data4f(_color); + color.add_data4f(_color); + + strip->add_next_vertices(6); + strip->close_primitive(); + strip->set_shade_model(qpGeomPrimitive::SM_flat_last_vertex); + + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(strip); + + CPT(RenderState) flat_state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat)); + gnode->add_geom(geom, flat_state); + + } else { + // Now make the tristrips. + Geom *geom = new GeomTristrip; + gnode->add_geom(geom); - verts.push_back(Vertexf(right, 0.0f, bottom)); - verts.push_back(Vertexf(inner_right, 0.0f, inner_bottom)); - verts.push_back(Vertexf(left, 0.0f, bottom)); - verts.push_back(Vertexf(inner_left, 0.0f, inner_bottom)); - verts.push_back(Vertexf(left, 0.0f, top)); - verts.push_back(Vertexf(inner_left, 0.0f, inner_top)); - verts.push_back(Vertexf(right, 0.0f, top)); - verts.push_back(Vertexf(inner_right, 0.0f, inner_top)); + PTA_int lengths; + PTA_Vertexf verts; + PTA_Colorf colors; + + // Tristrip 1. + lengths.push_back(8); + + verts.push_back(Vertexf(right, 0.0f, bottom)); + verts.push_back(Vertexf(inner_right, 0.0f, inner_bottom)); + verts.push_back(Vertexf(left, 0.0f, bottom)); + verts.push_back(Vertexf(inner_left, 0.0f, inner_bottom)); + verts.push_back(Vertexf(left, 0.0f, top)); + verts.push_back(Vertexf(inner_left, 0.0f, inner_top)); + verts.push_back(Vertexf(right, 0.0f, top)); + verts.push_back(Vertexf(inner_right, 0.0f, inner_top)); - colors.push_back(cbottom); - colors.push_back(cbottom); - colors.push_back(cleft); - colors.push_back(cleft); - colors.push_back(ctop); - colors.push_back(ctop); + colors.push_back(cbottom); + colors.push_back(cbottom); + colors.push_back(cleft); + colors.push_back(cleft); + colors.push_back(ctop); + colors.push_back(ctop); - // Tristrip 2. - lengths.push_back(6); + // Tristrip 2. + lengths.push_back(6); - verts.push_back(Vertexf(right, 0.0f, bottom)); - verts.push_back(Vertexf(right, 0.0f, top)); - verts.push_back(Vertexf(inner_right, 0.0f, inner_bottom)); - verts.push_back(Vertexf(inner_right, 0.0f, inner_top)); - verts.push_back(Vertexf(inner_left, 0.0f, inner_bottom)); - verts.push_back(Vertexf(inner_left, 0.0f, inner_top)); + verts.push_back(Vertexf(right, 0.0f, bottom)); + verts.push_back(Vertexf(right, 0.0f, top)); + verts.push_back(Vertexf(inner_right, 0.0f, inner_bottom)); + verts.push_back(Vertexf(inner_right, 0.0f, inner_top)); + verts.push_back(Vertexf(inner_left, 0.0f, inner_bottom)); + verts.push_back(Vertexf(inner_left, 0.0f, inner_top)); - colors.push_back(cright); - colors.push_back(cright); - colors.push_back(_color); - colors.push_back(_color); + colors.push_back(cright); + colors.push_back(cright); + colors.push_back(_color); + colors.push_back(_color); - geom->set_num_prims(2); - geom->set_lengths(lengths); - geom->set_coords(verts); - geom->set_colors(colors, G_PER_COMPONENT); + geom->set_num_prims(2); + geom->set_lengths(lengths); + geom->set_coords(verts); + geom->set_colors(colors, G_PER_COMPONENT); + } // For now, beveled and grooved geoms don't support textures. Easy // to add if anyone really wants this. @@ -537,75 +647,158 @@ generate_groove_geom(const LVecBase4f &frame, bool in) { min(_color[2] * top_color_scale, 1.0f), _color[3]); - // Now make the tristrips. - Geom *geom = new GeomTristrip; - gnode->add_geom(geom); - - PTA_int lengths; - PTA_Vertexf verts; - PTA_Colorf colors; + if (use_qpgeom) { + CPT(qpGeomVertexFormat) format = qpGeomVertexFormat::get_v3cp(); + PT(qpGeomVertexData) vdata = new qpGeomVertexData + ("PGFrame", format, qpGeomUsageHint::UH_static); - // Tristrip 1. - lengths.push_back(8); + qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); + qpGeomVertexWriter color(vdata, InternalName::get_color()); + + PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static); + // Tristrip 1. + vertex.add_data3f(right, 0.0f, bottom); + vertex.add_data3f(mid_right, 0.0f, mid_bottom); + vertex.add_data3f(left, 0.0f, bottom); + vertex.add_data3f(mid_left, 0.0f, mid_bottom); + vertex.add_data3f(left, 0.0f, top); + vertex.add_data3f(mid_left, 0.0f, mid_top); + vertex.add_data3f(right, 0.0f, top); + vertex.add_data3f(mid_right, 0.0f, mid_top); + color.add_data4f(cbottom); + color.add_data4f(cbottom); + color.add_data4f(cbottom); + color.add_data4f(cbottom); + color.add_data4f(cleft); + color.add_data4f(cleft); + color.add_data4f(ctop); + color.add_data4f(ctop); + + strip->add_next_vertices(8); + strip->close_primitive(); + + // Tristrip 2. + vertex.add_data3f(mid_right, 0.0f, mid_bottom); + vertex.add_data3f(inner_right, 0.0f, inner_bottom); + vertex.add_data3f(mid_left, 0.0f, mid_bottom); + vertex.add_data3f(inner_left, 0.0f, inner_bottom); + vertex.add_data3f(mid_left, 0.0f, mid_top); + vertex.add_data3f(inner_left, 0.0f, inner_top); + vertex.add_data3f(mid_right, 0.0f, mid_top); + vertex.add_data3f(inner_right, 0.0f, inner_top); + color.add_data4f(ctop); + color.add_data4f(ctop); + color.add_data4f(ctop); + color.add_data4f(ctop); + color.add_data4f(cright); + color.add_data4f(cright); + color.add_data4f(cbottom); + color.add_data4f(cbottom); + + strip->add_next_vertices(8); + strip->close_primitive(); + + // Tristrip 3. + vertex.add_data3f(right, 0.0f, bottom); + vertex.add_data3f(right, 0.0f, top); + vertex.add_data3f(mid_right, 0.0f, mid_bottom); + vertex.add_data3f(mid_right, 0.0f, mid_top); + vertex.add_data3f(inner_right, 0.0f, inner_bottom); + vertex.add_data3f(inner_right, 0.0f, inner_top); + vertex.add_data3f(inner_left, 0.0f, inner_bottom); + vertex.add_data3f(inner_left, 0.0f, inner_top); + color.add_data4f(cright); + color.add_data4f(cright); + color.add_data4f(cright); + color.add_data4f(cright); + color.add_data4f(cleft); + color.add_data4f(cleft); + color.add_data4f(_color); + color.add_data4f(_color); + + strip->add_next_vertices(8); + strip->close_primitive(); + + strip->set_shade_model(qpGeomPrimitive::SM_flat_last_vertex); + + PT(qpGeom) geom = new qpGeom; + geom->set_vertex_data(vdata); + geom->add_primitive(strip); + + CPT(RenderState) flat_state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat)); + gnode->add_geom(geom, flat_state); + + } else { + // Now make the tristrips. + Geom *geom = new GeomTristrip; + gnode->add_geom(geom); - verts.push_back(Vertexf(right, 0.0f, bottom)); - verts.push_back(Vertexf(mid_right, 0.0f, mid_bottom)); - verts.push_back(Vertexf(left, 0.0f, bottom)); - verts.push_back(Vertexf(mid_left, 0.0f, mid_bottom)); - verts.push_back(Vertexf(left, 0.0f, top)); - verts.push_back(Vertexf(mid_left, 0.0f, mid_top)); - verts.push_back(Vertexf(right, 0.0f, top)); - verts.push_back(Vertexf(mid_right, 0.0f, mid_top)); + PTA_int lengths; + PTA_Vertexf verts; + PTA_Colorf colors; + + // Tristrip 1. + lengths.push_back(8); + + verts.push_back(Vertexf(right, 0.0f, bottom)); + verts.push_back(Vertexf(mid_right, 0.0f, mid_bottom)); + verts.push_back(Vertexf(left, 0.0f, bottom)); + verts.push_back(Vertexf(mid_left, 0.0f, mid_bottom)); + verts.push_back(Vertexf(left, 0.0f, top)); + verts.push_back(Vertexf(mid_left, 0.0f, mid_top)); + verts.push_back(Vertexf(right, 0.0f, top)); + verts.push_back(Vertexf(mid_right, 0.0f, mid_top)); - colors.push_back(cbottom); - colors.push_back(cbottom); - colors.push_back(cleft); - colors.push_back(cleft); - colors.push_back(ctop); - colors.push_back(ctop); + colors.push_back(cbottom); + colors.push_back(cbottom); + colors.push_back(cleft); + colors.push_back(cleft); + colors.push_back(ctop); + colors.push_back(ctop); - // Tristrip 2. - lengths.push_back(8); + // Tristrip 2. + lengths.push_back(8); - verts.push_back(Vertexf(mid_right, 0.0f, mid_bottom)); - verts.push_back(Vertexf(inner_right, 0.0f, inner_bottom)); - verts.push_back(Vertexf(mid_left, 0.0f, mid_bottom)); - verts.push_back(Vertexf(inner_left, 0.0f, inner_bottom)); - verts.push_back(Vertexf(mid_left, 0.0f, mid_top)); - verts.push_back(Vertexf(inner_left, 0.0f, inner_top)); - verts.push_back(Vertexf(mid_right, 0.0f, mid_top)); - verts.push_back(Vertexf(inner_right, 0.0f, inner_top)); + verts.push_back(Vertexf(mid_right, 0.0f, mid_bottom)); + verts.push_back(Vertexf(inner_right, 0.0f, inner_bottom)); + verts.push_back(Vertexf(mid_left, 0.0f, mid_bottom)); + verts.push_back(Vertexf(inner_left, 0.0f, inner_bottom)); + verts.push_back(Vertexf(mid_left, 0.0f, mid_top)); + verts.push_back(Vertexf(inner_left, 0.0f, inner_top)); + verts.push_back(Vertexf(mid_right, 0.0f, mid_top)); + verts.push_back(Vertexf(inner_right, 0.0f, inner_top)); - colors.push_back(ctop); - colors.push_back(ctop); - colors.push_back(cright); - colors.push_back(cright); - colors.push_back(cbottom); - colors.push_back(cbottom); + colors.push_back(ctop); + colors.push_back(ctop); + colors.push_back(cright); + colors.push_back(cright); + colors.push_back(cbottom); + colors.push_back(cbottom); - // Tristrip 3. - lengths.push_back(8); + // Tristrip 3. + lengths.push_back(8); - verts.push_back(Vertexf(right, 0.0f, bottom)); - verts.push_back(Vertexf(right, 0.0f, top)); - verts.push_back(Vertexf(mid_right, 0.0f, mid_bottom)); - verts.push_back(Vertexf(mid_right, 0.0f, mid_top)); - verts.push_back(Vertexf(inner_right, 0.0f, inner_bottom)); - verts.push_back(Vertexf(inner_right, 0.0f, inner_top)); - verts.push_back(Vertexf(inner_left, 0.0f, inner_bottom)); - verts.push_back(Vertexf(inner_left, 0.0f, inner_top)); + verts.push_back(Vertexf(right, 0.0f, bottom)); + verts.push_back(Vertexf(right, 0.0f, top)); + verts.push_back(Vertexf(mid_right, 0.0f, mid_bottom)); + verts.push_back(Vertexf(mid_right, 0.0f, mid_top)); + verts.push_back(Vertexf(inner_right, 0.0f, inner_bottom)); + verts.push_back(Vertexf(inner_right, 0.0f, inner_top)); + verts.push_back(Vertexf(inner_left, 0.0f, inner_bottom)); + verts.push_back(Vertexf(inner_left, 0.0f, inner_top)); - colors.push_back(cright); - colors.push_back(cright); - colors.push_back(cleft); - colors.push_back(cleft); - colors.push_back(_color); - colors.push_back(_color); + colors.push_back(cright); + colors.push_back(cright); + colors.push_back(cleft); + colors.push_back(cleft); + colors.push_back(_color); + colors.push_back(_color); - geom->set_num_prims(3); - geom->set_lengths(lengths); - geom->set_coords(verts); - geom->set_colors(colors, G_PER_COMPONENT); + geom->set_num_prims(3); + geom->set_lengths(lengths); + geom->set_coords(verts); + geom->set_colors(colors, G_PER_COMPONENT); + } // For now, beveled and grooved geoms don't support textures. Easy // to add if anyone really wants this. diff --git a/panda/src/text/dynamicTextGlyph.cxx b/panda/src/text/dynamicTextGlyph.cxx index 469d299dd4..3c51f8188a 100644 --- a/panda/src/text/dynamicTextGlyph.cxx +++ b/panda/src/text/dynamicTextGlyph.cxx @@ -125,21 +125,15 @@ make_geom(int bitmap_top, int bitmap_left, float advance, float poly_margin, // Create a corresponding tristrip. if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - (string(), qpGeomVertexFormat::get_v3cpt2(), + (string(), qpGeomVertexFormat::get_v3t2(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); - qpGeomVertexWriter color(vdata, InternalName::get_color()); qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); vertex.add_data3f(left, 0, top); vertex.add_data3f(left, 0, bottom); vertex.add_data3f(right, 0, top); vertex.add_data3f(right, 0, bottom); - - color.add_data4f(1.0f, 1.0f, 1.0f, 1.0f); - color.add_data4f(1.0f, 1.0f, 1.0f, 1.0f); - color.add_data4f(1.0f, 1.0f, 1.0f, 1.0f); - color.add_data4f(1.0f, 1.0f, 1.0f, 1.0f); texcoord.add_data2f(uv_left, uv_top); texcoord.add_data2f(uv_left, uv_bottom); diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index 02a7ecd452..99def9899b 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -607,7 +607,7 @@ make_frame() { if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("text", qpGeomVertexFormat::get_v3cp(), + ("text", qpGeomVertexFormat::get_v3(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); @@ -681,7 +681,7 @@ make_card() { if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("text", qpGeomVertexFormat::get_v3cpt2(), + ("text", qpGeomVertexFormat::get_v3t2(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); @@ -766,7 +766,7 @@ make_card_with_border() { if (use_qpgeom) { PT(qpGeomVertexData) vdata = new qpGeomVertexData - ("text", qpGeomVertexFormat::get_v3cpt2(), + ("text", qpGeomVertexFormat::get_v3t2(), qpGeomUsageHint::UH_static); qpGeomVertexWriter vertex(vdata, InternalName::get_vertex()); qpGeomVertexWriter texcoord(vdata, InternalName::get_texcoord());