Merge branch 'master' into deploy-ng
This commit is contained in:
commit
43914f4e75
|
|
@ -97,7 +97,7 @@ do_transform_changed() {
|
|||
if (ts->has_scale()) {
|
||||
LVecBase3 scale = ts->get_scale();
|
||||
if (!scale.almost_equal(LVecBase3(1.0f, 1.0f, 1.0f))) {
|
||||
for (int i=0; i<get_num_shapes(); i++) {
|
||||
for (int i=0; i < _shapes.size(); i++) {
|
||||
PT(BulletShape) shape = _shapes[i];
|
||||
shape->do_set_local_scale(scale);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2381,6 +2381,15 @@ draw_triangles(const GeomPrimitivePipelineReader *, bool) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draws a series of disconnected triangles with adjacency information.
|
||||
*/
|
||||
bool GraphicsStateGuardian::
|
||||
draw_triangles_adj(const GeomPrimitivePipelineReader *, bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of triangle strips.
|
||||
*/
|
||||
|
|
@ -2389,6 +2398,14 @@ draw_tristrips(const GeomPrimitivePipelineReader *, bool) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of triangle strips with adjacency information.
|
||||
*/
|
||||
bool GraphicsStateGuardian::
|
||||
draw_tristrips_adj(const GeomPrimitivePipelineReader *, bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of triangle fans.
|
||||
*/
|
||||
|
|
@ -2414,6 +2431,14 @@ draw_lines(const GeomPrimitivePipelineReader *, bool) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of disconnected line segments with adjacency information.
|
||||
*/
|
||||
bool GraphicsStateGuardian::
|
||||
draw_lines_adj(const GeomPrimitivePipelineReader *, bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of line strips.
|
||||
*/
|
||||
|
|
@ -2422,6 +2447,14 @@ draw_linestrips(const GeomPrimitivePipelineReader *, bool) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of line strips with adjacency information.
|
||||
*/
|
||||
bool GraphicsStateGuardian::
|
||||
draw_linestrips_adj(const GeomPrimitivePipelineReader *, bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of disconnected points.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -371,16 +371,24 @@ public:
|
|||
bool force);
|
||||
virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_triangles_adj(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_tristrips_adj(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_patches(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_lines(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_lines_adj(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_linestrips_adj(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_points(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual void end_draw_primitives();
|
||||
|
|
|
|||
|
|
@ -653,6 +653,12 @@ reset() {
|
|||
Geom::GR_line_strip |
|
||||
Geom::GR_flat_last_vertex;
|
||||
|
||||
#ifndef OPENGLES
|
||||
if (_supports_geometry_shaders) {
|
||||
_supported_geom_rendering |= Geom::GR_adjacency;
|
||||
}
|
||||
#endif
|
||||
|
||||
_supports_point_parameters = false;
|
||||
|
||||
#ifdef OPENGLES_1
|
||||
|
|
@ -4543,6 +4549,68 @@ draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of disconnected triangles with adjacency information.
|
||||
*/
|
||||
#ifndef OPENGLES
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
draw_triangles_adj(const GeomPrimitivePipelineReader *reader, bool force) {
|
||||
// PStatGPUTimer timer(this, _draw_primitive_pcollector,
|
||||
// reader->get_current_thread());
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam() << "draw_triangles_adj: " << *(reader->get_object()) << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
if (_use_sender) {
|
||||
draw_immediate_simple_primitives(reader, GL_TRIANGLES_ADJACENCY);
|
||||
|
||||
} else
|
||||
#endif // SUPPORT_IMMEDIATE_MODE
|
||||
{
|
||||
int num_vertices = reader->get_num_vertices();
|
||||
_vertices_tri_pcollector.add_level(num_vertices);
|
||||
_primitive_batches_tri_pcollector.add_level(1);
|
||||
|
||||
if (reader->is_indexed()) {
|
||||
const unsigned char *client_pointer;
|
||||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_TRIANGLES_ADJACENCY, num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer, _instance_count);
|
||||
} else {
|
||||
_glDrawRangeElements(GL_TRIANGLES_ADJACENCY,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
}
|
||||
} else {
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_TRIANGLES_ADJACENCY,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices, _instance_count);
|
||||
} else {
|
||||
glDrawArrays(GL_TRIANGLES_ADJACENCY,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
#endif // OPENGLES
|
||||
|
||||
/**
|
||||
* Draws a series of triangle strips.
|
||||
*/
|
||||
|
|
@ -4669,6 +4737,128 @@ draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of triangle strips with adjacency information.
|
||||
*/
|
||||
#ifndef OPENGLES
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
draw_tristrips_adj(const GeomPrimitivePipelineReader *reader, bool force) {
|
||||
// PStatGPUTimer timer(this, _draw_primitive_pcollector,
|
||||
// reader->get_current_thread());
|
||||
|
||||
report_my_gl_errors();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam() << "draw_tristrips_adj: " << *(reader->get_object()) << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
if (_use_sender) {
|
||||
draw_immediate_composite_primitives(reader, GL_TRIANGLE_STRIP_ADJACENCY);
|
||||
|
||||
} else
|
||||
#endif // SUPPORT_IMMEDIATE_MODE
|
||||
{
|
||||
if (reader->is_indexed() &&
|
||||
(_supported_geom_rendering & GeomEnums::GR_strip_cut_index) != 0) {
|
||||
// One long line strip, connected by strip cut indices.
|
||||
if (_explicit_primitive_restart) {
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
_glPrimitiveRestartIndex(reader->get_strip_cut_index());
|
||||
}
|
||||
int num_vertices = reader->get_num_vertices();
|
||||
_vertices_tristrip_pcollector.add_level(num_vertices);
|
||||
_primitive_batches_tristrip_pcollector.add_level(1);
|
||||
if (reader->is_indexed()) {
|
||||
const unsigned char *client_pointer;
|
||||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_TRIANGLE_STRIP_ADJACENCY, num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer, _instance_count);
|
||||
} else {
|
||||
_glDrawRangeElements(GL_TRIANGLE_STRIP_ADJACENCY,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
}
|
||||
} else {
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_TRIANGLE_STRIP_ADJACENCY,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices, _instance_count);
|
||||
} else {
|
||||
glDrawArrays(GL_TRIANGLE_STRIP_ADJACENCY,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
}
|
||||
}
|
||||
if (_explicit_primitive_restart) {
|
||||
glDisable(GL_PRIMITIVE_RESTART);
|
||||
}
|
||||
} else {
|
||||
// Send the individual triangle strips, stepping over the degenerate
|
||||
// vertices.
|
||||
CPTA_int ends = reader->get_ends();
|
||||
|
||||
_primitive_batches_tristrip_pcollector.add_level(ends.size());
|
||||
if (reader->is_indexed()) {
|
||||
const unsigned char *client_pointer;
|
||||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
int index_stride = reader->get_index_stride();
|
||||
GeomVertexReader mins(reader->get_mins(), 0);
|
||||
GeomVertexReader maxs(reader->get_maxs(), 0);
|
||||
nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
|
||||
reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
|
||||
|
||||
unsigned int start = 0;
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_tristrip_pcollector.add_level(ends[i] - start);
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_TRIANGLE_STRIP_ADJACENCY, ends[i] - start,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer + start * index_stride,
|
||||
_instance_count);
|
||||
} else {
|
||||
_glDrawRangeElements(GL_TRIANGLE_STRIP_ADJACENCY,
|
||||
mins.get_data1i(), maxs.get_data1i(),
|
||||
ends[i] - start,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
}
|
||||
start = ends[i] + 1;
|
||||
}
|
||||
} else {
|
||||
unsigned int start = 0;
|
||||
int first_vertex = reader->get_first_vertex();
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_tristrip_pcollector.add_level(ends[i] - start);
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_TRIANGLE_STRIP_ADJACENCY, first_vertex + start,
|
||||
ends[i] - start, _instance_count);
|
||||
} else {
|
||||
glDrawArrays(GL_TRIANGLE_STRIP_ADJACENCY, first_vertex + start,
|
||||
ends[i] - start);
|
||||
}
|
||||
start = ends[i] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
#endif // OPENGLES
|
||||
|
||||
/**
|
||||
* Draws a series of triangle fans.
|
||||
*/
|
||||
|
|
@ -4888,6 +5078,66 @@ draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of disconnected line segments with adjacency information.
|
||||
*/
|
||||
#ifndef OPENGLES
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
draw_lines_adj(const GeomPrimitivePipelineReader *reader, bool force) {
|
||||
// PStatGPUTimer timer(this, _draw_primitive_pcollector,
|
||||
// reader->get_current_thread());
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam() << "draw_lines_adj: " << *(reader->get_object()) << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
if (_use_sender) {
|
||||
draw_immediate_simple_primitives(reader, GL_LINES_ADJACENCY);
|
||||
} else
|
||||
#endif // SUPPORT_IMMEDIATE_MODE
|
||||
{
|
||||
int num_vertices = reader->get_num_vertices();
|
||||
_vertices_other_pcollector.add_level(num_vertices);
|
||||
_primitive_batches_other_pcollector.add_level(1);
|
||||
|
||||
if (reader->is_indexed()) {
|
||||
const unsigned char *client_pointer;
|
||||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_LINES_ADJACENCY, num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer, _instance_count);
|
||||
} else {
|
||||
_glDrawRangeElements(GL_LINES_ADJACENCY,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
}
|
||||
} else {
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_LINES_ADJACENCY,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices, _instance_count);
|
||||
} else {
|
||||
glDrawArrays(GL_LINES_ADJACENCY,
|
||||
reader->get_first_vertex(),
|
||||
num_vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
#endif // OPENGLES
|
||||
|
||||
/**
|
||||
* Draws a series of line strips.
|
||||
*/
|
||||
|
|
@ -5010,6 +5260,117 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a series of line strips with adjacency information.
|
||||
*/
|
||||
#ifndef OPENGLES
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
draw_linestrips_adj(const GeomPrimitivePipelineReader *reader, bool force) {
|
||||
// PStatGPUTimer timer(this, _draw_primitive_pcollector,
|
||||
// reader->get_current_thread());
|
||||
|
||||
report_my_gl_errors();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (GLCAT.is_spam()) {
|
||||
GLCAT.spam() << "draw_linestrips_adj: " << *(reader->get_object()) << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
if (_use_sender) {
|
||||
draw_immediate_composite_primitives(reader, GL_LINE_STRIP_ADJACENCY);
|
||||
|
||||
} else
|
||||
#endif // SUPPORT_IMMEDIATE_MODE
|
||||
{
|
||||
if (reader->is_indexed() &&
|
||||
(_supported_geom_rendering & GeomEnums::GR_strip_cut_index) != 0) {
|
||||
// One long line strip, connected by strip cut indices.
|
||||
if (_explicit_primitive_restart) {
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
_glPrimitiveRestartIndex(reader->get_strip_cut_index());
|
||||
}
|
||||
|
||||
int num_vertices = reader->get_num_vertices();
|
||||
_vertices_other_pcollector.add_level(num_vertices);
|
||||
_primitive_batches_other_pcollector.add_level(1);
|
||||
|
||||
const unsigned char *client_pointer;
|
||||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_LINE_STRIP_ADJACENCY, num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer, _instance_count);
|
||||
} else {
|
||||
_glDrawRangeElements(GL_LINE_STRIP_ADJACENCY,
|
||||
reader->get_min_vertex(),
|
||||
reader->get_max_vertex(),
|
||||
num_vertices,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer);
|
||||
}
|
||||
|
||||
if (_explicit_primitive_restart) {
|
||||
glDisable(GL_PRIMITIVE_RESTART);
|
||||
}
|
||||
} else {
|
||||
// Send the individual line strips, stepping over the strip-cut indices.
|
||||
CPTA_int ends = reader->get_ends();
|
||||
|
||||
_primitive_batches_other_pcollector.add_level(ends.size());
|
||||
if (reader->is_indexed()) {
|
||||
const unsigned char *client_pointer;
|
||||
if (!setup_primitive(client_pointer, reader, force)) {
|
||||
return false;
|
||||
}
|
||||
int index_stride = reader->get_index_stride();
|
||||
GeomVertexReader mins(reader->get_mins(), 0);
|
||||
GeomVertexReader maxs(reader->get_maxs(), 0);
|
||||
nassertr(reader->get_mins()->get_num_rows() == (int)ends.size() &&
|
||||
reader->get_maxs()->get_num_rows() == (int)ends.size(), false);
|
||||
|
||||
unsigned int start = 0;
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_other_pcollector.add_level(ends[i] - start);
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawElementsInstanced(GL_LINE_STRIP_ADJACENCY, ends[i] - start,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer + start * index_stride,
|
||||
_instance_count);
|
||||
} else {
|
||||
_glDrawRangeElements(GL_LINE_STRIP_ADJACENCY,
|
||||
mins.get_data1i(), maxs.get_data1i(),
|
||||
ends[i] - start,
|
||||
get_numeric_type(reader->get_index_type()),
|
||||
client_pointer + start * index_stride);
|
||||
}
|
||||
start = ends[i] + 1;
|
||||
}
|
||||
} else {
|
||||
unsigned int start = 0;
|
||||
int first_vertex = reader->get_first_vertex();
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_other_pcollector.add_level(ends[i] - start);
|
||||
if (_supports_geometry_instancing && _instance_count > 0) {
|
||||
_glDrawArraysInstanced(GL_LINE_STRIP_ADJACENCY, first_vertex + start,
|
||||
ends[i] - start, _instance_count);
|
||||
} else {
|
||||
glDrawArrays(GL_LINE_STRIP_ADJACENCY, first_vertex + start, ends[i] - start);
|
||||
}
|
||||
start = ends[i] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
#endif // OPENGLES
|
||||
|
||||
/**
|
||||
* Draws a series of disconnected points.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -288,16 +288,32 @@ public:
|
|||
bool force);
|
||||
virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
#ifndef OPENGLES
|
||||
virtual bool draw_triangles_adj(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
#endif
|
||||
virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
#ifndef OPENGLES
|
||||
virtual bool draw_tristrips_adj(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
#endif
|
||||
virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_patches(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual bool draw_lines(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
#ifndef OPENGLES
|
||||
virtual bool draw_lines_adj(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
#endif
|
||||
virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
#ifndef OPENGLES
|
||||
virtual bool draw_linestrips_adj(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
#endif
|
||||
virtual bool draw_points(const GeomPrimitivePipelineReader *reader,
|
||||
bool force);
|
||||
virtual void end_draw_primitives();
|
||||
|
|
|
|||
|
|
@ -20,11 +20,15 @@
|
|||
#include "geomMunger.h"
|
||||
#include "geomPrimitive.h"
|
||||
#include "geomTriangles.h"
|
||||
#include "geomTrianglesAdjacency.h"
|
||||
#include "geomTristrips.h"
|
||||
#include "geomTristripsAdjacency.h"
|
||||
#include "geomTrifans.h"
|
||||
#include "geomPatches.h"
|
||||
#include "geomLines.h"
|
||||
#include "geomLinesAdjacency.h"
|
||||
#include "geomLinestrips.h"
|
||||
#include "geomLinestripsAdjacency.h"
|
||||
#include "geomPoints.h"
|
||||
#include "geomVertexArrayData.h"
|
||||
#include "geomVertexArrayFormat.h"
|
||||
|
|
@ -546,14 +550,18 @@ ConfigureFn(config_gobj) {
|
|||
GeomPipelineReader::init_type();
|
||||
GeomContext::init_type();
|
||||
GeomLines::init_type();
|
||||
GeomLinesAdjacency::init_type();
|
||||
GeomLinestrips::init_type();
|
||||
GeomLinestripsAdjacency::init_type();
|
||||
GeomMunger::init_type();
|
||||
GeomPoints::init_type();
|
||||
GeomPrimitive::init_type();
|
||||
GeomPrimitivePipelineReader::init_type();
|
||||
GeomTriangles::init_type();
|
||||
GeomTrianglesAdjacency::init_type();
|
||||
GeomTrifans::init_type();
|
||||
GeomTristrips::init_type();
|
||||
GeomTristripsAdjacency::init_type();
|
||||
GeomPatches::init_type();
|
||||
GeomVertexArrayData::init_type();
|
||||
GeomVertexArrayDataHandle::init_type();
|
||||
|
|
@ -601,11 +609,15 @@ ConfigureFn(config_gobj) {
|
|||
// factory
|
||||
Geom::register_with_read_factory();
|
||||
GeomLines::register_with_read_factory();
|
||||
GeomLinesAdjacency::register_with_read_factory();
|
||||
GeomLinestrips::register_with_read_factory();
|
||||
GeomLinestripsAdjacency::register_with_read_factory();
|
||||
GeomPoints::register_with_read_factory();
|
||||
GeomTriangles::register_with_read_factory();
|
||||
GeomTrianglesAdjacency::register_with_read_factory();
|
||||
GeomTrifans::register_with_read_factory();
|
||||
GeomTristrips::register_with_read_factory();
|
||||
GeomTristripsAdjacency::register_with_read_factory();
|
||||
GeomPatches::register_with_read_factory();
|
||||
GeomVertexArrayData::register_with_read_factory();
|
||||
GeomVertexArrayFormat::register_with_read_factory();
|
||||
|
|
|
|||
|
|
@ -212,6 +212,17 @@ make_patches() const {
|
|||
return new_geom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Geom with each primitive converted into a corresponding
|
||||
* version with adjacency information.
|
||||
*/
|
||||
INLINE PT(Geom) Geom::
|
||||
make_adjacency() const {
|
||||
PT(Geom) new_geom = make_copy();
|
||||
new_geom->make_adjacency_in_place();
|
||||
return new_geom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequence number which is guaranteed to change at least every time
|
||||
* any of the primitives in the Geom is modified, or the set of primitives is
|
||||
|
|
|
|||
|
|
@ -834,6 +834,42 @@ make_patches_in_place() {
|
|||
nassertv(all_is_valid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the GeomPrimitives within this Geom with corresponding versions
|
||||
* with adjacency information. See GeomPrimitive::make_adjacency().
|
||||
*
|
||||
* Don't call this in a downstream thread unless you don't mind it blowing
|
||||
* away other changes you might have recently made in an upstream thread.
|
||||
*/
|
||||
void Geom::
|
||||
make_adjacency_in_place() {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDWriter cdata(_cycler, true, current_thread);
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool all_is_valid = true;
|
||||
#endif
|
||||
Primitives::iterator pi;
|
||||
for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
|
||||
CPT(GeomPrimitive) new_prim = (*pi).get_read_pointer(current_thread)->make_adjacency();
|
||||
if (new_prim != nullptr) {
|
||||
(*pi) = (GeomPrimitive *)new_prim.p();
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!new_prim->check_valid(cdata->_data.get_read_pointer(current_thread))) {
|
||||
all_is_valid = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
cdata->_modified = Geom::get_next_modified();
|
||||
reset_geom_rendering(cdata);
|
||||
clear_cache_stage(current_thread);
|
||||
|
||||
nassertv(all_is_valid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the primitives from the indicated Geom into this one. This does
|
||||
* require that both Geoms contain the same fundamental type primitives, both
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ PUBLISHED:
|
|||
INLINE PT(Geom) make_points() const;
|
||||
INLINE PT(Geom) make_lines() const;
|
||||
INLINE PT(Geom) make_patches() const;
|
||||
INLINE PT(Geom) make_adjacency() const;
|
||||
|
||||
void decompose_in_place();
|
||||
void doubleside_in_place();
|
||||
|
|
@ -115,6 +116,7 @@ PUBLISHED:
|
|||
void make_points_in_place();
|
||||
void make_lines_in_place();
|
||||
void make_patches_in_place();
|
||||
void make_adjacency_in_place();
|
||||
|
||||
virtual bool copy_primitives_from(const Geom *other);
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,9 @@ PUBLISHED:
|
|||
// If a particular non-fill polygon mode is used.
|
||||
GR_render_mode_wireframe= 0x40000,
|
||||
GR_render_mode_point = 0x80000,
|
||||
|
||||
// The primitive has adjacency information.
|
||||
GR_adjacency = 0x100000,
|
||||
};
|
||||
|
||||
// The shade model specifies whether the per-vertex colors and normals
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "graphicsStateGuardianBase.h"
|
||||
#include "geomVertexReader.h"
|
||||
#include "geomVertexWriter.h"
|
||||
#include "geomLinesAdjacency.h"
|
||||
|
||||
TypeHandle GeomLines::_type_handle;
|
||||
|
||||
|
|
@ -67,6 +68,67 @@ get_primitive_type() const {
|
|||
return PT_lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds adjacency information to this primitive. May return null if this type
|
||||
* of geometry does not support adjacency information.
|
||||
*/
|
||||
CPT(GeomPrimitive) GeomLines::
|
||||
make_adjacency() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(GeomLinesAdjacency) adj = new GeomLinesAdjacency(get_usage_hint());
|
||||
|
||||
GeomPrimitivePipelineReader from(this, current_thread);
|
||||
int num_vertices = from.get_num_vertices();
|
||||
|
||||
PT(GeomVertexArrayData) new_vertices = adj->make_index_data();
|
||||
new_vertices->set_num_rows(num_vertices * 2);
|
||||
|
||||
// First, build a map of each vertex to its next vertex, and another map
|
||||
// doing the exact reverse. Note that this only considers lines that are
|
||||
// ordered the same way as being connected; we may need to change this.
|
||||
map<int, int> forward_map, reverse_map;
|
||||
for (int i = 0; i < num_vertices; i += 2) {
|
||||
int v0 = from.get_vertex(i);
|
||||
int v1 = from.get_vertex(i + 1);
|
||||
forward_map[v0] = v1;
|
||||
reverse_map[v1] = v0;
|
||||
}
|
||||
|
||||
// Now build up the new vertex data. For each line, we insert the
|
||||
// appropriate connecting vertex.
|
||||
{
|
||||
GeomVertexWriter to(new_vertices, 0);
|
||||
for (int i = 0; i < num_vertices; i += 2) {
|
||||
int v0 = from.get_vertex(i);
|
||||
int v1 = from.get_vertex(i + 1);
|
||||
|
||||
auto it = reverse_map.find(v0);
|
||||
if (it != reverse_map.end()) {
|
||||
to.set_data1i(it->second);
|
||||
} else {
|
||||
// Um, no adjoining line segment? Just repeat the vertex, I guess.
|
||||
to.set_data1i(v0);
|
||||
}
|
||||
|
||||
to.set_data1i(v0);
|
||||
to.set_data1i(v1);
|
||||
|
||||
// Do the same for the second vertex in the line.
|
||||
it = forward_map.find(v1);
|
||||
if (it != forward_map.end()) {
|
||||
to.set_data1i(it->second);
|
||||
} else {
|
||||
to.set_data1i(v1);
|
||||
}
|
||||
}
|
||||
|
||||
nassertr(to.is_at_end(), nullptr);
|
||||
}
|
||||
|
||||
adj->set_vertices(move(new_vertices));
|
||||
return adj.p();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the primitive type is a simple type in which all primitives have the
|
||||
* same number of vertices, like lines, returns the number of vertices per
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ public:
|
|||
virtual PT(GeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
|
||||
CPT(GeomPrimitive) make_adjacency() const;
|
||||
|
||||
virtual int get_num_vertices_per_primitive() const;
|
||||
virtual int get_min_num_vertices_per_primitive() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file geomLinesAdjacency.cxx
|
||||
* @author rdb
|
||||
* @date 2018-03-01
|
||||
*/
|
||||
|
||||
#include "geomLinesAdjacency.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "geomVertexReader.h"
|
||||
#include "geomVertexWriter.h"
|
||||
|
||||
TypeHandle GeomLinesAdjacency::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomLinesAdjacency::
|
||||
GeomLinesAdjacency(GeomEnums::UsageHint usage_hint) :
|
||||
GeomPrimitive(usage_hint)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomLinesAdjacency::
|
||||
GeomLinesAdjacency(const GeomLinesAdjacency ©) :
|
||||
GeomPrimitive(copy)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomLinesAdjacency::
|
||||
~GeomLinesAdjacency() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PT(GeomPrimitive) GeomLinesAdjacency::
|
||||
make_copy() const {
|
||||
return new GeomLinesAdjacency(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fundamental rendering type of this primitive: whether it is
|
||||
* points, lines, or polygons.
|
||||
*
|
||||
* This is used to set up the appropriate antialiasing settings when
|
||||
* AntialiasAttrib::M_auto is in effect; it also implies the type of primitive
|
||||
* that will be produced when decompose() is called.
|
||||
*/
|
||||
GeomPrimitive::PrimitiveType GeomLinesAdjacency::
|
||||
get_primitive_type() const {
|
||||
return PT_lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of GeomRendering bits that represent the rendering
|
||||
* properties required to properly render this primitive.
|
||||
*/
|
||||
int GeomLinesAdjacency::
|
||||
get_geom_rendering() const {
|
||||
return GeomPrimitive::get_geom_rendering() | GR_adjacency;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the primitive type is a simple type in which all primitives have the
|
||||
* same number of vertices, like lines, returns the number of vertices per
|
||||
* primitive. If the primitive type is a more complex type in which different
|
||||
* primitives might have different numbers of vertices, for instance a line
|
||||
* strip, returns 0.
|
||||
*/
|
||||
int GeomLinesAdjacency::
|
||||
get_num_vertices_per_primitive() const {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum number of vertices that must be added before
|
||||
* close_primitive() may legally be called.
|
||||
*/
|
||||
int GeomLinesAdjacency::
|
||||
get_min_num_vertices_per_primitive() const {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the appropriate method on the GSG to draw the primitive.
|
||||
*/
|
||||
bool GeomLinesAdjacency::
|
||||
draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
|
||||
bool force) const {
|
||||
return gsg->draw_lines_adj(reader, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the BamReader how to create objects of type Geom.
|
||||
*/
|
||||
void GeomLinesAdjacency::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by the BamReader's factory when a new object of
|
||||
* type Geom is encountered in the Bam file. It should create the Geom and
|
||||
* extract its information from the file.
|
||||
*/
|
||||
TypedWritable *GeomLinesAdjacency::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
GeomLinesAdjacency *object = new GeomLinesAdjacency(UH_unspecified);
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
object->fillin(scan, manager);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file geomLinesAdjacency.h
|
||||
* @author rdb
|
||||
* @date 2018-03-01
|
||||
*/
|
||||
|
||||
#ifndef GEOMLINESADJACENCY_H
|
||||
#define GEOMLINESADJACENCY_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "geomPrimitive.h"
|
||||
|
||||
/**
|
||||
* Defines a series of disconnected line segments with adjacency information,
|
||||
* for use with geometry shaders.
|
||||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomLinesAdjacency : public GeomPrimitive {
|
||||
PUBLISHED:
|
||||
explicit GeomLinesAdjacency(UsageHint usage_hint);
|
||||
GeomLinesAdjacency(const GeomLinesAdjacency ©);
|
||||
virtual ~GeomLinesAdjacency();
|
||||
ALLOC_DELETED_CHAIN(GeomLinesAdjacency);
|
||||
|
||||
public:
|
||||
virtual PT(GeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
virtual int get_geom_rendering() const;
|
||||
|
||||
virtual int get_num_vertices_per_primitive() const;
|
||||
virtual int get_min_num_vertices_per_primitive() const;
|
||||
|
||||
public:
|
||||
virtual bool draw(GraphicsStateGuardianBase *gsg,
|
||||
const GeomPrimitivePipelineReader *reader,
|
||||
bool force) const;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
GeomPrimitive::init_type();
|
||||
register_type(_type_handle, "GeomLinesAdjacency",
|
||||
GeomPrimitive::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class Geom;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "geomLinestripsAdjacency.h"
|
||||
|
||||
TypeHandle GeomLinestrips::_type_handle;
|
||||
|
||||
|
|
@ -84,6 +85,86 @@ get_geom_rendering() const {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds adjacency information to this primitive. May return null if this type
|
||||
* of geometry does not support adjacency information.
|
||||
*/
|
||||
CPT(GeomPrimitive) GeomLinestrips::
|
||||
make_adjacency() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(GeomLinestripsAdjacency) adj = new GeomLinestripsAdjacency(get_usage_hint());
|
||||
|
||||
GeomPrimitivePipelineReader from(this, current_thread);
|
||||
int num_vertices = from.get_num_vertices();
|
||||
CPTA_int ends = get_ends();
|
||||
|
||||
const int num_unused = 1;
|
||||
|
||||
// First, build a map of each vertex to its next vertex, and another map
|
||||
// doing the exact reverse.
|
||||
map<int, int> forward_map, reverse_map;
|
||||
int vi = -num_unused;
|
||||
int li = 0;
|
||||
while (li < (int)ends.size()) {
|
||||
// Skip unused vertices between linestrips.
|
||||
vi += num_unused;
|
||||
int end = ends[li];
|
||||
nassertr(vi + 1 <= end, nullptr);
|
||||
int v0 = from.get_vertex(vi++);
|
||||
while (vi < end) {
|
||||
int v1 = from.get_vertex(vi++);
|
||||
forward_map[v0] = v1;
|
||||
reverse_map[v1] = v0;
|
||||
v0 = v1;
|
||||
}
|
||||
++li;
|
||||
}
|
||||
nassertr(vi == num_vertices, nullptr);
|
||||
|
||||
// Now build up the new vertex data. For each linestrip, we prepend and
|
||||
// append the appropriate connecting vertices.
|
||||
vi = -num_unused;
|
||||
li = 0;
|
||||
while (li < (int)ends.size()) {
|
||||
// Skip unused vertices between linestrips.
|
||||
vi += num_unused;
|
||||
int end = ends[li];
|
||||
nassertr(vi + 1 <= end, nullptr);
|
||||
|
||||
// Look for the line segment connected to the beginning of this strip.
|
||||
int v0 = from.get_vertex(vi++);
|
||||
auto it = reverse_map.find(v0);
|
||||
if (it != reverse_map.end()) {
|
||||
adj->add_vertex(it->second);
|
||||
} else {
|
||||
// Um, no adjoining line segment? Just repeat the vertex, I guess.
|
||||
adj->add_vertex(v0);
|
||||
}
|
||||
|
||||
// Add the actual vertices in the strip.
|
||||
adj->add_vertex(v0);
|
||||
int v1;
|
||||
while (vi < end) {
|
||||
v1 = from.get_vertex(vi++);
|
||||
adj->add_vertex(v1);
|
||||
}
|
||||
|
||||
// Do the same for the last vertex in the strip.
|
||||
it = forward_map.find(v1);
|
||||
if (it != forward_map.end()) {
|
||||
adj->add_vertex(it->second);
|
||||
} else {
|
||||
adj->add_vertex(v1);
|
||||
}
|
||||
|
||||
adj->close_primitive();
|
||||
++li;
|
||||
}
|
||||
nassertr(vi == num_vertices, nullptr);
|
||||
|
||||
return adj.p();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum number of vertices that must be added before
|
||||
* close_primitive() may legally be called.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ public:
|
|||
virtual PT(GeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
virtual int get_geom_rendering() const;
|
||||
|
||||
CPT(GeomPrimitive) make_adjacency() const;
|
||||
|
||||
virtual int get_min_num_vertices_per_primitive() const;
|
||||
virtual int get_num_unused_vertices_per_primitive() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,210 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file geomLinestripsAdjacency.cxx
|
||||
* @author rdb
|
||||
* @date 2018-03-01
|
||||
*/
|
||||
|
||||
#include "geomLinestripsAdjacency.h"
|
||||
#include "geomLines.h"
|
||||
#include "geomVertexRewriter.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
|
||||
TypeHandle GeomLinestripsAdjacency::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomLinestripsAdjacency::
|
||||
GeomLinestripsAdjacency(GeomEnums::UsageHint usage_hint) :
|
||||
GeomPrimitive(usage_hint)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomLinestripsAdjacency::
|
||||
GeomLinestripsAdjacency(const GeomLinestripsAdjacency ©) :
|
||||
GeomPrimitive(copy)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomLinestripsAdjacency::
|
||||
~GeomLinestripsAdjacency() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PT(GeomPrimitive) GeomLinestripsAdjacency::
|
||||
make_copy() const {
|
||||
return new GeomLinestripsAdjacency(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fundamental rendering type of this primitive: whether it is
|
||||
* points, lines, or polygons.
|
||||
*
|
||||
* This is used to set up the appropriate antialiasing settings when
|
||||
* AntialiasAttrib::M_auto is in effect; it also implies the type of primitive
|
||||
* that will be produced when decompose() is called.
|
||||
*/
|
||||
GeomPrimitive::PrimitiveType GeomLinestripsAdjacency::
|
||||
get_primitive_type() const {
|
||||
return PT_lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of GeomRendering bits that represent the rendering
|
||||
* properties required to properly render this primitive.
|
||||
*/
|
||||
int GeomLinestripsAdjacency::
|
||||
get_geom_rendering() const {
|
||||
if (is_indexed()) {
|
||||
if (get_num_primitives() > 1) {
|
||||
return GR_line_strip | GR_indexed_other | GR_strip_cut_index | GR_adjacency;
|
||||
} else {
|
||||
return GR_line_strip | GR_indexed_other | GR_adjacency;
|
||||
}
|
||||
} else {
|
||||
return GR_line_strip | GR_adjacency;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum number of vertices that must be added before
|
||||
* close_primitive() may legally be called.
|
||||
*/
|
||||
int GeomLinestripsAdjacency::
|
||||
get_min_num_vertices_per_primitive() const {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of vertices that are added between primitives that
|
||||
* aren't, strictly speaking, part of the primitives themselves. This is
|
||||
* used, for instance, to define degenerate triangles to connect otherwise
|
||||
* disconnected triangle strips.
|
||||
*/
|
||||
int GeomLinestripsAdjacency::
|
||||
get_num_unused_vertices_per_primitive() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the appropriate method on the GSG to draw the primitive.
|
||||
*/
|
||||
bool GeomLinestripsAdjacency::
|
||||
draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
|
||||
bool force) const {
|
||||
return gsg->draw_linestrips_adj(reader, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decomposes a complex primitive type into a simpler primitive type, for
|
||||
* instance line strips to lines, and returns a pointer to the new primitive
|
||||
* definition. If the decomposition cannot be performed, this might return
|
||||
* the original object.
|
||||
*
|
||||
* This method is useful for application code that wants to iterate through
|
||||
* the set of lines on the primitive without having to write handlers for each
|
||||
* possible kind of primitive type.
|
||||
*/
|
||||
CPT(GeomPrimitive) GeomLinestripsAdjacency::
|
||||
decompose_impl() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(GeomLinesAdjacency) lines = new GeomLinesAdjacency(get_usage_hint());
|
||||
lines->set_shade_model(get_shade_model());
|
||||
|
||||
GeomPrimitivePipelineReader from(this, current_thread);
|
||||
int num_vertices = from.get_num_vertices();
|
||||
CPTA_int ends = get_ends();
|
||||
|
||||
const int num_unused = 1;
|
||||
|
||||
int vi = -num_unused;
|
||||
int li = 0;
|
||||
while (li < (int)ends.size()) {
|
||||
// Skip unused vertices between tristrips.
|
||||
vi += num_unused;
|
||||
int end = ends[li];
|
||||
nassertr(vi + 3 <= end, lines.p());
|
||||
int v0 = from.get_vertex(vi++);
|
||||
int v1 = from.get_vertex(vi++);
|
||||
int v2 = from.get_vertex(vi++);
|
||||
while (vi < end) {
|
||||
int v3 = from.get_vertex(vi++);
|
||||
lines->add_vertex(v0);
|
||||
lines->add_vertex(v1);
|
||||
lines->add_vertex(v2);
|
||||
lines->add_vertex(v3);
|
||||
v0 = v1;
|
||||
v1 = v2;
|
||||
v2 = v3;
|
||||
}
|
||||
++li;
|
||||
}
|
||||
nassertr(vi == num_vertices, nullptr);
|
||||
|
||||
return lines.p();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be redefined to return true in any primitive that implements
|
||||
* append_unused_vertices().
|
||||
*/
|
||||
bool GeomLinestripsAdjacency::
|
||||
requires_unused_vertices() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new primitive is begun (other than the first primitive), this
|
||||
* should add some degenerate vertices between primitives, if the primitive
|
||||
* type requires that. The second parameter is the first vertex that begins
|
||||
* the new primitive.
|
||||
*/
|
||||
void GeomLinestripsAdjacency::
|
||||
append_unused_vertices(GeomVertexArrayData *vertices, int vertex) {
|
||||
GeomVertexWriter to(vertices, 0);
|
||||
to.set_row_unsafe(vertices->get_num_rows());
|
||||
to.add_data1i(get_strip_cut_index());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the BamReader how to create objects of type Geom.
|
||||
*/
|
||||
void GeomLinestripsAdjacency::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by the BamReader's factory when a new object of
|
||||
* type Geom is encountered in the Bam file. It should create the Geom and
|
||||
* extract its information from the file.
|
||||
*/
|
||||
TypedWritable *GeomLinestripsAdjacency::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
GeomLinestripsAdjacency *object = new GeomLinestripsAdjacency(UH_unspecified);
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
object->fillin(scan, manager);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file geomLinestripsAdjacency.h
|
||||
* @author rdb
|
||||
* @date 2018-03-01
|
||||
*/
|
||||
|
||||
#ifndef GEOMLINESTRIPSADJACENCY_H
|
||||
#define GEOMLINESTRIPSADJACENCY_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "geomPrimitive.h"
|
||||
|
||||
/**
|
||||
* Defines a series of line strips.
|
||||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomLinestripsAdjacency : public GeomPrimitive {
|
||||
PUBLISHED:
|
||||
explicit GeomLinestripsAdjacency(UsageHint usage_hint);
|
||||
GeomLinestripsAdjacency(const GeomLinestripsAdjacency ©);
|
||||
virtual ~GeomLinestripsAdjacency();
|
||||
ALLOC_DELETED_CHAIN(GeomLinestripsAdjacency);
|
||||
|
||||
public:
|
||||
virtual PT(GeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
virtual int get_geom_rendering() const;
|
||||
|
||||
virtual int get_min_num_vertices_per_primitive() const;
|
||||
virtual int get_num_unused_vertices_per_primitive() const;
|
||||
|
||||
public:
|
||||
virtual bool draw(GraphicsStateGuardianBase *gsg,
|
||||
const GeomPrimitivePipelineReader *reader,
|
||||
bool force) const;
|
||||
|
||||
protected:
|
||||
virtual CPT(GeomPrimitive) decompose_impl() const;
|
||||
virtual bool requires_unused_vertices() const;
|
||||
virtual void append_unused_vertices(GeomVertexArrayData *vertices,
|
||||
int vertex);
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
GeomPrimitive::init_type();
|
||||
register_type(_type_handle, "GeomLinestripsAdjacency",
|
||||
GeomPrimitive::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class Geom;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1021,6 +1021,15 @@ make_patches() const {
|
|||
return patches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds adjacency information to this primitive. May return null if this type
|
||||
* of geometry does not support adjacency information.
|
||||
*/
|
||||
CPT(GeomPrimitive) GeomPrimitive::
|
||||
make_adjacency() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes consumed by the primitive and its index
|
||||
* table(s).
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ PUBLISHED:
|
|||
CPT(GeomPrimitive) make_points() const;
|
||||
CPT(GeomPrimitive) make_lines() const;
|
||||
CPT(GeomPrimitive) make_patches() const;
|
||||
virtual CPT(GeomPrimitive) make_adjacency() const;
|
||||
|
||||
int get_num_bytes() const;
|
||||
INLINE int get_data_size_bytes() const;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "geomTrianglesAdjacency.h"
|
||||
|
||||
TypeHandle GeomTriangles::_type_handle;
|
||||
|
||||
|
|
@ -66,6 +67,76 @@ get_primitive_type() const {
|
|||
return PT_polygons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds adjacency information to this primitive. May return null if this type
|
||||
* of geometry does not support adjacency information.
|
||||
*/
|
||||
CPT(GeomPrimitive) GeomTriangles::
|
||||
make_adjacency() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(GeomTrianglesAdjacency) adj = new GeomTrianglesAdjacency(get_usage_hint());
|
||||
|
||||
GeomPrimitivePipelineReader from(this, current_thread);
|
||||
int num_vertices = from.get_num_vertices();
|
||||
|
||||
PT(GeomVertexArrayData) new_vertices = adj->make_index_data();
|
||||
new_vertices->set_num_rows(num_vertices * 2);
|
||||
|
||||
// First, build a map of each triangle's halfedges to its opposing vertices.
|
||||
map<pair<int, int>, int> edge_map;
|
||||
for (int i = 0; i < num_vertices; i += 3) {
|
||||
int v0 = from.get_vertex(i);
|
||||
int v1 = from.get_vertex(i + 1);
|
||||
int v2 = from.get_vertex(i + 2);
|
||||
edge_map[make_pair(v0, v1)] = v2;
|
||||
edge_map[make_pair(v1, v2)] = v0;
|
||||
edge_map[make_pair(v2, v0)] = v1;
|
||||
}
|
||||
|
||||
// Now build up the new vertex data. For each edge, we insert the
|
||||
// appropriate connecting vertex.
|
||||
{
|
||||
GeomVertexWriter to(new_vertices, 0);
|
||||
for (int i = 0; i < num_vertices; i += 3) {
|
||||
int v0 = from.get_vertex(i);
|
||||
int v1 = from.get_vertex(i + 1);
|
||||
int v2 = from.get_vertex(i + 2);
|
||||
|
||||
// Get the third vertex of the triangle adjoining this edge.
|
||||
to.set_data1(v0);
|
||||
auto it = edge_map.find(make_pair(v1, v0));
|
||||
if (it != edge_map.end()) {
|
||||
to.set_data1i(it->second);
|
||||
} else {
|
||||
// Um, no adjoining triangle? Just repeat the vertex, I guess.
|
||||
to.set_data1i(v0);
|
||||
}
|
||||
|
||||
// Do the same for the other two edges.
|
||||
to.set_data1(v1);
|
||||
it = edge_map.find(make_pair(v2, v1));
|
||||
if (it != edge_map.end()) {
|
||||
to.set_data1i(it->second);
|
||||
} else {
|
||||
to.set_data1i(v1);
|
||||
}
|
||||
|
||||
to.set_data1(v2);
|
||||
it = edge_map.find(make_pair(v0, v2));
|
||||
if (it != edge_map.end()) {
|
||||
to.set_data1i(it->second);
|
||||
} else {
|
||||
to.set_data1i(v2);
|
||||
}
|
||||
}
|
||||
|
||||
nassertr(to.is_at_end(), nullptr);
|
||||
}
|
||||
|
||||
adj->set_vertices(move(new_vertices));
|
||||
return adj.p();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the primitive type is a simple type in which all primitives have the
|
||||
* same number of vertices, like triangles, returns the number of vertices per
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ public:
|
|||
virtual PT(GeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
|
||||
CPT(GeomPrimitive) make_adjacency() const;
|
||||
|
||||
virtual int get_num_vertices_per_primitive() const;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,195 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file geomTrianglesAdjacency.cxx
|
||||
* @author rdb
|
||||
* @date 2018-03-01
|
||||
*/
|
||||
|
||||
#include "geomTrianglesAdjacency.h"
|
||||
#include "geomVertexRewriter.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
|
||||
TypeHandle GeomTrianglesAdjacency::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomTrianglesAdjacency::
|
||||
GeomTrianglesAdjacency(GeomTrianglesAdjacency::UsageHint usage_hint) :
|
||||
GeomPrimitive(usage_hint)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomTrianglesAdjacency::
|
||||
GeomTrianglesAdjacency(const GeomTrianglesAdjacency ©) :
|
||||
GeomPrimitive(copy)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomTrianglesAdjacency::
|
||||
~GeomTrianglesAdjacency() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PT(GeomPrimitive) GeomTrianglesAdjacency::
|
||||
make_copy() const {
|
||||
return new GeomTrianglesAdjacency(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fundamental rendering type of this primitive: whether it is
|
||||
* points, lines, or polygons.
|
||||
*
|
||||
* This is used to set up the appropriate antialiasing settings when
|
||||
* AntialiasAttrib::M_auto is in effect; it also implies the type of primitive
|
||||
* that will be produced when decompose() is called.
|
||||
*/
|
||||
GeomPrimitive::PrimitiveType GeomTrianglesAdjacency::
|
||||
get_primitive_type() const {
|
||||
return PT_polygons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of GeomRendering bits that represent the rendering
|
||||
* properties required to properly render this primitive.
|
||||
*/
|
||||
int GeomTrianglesAdjacency::
|
||||
get_geom_rendering() const {
|
||||
return GeomPrimitive::get_geom_rendering() | GR_adjacency;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the primitive type is a simple type in which all primitives have the
|
||||
* same number of vertices, like triangles, returns the number of vertices per
|
||||
* primitive. If the primitive type is a more complex type in which different
|
||||
* primitives might have different numbers of vertices, for instance a
|
||||
* triangle strip, returns 0.
|
||||
*/
|
||||
int GeomTrianglesAdjacency::
|
||||
get_num_vertices_per_primitive() const {
|
||||
return 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the appropriate method on the GSG to draw the primitive.
|
||||
*/
|
||||
bool GeomTrianglesAdjacency::
|
||||
draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
|
||||
bool force) const {
|
||||
return gsg->draw_triangles_adj(reader, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* The virtual implementation of doubleside().
|
||||
*/
|
||||
CPT(GeomPrimitive) GeomTrianglesAdjacency::
|
||||
doubleside_impl() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(GeomTrianglesAdjacency) reversed = new GeomTrianglesAdjacency(*this);
|
||||
|
||||
GeomPrimitivePipelineReader from(this, current_thread);
|
||||
|
||||
// This is like reverse(), except we don't clear the vertices first. That
|
||||
// way we double the vertices up.
|
||||
|
||||
// First, rotate the original copy, if necessary, so the flat-firstflat-last
|
||||
// nature of the vertices is consistent throughout the primitive.
|
||||
bool needs_rotate = false;
|
||||
switch (from.get_shade_model()) {
|
||||
case SM_flat_first_vertex:
|
||||
case SM_flat_last_vertex:
|
||||
reversed = (GeomTrianglesAdjacency *)DCAST(GeomTrianglesAdjacency, reversed->rotate());
|
||||
needs_rotate = true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Now append all the new vertices, in reverse order.
|
||||
for (int i = from.get_num_vertices() - 1; i >= 0; --i) {
|
||||
reversed->add_vertex(from.get_vertex(i));
|
||||
}
|
||||
|
||||
// Finally, re-rotate the whole thing to get back to the original shade
|
||||
// model.
|
||||
if (needs_rotate) {
|
||||
reversed = (GeomTrianglesAdjacency *)DCAST(GeomTrianglesAdjacency, reversed->rotate());
|
||||
}
|
||||
|
||||
return reversed.p();
|
||||
}
|
||||
|
||||
/**
|
||||
* The virtual implementation of reverse().
|
||||
*/
|
||||
CPT(GeomPrimitive) GeomTrianglesAdjacency::
|
||||
reverse_impl() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(GeomTrianglesAdjacency) reversed = new GeomTrianglesAdjacency(*this);
|
||||
|
||||
GeomPrimitivePipelineReader from(this, current_thread);
|
||||
reversed->clear_vertices();
|
||||
|
||||
for (int i = from.get_num_vertices() - 1; i >= 0; --i) {
|
||||
reversed->add_vertex(from.get_vertex(i));
|
||||
}
|
||||
|
||||
switch (from.get_shade_model()) {
|
||||
case SM_flat_first_vertex:
|
||||
reversed->set_shade_model(SM_flat_last_vertex);
|
||||
reversed = (GeomTrianglesAdjacency *)DCAST(GeomTrianglesAdjacency, reversed->rotate());
|
||||
break;
|
||||
|
||||
case SM_flat_last_vertex:
|
||||
reversed->set_shade_model(SM_flat_first_vertex);
|
||||
reversed = (GeomTrianglesAdjacency *)DCAST(GeomTrianglesAdjacency, reversed->rotate());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return reversed.p();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the BamReader how to create objects of type Geom.
|
||||
*/
|
||||
void GeomTrianglesAdjacency::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by the BamReader's factory when a new object of
|
||||
* type Geom is encountered in the Bam file. It should create the Geom and
|
||||
* extract its information from the file.
|
||||
*/
|
||||
TypedWritable *GeomTrianglesAdjacency::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
GeomTrianglesAdjacency *object = new GeomTrianglesAdjacency(UH_unspecified);
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
object->fillin(scan, manager);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file geomTrianglesAdjacency.h
|
||||
* @author rdb
|
||||
* @date 2018-03-01
|
||||
*/
|
||||
|
||||
#ifndef GEOMTRIANGLESADJACENCY_H
|
||||
#define GEOMTRIANGLESADJACENCY_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "geomPrimitive.h"
|
||||
|
||||
/**
|
||||
* Defines a series of disconnected triangles, with adjacency information.
|
||||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomTrianglesAdjacency : public GeomPrimitive {
|
||||
PUBLISHED:
|
||||
explicit GeomTrianglesAdjacency(UsageHint usage_hint);
|
||||
GeomTrianglesAdjacency(const GeomTrianglesAdjacency ©);
|
||||
virtual ~GeomTrianglesAdjacency();
|
||||
ALLOC_DELETED_CHAIN(GeomTrianglesAdjacency);
|
||||
|
||||
public:
|
||||
virtual PT(GeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
virtual int get_geom_rendering() const;
|
||||
|
||||
virtual int get_num_vertices_per_primitive() const;
|
||||
|
||||
public:
|
||||
virtual bool draw(GraphicsStateGuardianBase *gsg,
|
||||
const GeomPrimitivePipelineReader *reader,
|
||||
bool force) const;
|
||||
|
||||
protected:
|
||||
virtual CPT(GeomPrimitive) doubleside_impl() const;
|
||||
virtual CPT(GeomPrimitive) reverse_impl() const;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
GeomPrimitive::init_type();
|
||||
register_type(_type_handle, "GeomTrianglesAdjacency",
|
||||
GeomPrimitive::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class Geom;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "geomTristripsAdjacency.h"
|
||||
|
||||
TypeHandle GeomTristrips::_type_handle;
|
||||
|
||||
|
|
@ -80,6 +81,143 @@ get_geom_rendering() const {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds adjacency information to this primitive. May return null if this type
|
||||
* of geometry does not support adjacency information.
|
||||
*/
|
||||
CPT(GeomPrimitive) GeomTristrips::
|
||||
make_adjacency() const {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(GeomTristripsAdjacency) adj = new GeomTristripsAdjacency(get_usage_hint());
|
||||
CPTA_int ends = get_ends();
|
||||
|
||||
GeomPrimitivePipelineReader from(this, current_thread);
|
||||
int num_vertices = from.get_num_vertices();
|
||||
const int num_unused = 2;
|
||||
|
||||
// First, build a map of each triangle's halfedges to its opposing vertices.
|
||||
map<pair<int, int>, int> edge_map;
|
||||
|
||||
int vi = -num_unused;
|
||||
int li = 0;
|
||||
while (li < (int)ends.size()) {
|
||||
// Skip unused vertices between tristrips.
|
||||
vi += num_unused;
|
||||
int end = ends[li];
|
||||
nassertr(vi + 2 <= end, nullptr);
|
||||
|
||||
int v0 = from.get_vertex(vi++);
|
||||
int v1 = from.get_vertex(vi++);
|
||||
int v2 = from.get_vertex(vi);
|
||||
edge_map[make_pair(v0, v1)] = v2;
|
||||
|
||||
while (true) {
|
||||
v2 = from.get_vertex(vi++);
|
||||
edge_map[make_pair(v2, v0)] = v1;
|
||||
|
||||
if (vi >= end) {
|
||||
// Edge at the end of the strip
|
||||
edge_map[make_pair(v1, v2)] = v0;
|
||||
break;
|
||||
}
|
||||
|
||||
v0 = v1;
|
||||
v1 = v2;
|
||||
v2 = from.get_vertex(vi++);
|
||||
edge_map[make_pair(v0, v2)] = v1;
|
||||
|
||||
if (vi >= end) {
|
||||
// Edge at the end of the strip
|
||||
edge_map[make_pair(v2, v1)] = v0;
|
||||
break;
|
||||
}
|
||||
|
||||
v0 = v1;
|
||||
v1 = v2;
|
||||
}
|
||||
++li;
|
||||
}
|
||||
nassertr(vi == num_vertices, nullptr);
|
||||
|
||||
// Now build up the new vertex data. For each edge, we insert the
|
||||
// appropriate connecting vertex.
|
||||
vi = -num_unused;
|
||||
li = 0;
|
||||
while (li < (int)ends.size()) {
|
||||
// Skip unused vertices between tristrips.
|
||||
vi += num_unused;
|
||||
int end = ends[li];
|
||||
nassertr(vi + 2 <= end, nullptr);
|
||||
|
||||
int v0 = from.get_vertex(vi++);
|
||||
int v1 = from.get_vertex(vi++);
|
||||
int v2;
|
||||
adj->add_vertex(v0);
|
||||
|
||||
// Get the third vertex of the triangle adjoining this edge.
|
||||
auto it = edge_map.find(make_pair(v1, v0));
|
||||
if (it != edge_map.end()) {
|
||||
adj->add_vertex(it->second);
|
||||
} else {
|
||||
// Um, no adjoining triangle? Just repeat the vertex, I guess.
|
||||
adj->add_vertex(v0);
|
||||
}
|
||||
adj->add_vertex(v1);
|
||||
|
||||
while (true) {
|
||||
v2 = from.get_vertex(vi++);
|
||||
it = edge_map.find(make_pair(v0, v2));
|
||||
if (it != edge_map.end()) {
|
||||
adj->add_vertex(it->second);
|
||||
} else {
|
||||
adj->add_vertex(v1);
|
||||
}
|
||||
adj->add_vertex(v2);
|
||||
|
||||
if (vi >= end) {
|
||||
// Edge at the end of the strip
|
||||
it = edge_map.find(make_pair(v2, v1));
|
||||
if (it != edge_map.end()) {
|
||||
adj->add_vertex(it->second);
|
||||
} else {
|
||||
adj->add_vertex(v2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
v0 = v1;
|
||||
v1 = v2;
|
||||
v2 = from.get_vertex(vi++);
|
||||
it = edge_map.find(make_pair(v2, v0));
|
||||
if (it != edge_map.end()) {
|
||||
adj->add_vertex(it->second);
|
||||
} else {
|
||||
adj->add_vertex(v1);
|
||||
}
|
||||
adj->add_vertex(v2);
|
||||
|
||||
if (vi >= end) {
|
||||
// Edge at the end of the strip
|
||||
it = edge_map.find(make_pair(v1, v2));
|
||||
if (it != edge_map.end()) {
|
||||
adj->add_vertex(it->second);
|
||||
} else {
|
||||
adj->add_vertex(v1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
v0 = v1;
|
||||
v1 = v2;
|
||||
}
|
||||
adj->close_primitive();
|
||||
++li;
|
||||
}
|
||||
nassertr(vi == num_vertices, nullptr);
|
||||
|
||||
return adj.p();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum number of vertices that must be added before
|
||||
* close_primitive() may legally be called.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ public:
|
|||
virtual PT(GeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
virtual int get_geom_rendering() const;
|
||||
|
||||
CPT(GeomPrimitive) make_adjacency() const;
|
||||
|
||||
virtual int get_min_num_vertices_per_primitive() const;
|
||||
virtual int get_num_unused_vertices_per_primitive() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file geomTristripsAdjacency.cxx
|
||||
* @author rdb
|
||||
* @date 2018-03-01
|
||||
*/
|
||||
|
||||
#include "geomTristripsAdjacency.h"
|
||||
#include "geomTriangles.h"
|
||||
#include "geomVertexRewriter.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
|
||||
TypeHandle GeomTristripsAdjacency::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomTristripsAdjacency::
|
||||
GeomTristripsAdjacency(GeomTristripsAdjacency::UsageHint usage_hint) :
|
||||
GeomPrimitive(usage_hint)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomTristripsAdjacency::
|
||||
GeomTristripsAdjacency(const GeomTristripsAdjacency ©) :
|
||||
GeomPrimitive(copy)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
GeomTristripsAdjacency::
|
||||
~GeomTristripsAdjacency() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PT(GeomPrimitive) GeomTristripsAdjacency::
|
||||
make_copy() const {
|
||||
return new GeomTristripsAdjacency(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fundamental rendering type of this primitive: whether it is
|
||||
* points, lines, or polygons.
|
||||
*
|
||||
* This is used to set up the appropriate antialiasing settings when
|
||||
* AntialiasAttrib::M_auto is in effect; it also implies the type of primitive
|
||||
* that will be produced when decompose() is called.
|
||||
*/
|
||||
GeomPrimitive::PrimitiveType GeomTristripsAdjacency::
|
||||
get_primitive_type() const {
|
||||
return PT_polygons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of GeomRendering bits that represent the rendering
|
||||
* properties required to properly render this primitive.
|
||||
*/
|
||||
int GeomTristripsAdjacency::
|
||||
get_geom_rendering() const {
|
||||
if (is_indexed()) {
|
||||
if (get_num_primitives() > 1) {
|
||||
return GR_triangle_strip | GR_indexed_other | GR_strip_cut_index | GR_adjacency;
|
||||
} else {
|
||||
return GR_triangle_strip | GR_indexed_other | GR_adjacency;
|
||||
}
|
||||
} else {
|
||||
return GR_triangle_strip | GR_adjacency;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum number of vertices that must be added before
|
||||
* close_primitive() may legally be called.
|
||||
*/
|
||||
int GeomTristripsAdjacency::
|
||||
get_min_num_vertices_per_primitive() const {
|
||||
return 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of vertices that are added between primitives that
|
||||
* aren't, strictly speaking, part of the primitives themselves. This is
|
||||
* used, for instance, to define degenerate triangles to connect otherwise
|
||||
* disconnected triangle strips.
|
||||
*/
|
||||
int GeomTristripsAdjacency::
|
||||
get_num_unused_vertices_per_primitive() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the appropriate method on the GSG to draw the primitive.
|
||||
*/
|
||||
bool GeomTristripsAdjacency::
|
||||
draw(GraphicsStateGuardianBase *gsg, const GeomPrimitivePipelineReader *reader,
|
||||
bool force) const {
|
||||
return gsg->draw_tristrips_adj(reader, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be redefined to return true in any primitive that implements
|
||||
* append_unused_vertices().
|
||||
*/
|
||||
bool GeomTristripsAdjacency::
|
||||
requires_unused_vertices() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new primitive is begun (other than the first primitive), this
|
||||
* should add some degenerate vertices between primitives, if the primitive
|
||||
* type requires that. The second parameter is the first vertex that begins
|
||||
* the new primitive.
|
||||
*/
|
||||
void GeomTristripsAdjacency::
|
||||
append_unused_vertices(GeomVertexArrayData *vertices, int vertex) {
|
||||
GeomVertexWriter to(vertices, 0);
|
||||
to.set_row_unsafe(vertices->get_num_rows());
|
||||
to.add_data1i(get_strip_cut_index());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the BamReader how to create objects of type Geom.
|
||||
*/
|
||||
void GeomTristripsAdjacency::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by the BamReader's factory when a new object of
|
||||
* type Geom is encountered in the Bam file. It should create the Geom and
|
||||
* extract its information from the file.
|
||||
*/
|
||||
TypedWritable *GeomTristripsAdjacency::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
GeomTristripsAdjacency *object = new GeomTristripsAdjacency(UH_unspecified);
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
object->fillin(scan, manager);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file geomTristripsAdjacency.h
|
||||
* @author rdb
|
||||
* @date 2018-03-01
|
||||
*/
|
||||
|
||||
#ifndef GEOMTRISTRIPSADJACENCY_H
|
||||
#define GEOMTRISTRIPSADJACENCY_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "geomPrimitive.h"
|
||||
|
||||
/**
|
||||
* Defines a series of triangle strips.
|
||||
*/
|
||||
class EXPCL_PANDA_GOBJ GeomTristripsAdjacency : public GeomPrimitive {
|
||||
PUBLISHED:
|
||||
explicit GeomTristripsAdjacency(UsageHint usage_hint);
|
||||
GeomTristripsAdjacency(const GeomTristripsAdjacency ©);
|
||||
virtual ~GeomTristripsAdjacency();
|
||||
ALLOC_DELETED_CHAIN(GeomTristripsAdjacency);
|
||||
|
||||
public:
|
||||
virtual PT(GeomPrimitive) make_copy() const;
|
||||
virtual PrimitiveType get_primitive_type() const;
|
||||
virtual int get_geom_rendering() const;
|
||||
virtual int get_min_num_vertices_per_primitive() const;
|
||||
virtual int get_num_unused_vertices_per_primitive() const;
|
||||
|
||||
public:
|
||||
virtual bool draw(GraphicsStateGuardianBase *gsg,
|
||||
const GeomPrimitivePipelineReader *reader,
|
||||
bool force) const;
|
||||
|
||||
protected:
|
||||
virtual bool requires_unused_vertices() const;
|
||||
virtual void append_unused_vertices(GeomVertexArrayData *vertices,
|
||||
int vertex);
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
GeomPrimitive::init_type();
|
||||
register_type(_type_handle, "GeomTristripsAdjacency",
|
||||
GeomPrimitive::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class Geom;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -10,14 +10,18 @@
|
|||
#include "geomContext.cxx"
|
||||
#include "geomEnums.cxx"
|
||||
#include "geomLines.cxx"
|
||||
#include "geomLinesAdjacency.cxx"
|
||||
#include "geomLinestrips.cxx"
|
||||
#include "geomLinestripsAdjacency.cxx"
|
||||
#include "geomMunger.cxx"
|
||||
#include "geomPatches.cxx"
|
||||
#include "geomPoints.cxx"
|
||||
#include "geomPrimitive.cxx"
|
||||
#include "geomTriangles.cxx"
|
||||
#include "geomTrianglesAdjacency.cxx"
|
||||
#include "geomTrifans.cxx"
|
||||
#include "geomTristrips.cxx"
|
||||
#include "geomTristripsAdjacency.cxx"
|
||||
#include "geomVertexAnimationSpec.cxx"
|
||||
#include "geomVertexArrayData.cxx"
|
||||
#include "geomVertexArrayFormat.cxx"
|
||||
|
|
|
|||
|
|
@ -201,11 +201,15 @@ public:
|
|||
const GeomVertexDataPipelineReader *data_reader,
|
||||
bool force)=0;
|
||||
virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_triangles_adj(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_tristrips_adj(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_patches(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_lines(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_lines_adj(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_linestrips_adj(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual bool draw_points(const GeomPrimitivePipelineReader *reader, bool force)=0;
|
||||
virtual void end_draw_primitives()=0;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
from panda3d import core
|
||||
|
||||
|
||||
def test_geom_triangles_adjacency():
|
||||
prim = core.GeomTriangles(core.GeomEnums.UH_static)
|
||||
prim.add_vertex(0)
|
||||
prim.add_vertex(1)
|
||||
prim.add_vertex(2)
|
||||
prim.close_primitive()
|
||||
prim.add_vertex(2)
|
||||
prim.add_vertex(1)
|
||||
prim.add_vertex(3)
|
||||
prim.close_primitive()
|
||||
|
||||
adj = prim.make_adjacency()
|
||||
verts = adj.get_vertex_list()
|
||||
assert tuple(verts) == (
|
||||
0, 0, 1, 3, 2, 2,
|
||||
2, 0, 1, 1, 3, 3,
|
||||
)
|
||||
|
||||
|
||||
def test_geom_lines_adjacency():
|
||||
prim = core.GeomLines(core.GeomEnums.UH_static)
|
||||
prim.add_vertex(0)
|
||||
prim.add_vertex(1)
|
||||
prim.close_primitive()
|
||||
prim.add_vertex(1)
|
||||
prim.add_vertex(2)
|
||||
prim.close_primitive()
|
||||
prim.add_vertex(2)
|
||||
prim.add_vertex(3)
|
||||
prim.close_primitive()
|
||||
|
||||
adj = prim.make_adjacency()
|
||||
verts = adj.get_vertex_list()
|
||||
assert tuple(verts) == (
|
||||
0, 0, 1, 2,
|
||||
0, 1, 2, 3,
|
||||
1, 2, 3, 3,
|
||||
)
|
||||
|
||||
|
||||
def test_geom_linestrips_adjacency():
|
||||
prim = core.GeomLinestrips(core.GeomEnums.UH_static)
|
||||
prim.add_vertex(0)
|
||||
prim.add_vertex(1)
|
||||
prim.close_primitive()
|
||||
prim.add_vertex(1)
|
||||
prim.add_vertex(2)
|
||||
prim.add_vertex(3)
|
||||
prim.close_primitive()
|
||||
prim.add_vertex(3)
|
||||
prim.add_vertex(4)
|
||||
prim.add_vertex(5)
|
||||
prim.add_vertex(6)
|
||||
prim.close_primitive()
|
||||
|
||||
adj = prim.make_adjacency()
|
||||
verts = adj.get_vertex_list()
|
||||
cut = adj.get_strip_cut_index()
|
||||
assert tuple(verts) == (
|
||||
0, 0, 1, 2,
|
||||
cut,
|
||||
0, 1, 2, 3, 4,
|
||||
cut,
|
||||
2, 3, 4, 5, 6, 6,
|
||||
)
|
||||
|
||||
# Check that it decomposes properly to a lines-adjacency primitive
|
||||
prim = adj.decompose()
|
||||
assert isinstance(prim, core.GeomLinesAdjacency)
|
||||
verts = prim.get_vertex_list()
|
||||
assert tuple(verts) == (
|
||||
0, 0, 1, 2,
|
||||
|
||||
0, 1, 2, 3,
|
||||
1, 2, 3, 4,
|
||||
|
||||
2, 3, 4, 5,
|
||||
3, 4, 5, 6,
|
||||
4, 5, 6, 6,
|
||||
)
|
||||
Loading…
Reference in New Issue