initial checkin of experimental Geom rewrite--preliminary

This commit is contained in:
David Rose 2005-03-11 02:28:51 +00:00
parent 8303d57800
commit c975b7cd49
89 changed files with 8036 additions and 536 deletions

View File

@ -73,7 +73,7 @@ get_normals() const {
// associated with this bucket.
////////////////////////////////////////////////////////////////////
INLINE void BuilderBucket::
set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords) {
set_texcoords(const InternalName *name, const PTA_TexCoordf &texcoords) {
_texcoords[name] = texcoords;
}
@ -84,7 +84,7 @@ set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords) {
// Description:
////////////////////////////////////////////////////////////////////
INLINE PTA_TexCoordf BuilderBucket::
get_texcoords(const TexCoordName *name) const {
get_texcoords(const InternalName *name) const {
TexCoords::const_iterator ti = _texcoords.find(name);
if (ti != _texcoords.end()) {
return (*ti).second;

View File

@ -30,7 +30,7 @@
#include "pta_Normalf.h"
#include "pta_Colorf.h"
#include "pta_TexCoordf.h"
#include "texCoordName.h"
#include "internalName.h"
#include "renderState.h"
#include "stdlib.h"
@ -77,8 +77,8 @@ public:
INLINE void set_normals(const PTA_Normalf &normals);
INLINE PTA_Normalf get_normals() const;
INLINE void set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords);
INLINE PTA_TexCoordf get_texcoords(const TexCoordName *name) const;
INLINE void set_texcoords(const InternalName *name, const PTA_TexCoordf &texcoords);
INLINE PTA_TexCoordf get_texcoords(const InternalName *name) const;
INLINE void set_colors(const PTA_Colorf &colors);
INLINE PTA_Colorf get_colors() const;
@ -96,7 +96,7 @@ protected:
PTA_Normalf _normals;
PTA_Colorf _colors;
typedef pmap<CPT(TexCoordName), PTA_TexCoordf> TexCoords;
typedef pmap<CPT(InternalName), PTA_TexCoordf> TexCoords;
TexCoords _texcoords;
static BuilderBucket *_default_bucket;

View File

@ -555,13 +555,13 @@ build_geoms(InputIterator first, InputIterator last,
//
// Texcoords are an exception to the above, since they are either
// per vertex or not at all, and since there may be a different set
// of texcoords for each of a number of TexCoordName objects.
// of texcoords for each of a number of InternalName objects.
GeomBindType bind_normals = G_OVERALL;
GeomBindType bind_colors = G_OVERALL;
typedef pset<const TexCoordName *> TexCoordNames;
TexCoordNames texcoord_names;
typedef pset<const InternalName *> InternalNames;
InternalNames texcoord_names;
NType overall_normal(0);
CType overall_color(0);
@ -623,11 +623,11 @@ build_geoms(InputIterator first, InputIterator last,
}
}
// Texcoords. Get the union of all TexCoordNames defined on the
// Texcoords. Get the union of all InternalNames defined on the
// prims.
TYPENAME PrimType::tcn_const_iterator tni;
for (tni = (*i).tcn_begin(); tni != (*i).tcn_end(); ++tni) {
const TexCoordName *name = (*tni);
const InternalName *name = (*tni);
texcoord_names.insert(name);
}
}
@ -719,7 +719,7 @@ build_geoms(InputIterator first, InputIterator last,
typedef TYPENAME PrimType::TexCoordFill TexCoordFill;
TexCoordFill texcoords;
TexCoordNames::const_iterator tni;
InternalNames::const_iterator tni;
for (tni = texcoord_names.begin(); tni != texcoord_names.end(); ++tni) {
texcoords[*tni] = PTA(TType)::empty_array(0);
}
@ -744,7 +744,7 @@ build_geoms(InputIterator first, InputIterator last,
}
TYPENAME TexCoordFill::iterator tci;
for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) {
const TexCoordName *name = (*tci).first;
const InternalName *name = (*tci).first;
if ((*i).get_vertex(v).has_texcoord(name)) {
(*tci).second.push_back((*i).get_vertex(v).get_texcoord(name));
} else {

View File

@ -68,7 +68,7 @@ nonindexed_copy(const BuilderPrimTempl<BuilderVertexI> &copy,
BuilderVertexI::tc_const_iterator tci;
for (tci = cv.tc_begin(); tci != cv.tc_end(); ++tci) {
const TexCoordName *name = (*tci).first;
const InternalName *name = (*tci).first;
v.set_texcoord(name, cv.get_texcoord_value(name, bucket));
}
@ -153,7 +153,7 @@ fill_geom(Geom *geom, const PTA_BuilderV &v_array,
TexCoordFill::const_iterator tci;
for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) {
const TexCoordName *name = (*tci).first;
const InternalName *name = (*tci).first;
geom->set_texcoords(name, (*tci).second);
}
}
@ -238,7 +238,7 @@ fill_geom(Geom *geom, const PTA_ushort &v_array,
TexCoordFill::const_iterator tci;
for (tci = texcoords.begin(); tci != texcoords.end(); ++tci) {
const TexCoordName *name = (*tci).first;
const InternalName *name = (*tci).first;
PTA_ushort t_array = (*tci).second;
PTA_TexCoordf t_data = bucket.get_texcoords(name);

View File

@ -328,7 +328,7 @@ has_any_pixel_size() const {
// Function: BuilderPrimTempl::tcn_begin
// Access: Public
// Description: Returns an iterator that can be used to walk through
// the list of TexCoordNames that are common to all
// the list of InternalNames that are common to all
// vertices on this primitive.
////////////////////////////////////////////////////////////////////
template <class VTX>
@ -341,7 +341,7 @@ tcn_begin() const {
// Function: BuilderPrimTempl::tcn_end
// Access: Public
// Description: Returns an iterator that can be used to walk through
// the list of TexCoordNames that are common to all
// the list of InternalNames that are common to all
// vertices on this primitive.
////////////////////////////////////////////////////////////////////
template <class VTX>
@ -353,7 +353,7 @@ tcn_end() const {
////////////////////////////////////////////////////////////////////
// Function: BuilderPrimTempl::tcn_size
// Access: Public
// Description: Returns the number of TexCoordNames that are common
// Description: Returns the number of InternalNames that are common
// to all vertices on this primitive.
////////////////////////////////////////////////////////////////////
template <class VTX>
@ -885,12 +885,12 @@ update_overall_attrib() {
int i;
if (num_verts > 0) {
// Get the intersection of TexCoordNames that are defined on all
// Get the intersection of InternalNames that are defined on all
// vertices.
const Vertex &vtx = get_vertex(0);
TYPENAME Vertex::tc_const_iterator tci;
for (tci = vtx.tc_begin(); tci != vtx.tc_end(); ++tci) {
const TexCoordName *name = (*tci).first;
const InternalName *name = (*tci).first;
bool has_texcoord = true;
for (i = 1; i < num_verts && has_texcoord; i++) {
has_texcoord = get_vertex(i).has_texcoord(name);

View File

@ -45,12 +45,12 @@ public:
typedef TYPENAME VTX::TType TType;
typedef TYPENAME VTX::CType CType;
typedef TYPENAME VTX::Attrib DAttrib;
typedef pset<const TexCoordName *> TexCoordNames;
typedef TexCoordNames::const_iterator tcn_const_iterator;
typedef TexCoordNames::size_type tcn_size_type;
typedef pset<const InternalName *> InternalNames;
typedef InternalNames::const_iterator tcn_const_iterator;
typedef InternalNames::size_type tcn_size_type;
// This type is passed to fill_geom() for the texcoords.
typedef pmap<const TexCoordName *, PTA(TType) > TexCoordFill;
typedef pmap<const InternalName *, PTA(TType) > TexCoordFill;
INLINE BuilderPrimTempl();
INLINE BuilderPrimTempl(const BuilderPrimTempl &copy);
@ -151,7 +151,7 @@ protected:
Verts _verts;
Components _components;
TexCoordNames _texcoord_names;
InternalNames _texcoord_names;
BuilderPrimType _type;
int _overall;
};

View File

@ -60,7 +60,7 @@ set_normal_value(const BuilderN *array, ushort index) {
// assumes the array is the same one it's indexing on).
////////////////////////////////////////////////////////////////////
INLINE void BuilderVertex::
set_texcoord_value(const TexCoordName *name, const BuilderTC *array, ushort index) {
set_texcoord_value(const InternalName *name, const BuilderTC *array, ushort index) {
set_texcoord(name, array[index]);
}
@ -130,7 +130,7 @@ get_normal_value(const BuilderBucket &) const {
// get_coord_value().
////////////////////////////////////////////////////////////////////
INLINE BuilderTC BuilderVertex::
get_texcoord_value(const TexCoordName *name, const BuilderBucket &) const {
get_texcoord_value(const InternalName *name, const BuilderBucket &) const {
return get_texcoord(name);
}
@ -191,7 +191,7 @@ set_normal_value(const BuilderN *, ushort index) {
// assumes the array is the same one it's indexing on).
////////////////////////////////////////////////////////////////////
INLINE void BuilderVertexI::
set_texcoord_value(const TexCoordName *name,const BuilderTC *, ushort index) {
set_texcoord_value(const InternalName *name,const BuilderTC *, ushort index) {
set_texcoord(name, index);
}
@ -259,7 +259,7 @@ get_normal_value(const BuilderBucket &bucket) const {
// get_coord_value().
////////////////////////////////////////////////////////////////////
INLINE BuilderTC BuilderVertexI::
get_texcoord_value(const TexCoordName *name, const BuilderBucket &bucket) const {
get_texcoord_value(const InternalName *name, const BuilderBucket &bucket) const {
nassertr(bucket.get_texcoords(name) != (TexCoordf *)NULL, BuilderTC());
return bucket.get_texcoords(name)[get_texcoord(name)];
}

View File

@ -80,12 +80,12 @@ public:
INLINE void set_coord_value(const BuilderV *array, ushort index);
INLINE void set_normal_value(const BuilderN *array, ushort index);
INLINE void set_texcoord_value(const TexCoordName *name, const BuilderTC *array, ushort index);
INLINE void set_texcoord_value(const InternalName *name, const BuilderTC *array, ushort index);
INLINE void set_color_value(const BuilderC *array, ushort index);
INLINE BuilderV get_coord_value(const BuilderBucket &bucket) const;
INLINE BuilderN get_normal_value(const BuilderBucket &bucket) const;
INLINE BuilderTC get_texcoord_value(const TexCoordName *name, const BuilderBucket &bucket) const;
INLINE BuilderTC get_texcoord_value(const InternalName *name, const BuilderBucket &bucket) const;
INLINE BuilderC get_color_value(const BuilderBucket &bucket) const;
};
@ -111,12 +111,12 @@ public:
INLINE void set_coord_value(const BuilderV *array, ushort index);
INLINE void set_normal_value(const BuilderN *array, ushort index);
INLINE void set_texcoord_value(const TexCoordName *name, const BuilderTC *array, ushort index);
INLINE void set_texcoord_value(const InternalName *name, const BuilderTC *array, ushort index);
INLINE void set_color_value(const BuilderC *array, ushort index);
INLINE BuilderV get_coord_value(const BuilderBucket &bucket) const;
INLINE BuilderN get_normal_value(const BuilderBucket &bucket) const;
INLINE BuilderTC get_texcoord_value(const TexCoordName *name, const BuilderBucket &bucket) const;
INLINE BuilderTC get_texcoord_value(const InternalName *name, const BuilderBucket &bucket) const;
INLINE BuilderC get_color_value(const BuilderBucket &bucket) const;
};

View File

@ -170,7 +170,7 @@ clear_normal() {
////////////////////////////////////////////////////////////////////
template <class VT, class NT, class TT, class CT>
INLINE bool BuilderVertexTempl<VT, NT, TT, CT>::
has_texcoord(const TexCoordName *name) const {
has_texcoord(const InternalName *name) const {
TYPENAME TexCoords::const_iterator ti = _texcoords.find(name);
return (ti != _texcoords.end());
}
@ -185,7 +185,7 @@ has_texcoord(const TexCoordName *name) const {
////////////////////////////////////////////////////////////////////
template <class VT, class NT, class TT, class CT>
INLINE TYPENAME BuilderVertexTempl<VT, NT, TT, CT>::TType BuilderVertexTempl<VT, NT, TT, CT>::
get_texcoord(const TexCoordName *name) const {
get_texcoord(const InternalName *name) const {
TYPENAME TexCoords::const_iterator ti = _texcoords.find(name);
nassertr(ti != _texcoords.end(), (*ti).second);
return (*ti).second;
@ -199,7 +199,7 @@ get_texcoord(const TexCoordName *name) const {
////////////////////////////////////////////////////////////////////
template <class VT, class NT, class TT, class CT>
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
set_texcoord(const TexCoordName *name, const TType &t) {
set_texcoord(const InternalName *name, const TType &t) {
_texcoords[name] = t;
return *this;
}
@ -211,7 +211,7 @@ set_texcoord(const TexCoordName *name, const TType &t) {
////////////////////////////////////////////////////////////////////
template <class VT, class NT, class TT, class CT>
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
clear_texcoord(const TexCoordName *name) {
clear_texcoord(const InternalName *name) {
_texcoords.erase(name);
return *this;
}
@ -422,7 +422,7 @@ output(ostream &out) const {
TYPENAME TexCoords::const_iterator ti;
for (ti = _texcoords.begin(); ti != _texcoords.end(); ++ti) {
const TexCoordName *name = (*ti).first;
const InternalName *name = (*ti).first;
out << " texcoord \"" << name->get_name() << "\" " << (*ti).second;
}

View File

@ -24,7 +24,7 @@
#include "builderTypes.h"
#include "builderAttribTempl.h"
#include "builder_compare.h"
#include "texCoordName.h"
#include "internalName.h"
#include "pointerTo.h"
#include "notify.h"
@ -45,7 +45,7 @@ public:
typedef NT NType;
typedef TT TType;
typedef CT CType;
typedef pmap<CPT(TexCoordName), TType> TexCoords;
typedef pmap<CPT(InternalName), TType> TexCoords;
typedef TYPENAME TexCoords::const_iterator tc_const_iterator;
typedef TYPENAME TexCoords::size_type tc_size_type;
@ -64,10 +64,10 @@ public:
INLINE BuilderVertexTempl &set_normal(const NType &c);
INLINE BuilderVertexTempl &clear_normal();
INLINE bool has_texcoord(const TexCoordName *name) const;
INLINE TType get_texcoord(const TexCoordName *name) const;
INLINE BuilderVertexTempl &set_texcoord(const TexCoordName *name, const TType &t);
INLINE BuilderVertexTempl &clear_texcoord(const TexCoordName *name);
INLINE bool has_texcoord(const InternalName *name) const;
INLINE TType get_texcoord(const InternalName *name) const;
INLINE BuilderVertexTempl &set_texcoord(const InternalName *name, const TType &t);
INLINE BuilderVertexTempl &clear_texcoord(const InternalName *name);
INLINE tc_const_iterator tc_begin() const;
INLINE tc_const_iterator tc_end() const;
INLINE tc_size_type tc_size() const;

View File

@ -285,6 +285,16 @@ get_scene() const {
return _scene_setup;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_geom_munger
// Access: Public
// Description: Returns the current GeomMunger object.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomMunger *GraphicsStateGuardian::
get_geom_munger() const {
return _geom_munger;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::clear
// Access: Public
@ -373,6 +383,7 @@ modify_state(const RenderState *state) {
_state_pcollector.add_level(1);
_state = _state->issue_delta_modify(state, this);
finish_modify_state();
setup_geom_munger(NULL);
}
}
@ -400,6 +411,7 @@ set_state(const RenderState *state) {
_state_pcollector.add_level(1);
_state = _state->issue_delta_set(state, this);
finish_modify_state();
setup_geom_munger(NULL);
}
}

View File

@ -37,6 +37,8 @@
#include "throw_event.h"
#include "clockObject.h"
#include "pStatTimer.h"
#include "qpgeomTristrips.h"
#include "qpgeomTrifans.h"
#include <algorithm>
@ -592,6 +594,58 @@ finish_decal() {
// No need to do anything special here.
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::begin_draw_primitives()
// Access: Public, Virtual
// Description: Called before a sequence of draw_primitive()
// functions are called, this should prepare the vertex
// data for rendering.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
begin_draw_primitives(const qpGeomVertexData *data) {
_vertex_data = get_geom_munger()->munge_data(data);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::draw_triangles
// Access: Public, Virtual
// Description: Draws a series of disconnected triangles.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
draw_triangles(qpGeomTriangles *) {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::draw_tristrips
// Access: Public, Virtual
// Description: Draws a series of triangle strips.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
draw_tristrips(qpGeomTristrips *primitive) {
primitive->decompose(_vertex_data)->draw(this);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::draw_trifans
// Access: Public, Virtual
// Description: Draws a series of triangle fans.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
draw_trifans(qpGeomTrifans *primitive) {
primitive->decompose(_vertex_data)->draw(this);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::end_draw_primitives()
// Access: Public, Virtual
// Description: Called after a sequence of draw_primitive()
// functions are called, this should do whatever cleanup
// is appropriate.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
end_draw_primitives() {
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::framebuffer_bind_to_texture
// Access: Public, Virtual
@ -1270,6 +1324,21 @@ finish_modify_state() {
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::setup_geom_munger
// Access: Protected, Virtual
// Description: Called after finish_modify_state has completed, this
// method sets up the GeomMunger for rendering with the
// current state.
////////////////////////////////////////////////////////////////////
void GraphicsStateGuardian::
setup_geom_munger(PT(qpGeomMunger) munger) {
if (munger == (qpGeomMunger *)NULL) {
munger = new qpGeomMunger;
}
_geom_munger = qpGeomMunger::register_munger(munger);
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::free_pointers
// Access: Protected, Virtual

View File

@ -44,6 +44,8 @@
#include "textureAttrib.h"
#include "transparencyAttrib.h"
#include "config_display.h"
#include "qpgeomMunger.h"
#include "qpgeomVertexData.h"
#include "notify.h"
#include "pvector.h"
@ -95,6 +97,7 @@ PUBLISHED:
public:
INLINE bool set_scene(SceneSetup *scene_setup);
INLINE SceneSetup *get_scene() const;
INLINE const qpGeomMunger *get_geom_munger() const;
virtual PreparedGraphicsObjects *get_prepared_objects();
@ -139,6 +142,12 @@ public:
virtual CPT(RenderState) begin_decal_base_second();
virtual void finish_decal();
virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data);
virtual void draw_triangles(qpGeomTriangles *primitive);
virtual void draw_tristrips(qpGeomTristrips *primitive);
virtual void draw_trifans(qpGeomTrifans *primitive);
virtual void end_draw_primitives();
virtual bool framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex);
virtual void framebuffer_release_texture(GraphicsOutput *win, Texture *tex);
@ -200,6 +209,7 @@ protected:
virtual void set_blend_mode();
virtual void finish_modify_state();
virtual void setup_geom_munger(PT(qpGeomMunger) munger);
virtual void free_pointers();
virtual void close_gsg();
@ -232,6 +242,8 @@ protected:
CPT(RenderState) _state;
CPT(TransformState) _transform;
CPT(qpGeomMunger) _geom_munger;
CPT(qpGeomVertexData) _vertex_data;
int _buffer_mask;
Colorf _color_clear_value;

View File

@ -41,7 +41,7 @@ get_projector() const {
////////////////////////////////////////////////////////////////////
INLINE void ProjectionScreen::
set_texcoord_name(const string &texcoord_name) {
_texcoord_name = TexCoordName::make(texcoord_name);
_texcoord_name = InternalName::get_texcoord_name(texcoord_name);
_stale = true;
}
@ -52,7 +52,7 @@ set_texcoord_name(const string &texcoord_name) {
// will be generated by this particular
// ProjectionScreen, as set by set_texcoord_name().
////////////////////////////////////////////////////////////////////
INLINE const string &ProjectionScreen::
INLINE string ProjectionScreen::
get_texcoord_name() const {
return _texcoord_name->get_name();
}

View File

@ -34,7 +34,7 @@ TypeHandle ProjectionScreen::_type_handle;
ProjectionScreen::
ProjectionScreen(const string &name) : PandaNode(name)
{
_texcoord_name = TexCoordName::get_default();
_texcoord_name = InternalName::get_texcoord();
_invert_uvs = project_invert_uvs;
_vignette_on = false;

View File

@ -25,7 +25,7 @@
#include "lensNode.h"
#include "geomNode.h"
#include "nodePath.h"
#include "texCoordName.h"
#include "internalName.h"
#include "pointerTo.h"
class Geom;
@ -82,7 +82,7 @@ PUBLISHED:
PT(PandaNode) make_flat_mesh(const NodePath &this_np, const NodePath &camera);
INLINE void set_texcoord_name(const string &texcoord_name);
INLINE const string &get_texcoord_name() const;
INLINE string get_texcoord_name() const;
INLINE void set_invert_uvs(bool invert_uvs);
INLINE bool get_invert_uvs() const;
@ -124,7 +124,7 @@ private:
NodePath _projector;
PT(LensNode) _projector_node;
CPT(TexCoordName) _texcoord_name;
CPT(InternalName) _texcoord_name;
bool _invert_uvs;
bool _vignette_on;
Colorf _vignette_color;

View File

@ -48,6 +48,11 @@
#include "depthOffsetAttrib.h"
#include "fog.h"
#include "throw_event.h"
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexData.h"
#include "qpgeomTriangles.h"
#include "qpgeomTristrips.h"
#include "qpgeomTrifans.h"
#ifdef DO_PSTATS
#include "pStatTimer.h"
@ -2575,6 +2580,78 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
_pCurFvfBufPtr = NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::begin_draw_primitives
// Access: Public, Virtual
// Description: Called before a sequence of draw_primitive()
// functions are called, this should prepare the vertex
// buffer if necessary.
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
begin_draw_primitives(const qpGeomVertexData *vertex_data) {
DO_PSTATS_STUFF(_draw_primitive_pcollector.start());
GraphicsStateGuardian::begin_draw_primitives(vertex_data);
const qpGeomVertexFormat *format = _vertex_data->get_format();
if (format == qpGeomVertexFormat::get_v3()) {
set_vertex_format(D3DFVF_XYZ);
} else if (format == qpGeomVertexFormat::get_v3n3()) {
set_vertex_format(D3DFVF_XYZ | D3DFVF_NORMAL);
} else if (format == qpGeomVertexFormat::get_v3t2()) {
set_vertex_format(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0));
} else if (format == qpGeomVertexFormat::get_v3n3t2()) {
set_vertex_format(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0));
} else if (format == qpGeomVertexFormat::get_v3cp() ||
format == qpGeomVertexFormat::get_v3c4()) {
set_vertex_format(D3DFVF_XYZ | D3DFVF_DIFFUSE);
} else if (format == qpGeomVertexFormat::get_v3n3cp() ||
format == qpGeomVertexFormat::get_v3n3c4()) {
set_vertex_format(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL);
} else if (format == qpGeomVertexFormat::get_v3cpt2() ||
format == qpGeomVertexFormat::get_v3c4t2()) {
set_vertex_format(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0));
} else if (format == qpGeomVertexFormat::get_v3n3cpt2() ||
format == qpGeomVertexFormat::get_v3n3c4t2()) {
set_vertex_format(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0));
} else {
nassert_raise("Unexpected vertex format");
}
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::draw_triangles
// Access: Public, Virtual
// Description: Draws a series of disconnected triangles.
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
draw_triangles(qpGeomTriangles *primitive) {
HRESULT hr = _pD3DDevice->DrawIndexedPrimitiveUP
(D3DPT_TRIANGLELIST,
primitive->get_min_vertex(),
primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
primitive->get_num_primitives(),
primitive->get_vertices(),
D3DFMT_INDEX16,
vertex_data->get_array_data(0),
vertex_data->get_format()->get_array_format(0)->get_stride());
TestDrawPrimFailure(DrawPrim,hr,_pD3DDevice,nPrims,0);
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::end_draw_primitives()
// Access: Public, Virtual
// Description: Called after a sequence of draw_primitive()
// functions are called, this should do whatever cleanup
// is appropriate.
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
end_draw_primitives() {
DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
}
////////////////////////////////////////////////////////////////////
// Function: DXGraphicsStateGuardian8::prepare_texture
// Access: Public, Virtual

View File

@ -89,6 +89,10 @@ public:
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc);
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc);
virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data);
virtual void draw_triangles(qpGeomTriangles *primitive);
virtual void end_draw_primitives();
virtual TextureContext *prepare_texture(Texture *tex);
virtual void apply_texture(TextureContext *tc);
virtual void release_texture(TextureContext *tc);

View File

@ -26,7 +26,7 @@
#include "eggNode.h"
#include "eggGroup.h"
#include "eggVertex.h"
#include "texCoordName.h"
#include "internalName.h"
#include <algorithm>
@ -257,7 +257,7 @@ add_normal(const Normald &normal, const EggMorphNormalList &morphs,
// array.
////////////////////////////////////////////////////////////////////
int ComputedVerticesMaker::
add_texcoord(const TexCoordName *name,
add_texcoord(const InternalName *name,
const TexCoordd &texcoord, const EggMorphTexCoordList &morphs,
const LMatrix3d &transform) {
TexCoordDef &def = _tdefmap[name];
@ -389,7 +389,7 @@ make_computed_vertices(Character *character, CharacterMaker &char_maker) {
// Temporary: the ComputedVertices object currently doesn't support
// multitexture.
character->_cv._texcoords = _texcoords[TexCoordName::get_default()];
character->_cv._texcoords = _texcoords[InternalName::get_texcoord()];
// Finally, add in all the morph definitions.
Morphs::const_iterator mi;
@ -446,12 +446,12 @@ make_computed_vertices(Character *character, CharacterMaker &char_maker) {
TexCoordMorphMap::const_iterator mmi;
for (mmi = mlist._tmorphs.begin(); mmi != mlist._tmorphs.end(); ++mmi) {
const TexCoordName *name = (*mmi).first;
const InternalName *name = (*mmi).first;
const TexCoordMorphList &tmorphs = (*mmi).second;
// Temporary check: the ComputedVertices object currently
// doesn't support multitexture.
if (name == TexCoordName::get_default()) {
if (name == InternalName::get_texcoord()) {
comp_verts->_texcoord_morphs.push_back(ComputedVerticesMorphTexCoord());
ComputedVerticesMorphTexCoord &mv = comp_verts->_texcoord_morphs.back();
mv._slider_index = slider_index;

View File

@ -40,7 +40,7 @@ class ComputedVertices;
class CharacterMaker;
class EggNode;
class EggVertex;
class TexCoordName;
class InternalName;
///////////////////////////////////////////////////////////////////
// Class : ComputedVerticesMaker
@ -74,7 +74,7 @@ public:
const LMatrix4d &transform);
int add_normal(const Normald &normal, const EggMorphNormalList &morphs,
const LMatrix4d &transform);
int add_texcoord(const TexCoordName *name,
int add_texcoord(const InternalName *name,
const TexCoordd &texcoord,
const EggMorphTexCoordList &morphs,
const LMatrix3d &transform);
@ -90,7 +90,7 @@ public:
PTA_Normalf _norms;
PTA_Colorf _colors;
typedef pmap<const TexCoordName *, PTA_TexCoordf> TexCoords;
typedef pmap<const InternalName *, PTA_TexCoordf> TexCoords;
TexCoords _texcoords;
protected:
@ -98,7 +98,7 @@ protected:
typedef pmap<int, LVector3f> NormalMorphList;
typedef pmap<int, LVector2f> TexCoordMorphList;
typedef pmap<int, LVector4f> ColorMorphList;
typedef pmap<const TexCoordName *, TexCoordMorphList> TexCoordMorphMap;
typedef pmap<const InternalName *, TexCoordMorphList> TexCoordMorphMap;
class MorphList {
public:
VertexMorphList _vmorphs;
@ -120,7 +120,7 @@ protected:
ComputedVerticesMakerTexCoordMap _tmap;
};
typedef pmap<const TexCoordName *, TexCoordDef> TexCoordDefMap;
typedef pmap<const InternalName *, TexCoordDef> TexCoordDefMap;
TexCoordDefMap _tdefmap;
ComputedVerticesMakerColorMap _cmap;

View File

@ -320,11 +320,11 @@ make_nonindexed_primitive(EggPrimitive *egg_prim, PandaNode *parent,
for (ui = egg_vert->uv_begin(); ui != egg_vert->uv_end(); ++ui) {
EggVertexUV *uv_obj = (*ui);
TexCoordd uv = uv_obj->get_uv();
CPT(TexCoordName) uv_name;
if (uv_obj->has_name()) {
uv_name = TexCoordName::make(uv_obj->get_name());
CPT(InternalName) uv_name;
if (uv_obj->has_name() && uv_obj->get_name() != string("default")) {
uv_name = InternalName::get_texcoord_name(uv_obj->get_name());
} else {
uv_name = TexCoordName::get_default();
uv_name = InternalName::get_texcoord();
}
BakeInUVs::const_iterator buv = bake_in_uvs.find(uv_name);
@ -453,11 +453,11 @@ make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent,
for (ui = egg_vert->uv_begin(); ui != egg_vert->uv_end(); ++ui) {
EggVertexUV *uv_obj = (*ui);
TexCoordd uv = uv_obj->get_uv();
CPT(TexCoordName) uv_name;
if (uv_obj->has_name()) {
uv_name = TexCoordName::make(uv_obj->get_name());
CPT(InternalName) uv_name;
if (uv_obj->has_name() && uv_obj->get_name() != string("default")) {
uv_name = InternalName::get_texcoord_name(uv_obj->get_name());
} else {
uv_name = TexCoordName::get_default();
uv_name = InternalName::get_texcoord();
}
LMatrix3d mat = LMatrix3d::ident_mat();
@ -498,7 +498,7 @@ make_indexed_primitive(EggPrimitive *egg_prim, PandaNode *parent,
for (tci = comp_verts_maker._texcoords.begin();
tci != comp_verts_maker._texcoords.end();
++tci) {
const TexCoordName *name = (*tci).first;
const InternalName *name = (*tci).first;
bucket.set_texcoords(name, (*tci).second);
}
@ -1248,9 +1248,10 @@ make_texture_stage(const EggTexture *egg_tex) {
}
if (egg_tex->has_uv_name() && !egg_tex->get_uv_name().empty()) {
CPT(TexCoordName) name =
TexCoordName::make(egg_tex->get_uv_name());
if (egg_tex->has_uv_name() && !egg_tex->get_uv_name().empty() &&
egg_tex->get_uv_name() != string("default")) {
CPT(InternalName) name =
InternalName::get_texcoord_name(egg_tex->get_uv_name());
stage->set_texcoord_name(name);
}
@ -1461,11 +1462,11 @@ setup_bucket(BuilderBucket &bucket, EggLoader::BakeInUVs &bake_in_uvs,
// if we can safely bake it into the UV's. (We need to get the
// complete list of textures that share this same set of UV's
// per each unique texture matrix. Whew!)
CPT(TexCoordName) uv_name;
if (egg_tex->has_uv_name()) {
uv_name = TexCoordName::make(egg_tex->get_uv_name());
CPT(InternalName) uv_name;
if (egg_tex->has_uv_name() && egg_tex->get_uv_name() != string("default")) {
uv_name = InternalName::get_texcoord_name(egg_tex->get_uv_name());
} else {
uv_name = TexCoordName::get_default();
uv_name = InternalName::get_texcoord();
}
if (has_tex_gen) {
@ -1503,7 +1504,7 @@ setup_bucket(BuilderBucket &bucket, EggLoader::BakeInUVs &bake_in_uvs,
// texture matrix.
TexMats::const_iterator tmi;
for (tmi = tex_mats.begin(); tmi != tex_mats.end(); ++tmi) {
const TexCoordName *uv_name = (*tmi).first;
const InternalName *uv_name = (*tmi).first;
const TexMatTransforms &tmt = (*tmi).second;
if (tmt.size() == 1 && !needs_tex_mat) {

View File

@ -91,10 +91,10 @@ private:
// This structure is used internally in setup_bucket().
typedef pvector<const TextureDef *> TexMatTextures;
typedef pmap<LMatrix3d, TexMatTextures> TexMatTransforms;
typedef pmap<CPT(TexCoordName), TexMatTransforms> TexMats;
typedef pmap<CPT(InternalName), TexMatTransforms> TexMats;
// This structure is returned by setup_bucket().
typedef pmap<CPT(TexCoordName), const EggTexture *> BakeInUVs;
typedef pmap<CPT(InternalName), const EggTexture *> BakeInUVs;
void make_nurbs_curve(EggNurbsCurve *egg_curve, PandaNode *parent,
const LMatrix4d &mat);

View File

@ -44,6 +44,9 @@ typedef PRUint64 PN_uint64;
typedef PRFloat64 PN_float64;
// NSPR doesn't define a float32.
typedef float PN_float32;
#else // HAVE_NSPR
// Without NSPR, and without any other information, we need some
@ -66,6 +69,7 @@ typedef unsigned short PN_uint16;
typedef unsigned long PN_uint32;
typedef double PN_float64;
typedef float PN_float32;
#endif // HAVE_NSPR

View File

@ -228,8 +228,11 @@ back() const {
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE TYPENAME PointerToArray<Element>::iterator PointerToArray<Element>::
insert(iterator position, const Element &x) const {
nassertr((this->_void_ptr) != NULL, position);
insert(iterator position, const Element &x) {
if ((this->_void_ptr) == NULL) {
reassign(new RefCountObj<pvector<Element> >);
position = end();
}
nassertr(position >= ((To *)(this->_void_ptr))->begin() &&
position <= ((To *)(this->_void_ptr))->end(), position);
return ((To *)(this->_void_ptr))->insert(position, x);
@ -242,8 +245,11 @@ insert(iterator position, const Element &x) const {
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void PointerToArray<Element>::
insert(iterator position, size_type n, const Element &x) const {
nassertv((this->_void_ptr) != NULL);
insert(iterator position, size_type n, const Element &x) {
if ((this->_void_ptr) == NULL) {
reassign(new RefCountObj<pvector<Element> >);
position = end();
}
nassertv(position >= ((To *)(this->_void_ptr))->begin() &&
position <= ((To *)(this->_void_ptr))->end());
((To *)(this->_void_ptr))->insert(position, n, x);
@ -256,10 +262,8 @@ insert(iterator position, size_type n, const Element &x) const {
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void PointerToArray<Element>::
erase(iterator position) const {
nassertd((this->_void_ptr) != NULL) {
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
}
erase(iterator position) {
nassertv((this->_void_ptr) != NULL);
nassertv(position >= ((To *)(this->_void_ptr))->begin() &&
position <= ((To *)(this->_void_ptr))->end());
((To *)(this->_void_ptr))->erase(position);
@ -272,10 +276,8 @@ erase(iterator position) const {
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void PointerToArray<Element>::
erase(iterator first, iterator last) const {
nassertd((this->_void_ptr) != NULL) {
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
}
erase(iterator first, iterator last) {
nassertv((this->_void_ptr) != NULL);
nassertv(first >= ((To *)(this->_void_ptr))->begin() && first <= ((To *)(this->_void_ptr))->end());
nassertv(last >= ((To *)(this->_void_ptr))->begin() && last <= ((To *)(this->_void_ptr))->end());
((To *)(this->_void_ptr))->erase(first, last);

View File

@ -135,8 +135,8 @@ public:
INLINE size_type capacity() const;
INLINE reference front() const;
INLINE reference back() const;
INLINE iterator insert(iterator position, const Element &x) const;
INLINE void insert(iterator position, size_type n, const Element &x) const;
INLINE iterator insert(iterator position, const Element &x);
INLINE void insert(iterator position, size_type n, const Element &x);
// We don't define the insert() method that accepts a pair of
// iterators to copy from. That's problematic because of the whole
@ -145,8 +145,8 @@ public:
// be exported from the DLL, you should use
// insert_into_vector(pta.v(), ...).
INLINE void erase(iterator position) const;
INLINE void erase(iterator first, iterator last) const;
INLINE void erase(iterator position);
INLINE void erase(iterator first, iterator last);
PUBLISHED:
#if !defined(WIN32_VC)

View File

@ -26,8 +26,15 @@
#include "loader.h"
#include "keyboardButton.h"
#include "geomTri.h"
#include "qpgeom.h"
#include "qpgeomTriangles.h"
#include "qpgeomTristrips.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexIterator.h"
#include "texturePool.h"
#include "textureAttrib.h"
#include "colorAttrib.h"
#include "perspectiveLens.h"
#include "orthographicLens.h"
#include "auto_bind.h"
@ -603,31 +610,6 @@ load_model(const NodePath &parent, Filename filename) {
////////////////////////////////////////////////////////////////////
NodePath WindowFramework::
load_default_model(const NodePath &parent) {
PTA_Vertexf coords;
PTA_TexCoordf uvs;
PTA_Normalf norms;
PTA_Colorf colors;
PTA_ushort cindex;
coords.push_back(Vertexf::rfu(0.0, 0.0, 0.0));
coords.push_back(Vertexf::rfu(1.0, 0.0, 0.0));
coords.push_back(Vertexf::rfu(0.0, 0.0, 1.0));
uvs.push_back(TexCoordf(0.0, 0.0));
uvs.push_back(TexCoordf(1.0, 0.0));
uvs.push_back(TexCoordf(0.0, 1.0));
norms.push_back(Normalf::back());
colors.push_back(Colorf(0.5, 0.5, 1.0, 1.0));
cindex.push_back(0);
cindex.push_back(0);
cindex.push_back(0);
PT(GeomTri) geom = new GeomTri;
geom->set_num_prims(1);
geom->set_coords(coords);
geom->set_texcoords(uvs, G_PER_VERTEX);
geom->set_normals(norms, G_PER_PRIM);
geom->set_colors(colors, G_PER_VERTEX, cindex);
CPT(RenderState) state = RenderState::make_empty();
// Get the default texture to apply to the triangle; it's compiled
@ -645,7 +627,70 @@ load_default_model(const NodePath &parent) {
}
GeomNode *geomnode = new GeomNode("tri");
geomnode->add_geom(geom, state);
if (use_qpgeom) {
// New, experimental Geom code.
PT(qpGeomVertexData) vdata = new qpGeomVertexData(qpGeomVertexFormat::get_v3n3cpt2());
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
qpGeomVertexIterator normal(vdata, InternalName::get_normal());
qpGeomVertexIterator color(vdata, InternalName::get_color());
qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
vertex.set_data3(Vertexf::rfu(0.0, 0.0, 0.0));
vertex.set_data3(Vertexf::rfu(1.0, 0.0, 0.0));
vertex.set_data3(Vertexf::rfu(0.0, 0.0, 1.0));
normal.set_data3(Normalf::back());
normal.set_data3(Normalf::back());
normal.set_data3(Normalf::back());
color.set_data4(0.5, 0.5, 1.0, 1.0);
color.set_data4(0.5, 0.5, 1.0, 1.0);
color.set_data4(0.5, 0.5, 1.0, 1.0);
texcoord.set_data2(0.0, 0.0);
texcoord.set_data2(1.0, 0.0);
texcoord.set_data2(0.0, 1.0);
PT(qpGeomTriangles) tri = new qpGeomTriangles;
tri->add_consecutive_vertices(0, 3);
tri->close_primitive();
PT(qpGeom) geom = new qpGeom;
geom->set_vertex_data(vdata);
geom->add_primitive(tri);
geomnode->add_geom(geom, state);
} else {
// Original, tried-and-true Geom code.
PTA_Vertexf coords;
PTA_TexCoordf uvs;
PTA_Normalf norms;
PTA_Colorf colors;
PTA_ushort cindex;
coords.push_back(Vertexf::rfu(0.0, 0.0, 0.0));
coords.push_back(Vertexf::rfu(1.0, 0.0, 0.0));
coords.push_back(Vertexf::rfu(0.0, 0.0, 1.0));
uvs.push_back(TexCoordf(0.0, 0.0));
uvs.push_back(TexCoordf(1.0, 0.0));
uvs.push_back(TexCoordf(0.0, 1.0));
norms.push_back(Normalf::back());
colors.push_back(Colorf(0.5, 0.5, 1.0, 1.0));
cindex.push_back(0);
cindex.push_back(0);
cindex.push_back(0);
PT(GeomTri) geom = new GeomTri;
geom->set_num_prims(1);
geom->set_coords(coords);
geom->set_texcoords(uvs, G_PER_VERTEX);
geom->set_normals(norms, G_PER_PRIM);
geom->set_colors(colors, G_PER_VERTEX, cindex);
geomnode->add_geom(geom, state);
}
return parent.attach_new_node(geomnode);
}
@ -995,7 +1040,6 @@ load_image_as_model(const Filename &filename) {
tex->set_magfilter(Texture::FT_linear);
// Ok, now make a polygon to show the texture.
PT(GeomNode) card_geode = new GeomNode("card");
// Choose the dimensions of the polygon appropriately.
float left = -x_size / 2.0;
@ -1003,34 +1047,64 @@ load_image_as_model(const Filename &filename) {
float bottom = -y_size / 2.0;
float top = y_size / 2.0;
GeomTristrip *geoset = new GeomTristrip;
PTA_int lengths=PTA_int::empty_array(0);
lengths.push_back(4);
PTA_Vertexf verts;
verts.push_back(Vertexf::rfu(left, 0.02f, top));
verts.push_back(Vertexf::rfu(left, 0.02f, bottom));
verts.push_back(Vertexf::rfu(right, 0.02f, top));
verts.push_back(Vertexf::rfu(right, 0.02f, bottom));
geoset->set_num_prims(1);
geoset->set_lengths(lengths);
geoset->set_coords(verts);
PTA_TexCoordf uvs;
uvs.push_back(TexCoordf(0.0f, 1.0f));
uvs.push_back(TexCoordf(0.0f, 0.0f));
uvs.push_back(TexCoordf(1.0f, 1.0f));
uvs.push_back(TexCoordf(1.0f, 0.0f));
geoset->set_texcoords(uvs, G_PER_VERTEX);
card_geode->add_geom(geoset);
card_geode->set_attrib(TextureAttrib::make(tex));
PT(GeomNode) card_node = new GeomNode("card");
card_node->set_attrib(ColorAttrib::make_flat(Colorf(1.0f, 1.0f, 1.0f, 1.0f)));
card_node->set_attrib(TextureAttrib::make(tex));
if (has_alpha) {
card_geode->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
card_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
}
return card_geode.p();
if (use_qpgeom) {
PT(qpGeomVertexData) vdata = new qpGeomVertexData(qpGeomVertexFormat::get_v3t2());
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
vertex.set_data3(Vertexf::rfu(left, 0.02f, top));
vertex.set_data3(Vertexf::rfu(left, 0.02f, bottom));
vertex.set_data3(Vertexf::rfu(right, 0.02f, top));
vertex.set_data3(Vertexf::rfu(right, 0.02f, bottom));
texcoord.set_data2(0.0f, 1.0f);
texcoord.set_data2(0.0f, 0.0f);
texcoord.set_data2(1.0f, 1.0f);
texcoord.set_data2(1.0f, 0.0f);
PT(qpGeomTristrips) strip = new qpGeomTristrips;
strip->add_consecutive_vertices(0, 4);
strip->close_primitive();
PT(qpGeom) geom = new qpGeom;
geom->set_vertex_data(vdata);
geom->add_primitive(strip);
card_node->add_geom(geom);
} else {
GeomTristrip *geom = new GeomTristrip;
PTA_int lengths=PTA_int::empty_array(0);
lengths.push_back(4);
PTA_Vertexf verts;
verts.push_back(Vertexf::rfu(left, 0.02f, top));
verts.push_back(Vertexf::rfu(left, 0.02f, bottom));
verts.push_back(Vertexf::rfu(right, 0.02f, top));
verts.push_back(Vertexf::rfu(right, 0.02f, bottom));
geom->set_num_prims(1);
geom->set_lengths(lengths);
geom->set_coords(verts);
PTA_TexCoordf uvs;
uvs.push_back(TexCoordf(0.0f, 1.0f));
uvs.push_back(TexCoordf(0.0f, 0.0f));
uvs.push_back(TexCoordf(1.0f, 1.0f));
uvs.push_back(TexCoordf(1.0f, 0.0f));
geom->set_texcoords(uvs, G_PER_VERTEX);
card_node->add_geom(geom);
}
return card_node.p();
}

View File

@ -22,6 +22,9 @@
glGeomContext_src.cxx \
glGeomContext_src.I \
glGeomContext_src.h \
glGeomMunger_src.cxx \
glGeomMunger_src.I \
glGeomMunger_src.h \
glGraphicsStateGuardian_src.cxx \
glGraphicsStateGuardian_src.I \
glGraphicsStateGuardian_src.h \

View File

@ -0,0 +1,27 @@
// Filename: glGeomMunger_src.I
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CLP(GeomMunger)::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CLP(GeomMunger)::
CLP(GeomMunger)() {
}

View File

@ -0,0 +1,52 @@
// Filename: glGeomMunger_src.cxx
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
TypeHandle CLP(GeomMunger)::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: CLP(GeomMunger)::munge_format_impl
// Access: Protected, Virtual
// Description: Given a source GeomVertexFormat, converts it if
// necessary to the appropriate format for rendering.
////////////////////////////////////////////////////////////////////
CPT(qpGeomVertexFormat) CLP(GeomMunger)::
munge_format_impl(const qpGeomVertexFormat *orig) {
CPT(qpGeomVertexFormat) format = orig;
const qpGeomVertexDataType *color_type =
format->get_data_type(InternalName::get_color());
if (color_type != (qpGeomVertexDataType *)NULL &&
color_type->get_numeric_type() == qpGeomVertexDataType::NT_packed_argb) {
// We need to convert the color format; OpenGL doesn't support the
// byte order of DirectX's packed_argb format.
int color_array = format->get_array_with(InternalName::get_color());
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*format);
PT(qpGeomVertexArrayFormat) new_array_format = new_format->modify_array(color_array);
// Replace the existing color format with the new format.
new_array_format->add_data_type
(InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8,
color_type->get_start());
format = qpGeomVertexFormat::register_format(new_format);
}
return format;
}

View File

@ -0,0 +1,54 @@
// Filename: glGeomMunger_src.h
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "qpgeomMunger.h"
////////////////////////////////////////////////////////////////////
// Class : GLGeomMunger
// Description : This specialization on GeomMunger finesses vertices
// for OpenGL rendering. In particular, it makes sure
// colors aren't stored in DirectX's packed_argb format.
////////////////////////////////////////////////////////////////////
class EXPCL_GL CLP(GeomMunger) : public qpGeomMunger {
public:
INLINE CLP(GeomMunger)();
protected:
virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
qpGeomMunger::init_type();
register_type(_type_handle, CLASSPREFIX_QUOTED "GeomMunger",
qpGeomMunger::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;
};
#include "glGeomMunger_src.I"

View File

@ -21,6 +21,10 @@
#include "renderBuffer.h"
#include "geom.h"
#include "geomIssuer.h"
#include "qpgeomVertexData.h"
#include "qpgeomTriangles.h"
#include "qpgeomTristrips.h"
#include "qpgeomTrifans.h"
#include "graphicsWindow.h"
#include "lens.h"
#include "perspectiveLens.h"
@ -128,6 +132,14 @@ issue_scaled_color_gl(const Geom *geom, Geom::ColorIterator &citerator,
// defined by the GL, just so it will always be safe to call the
// extension functions.
static void APIENTRY
null_glDrawRangeElements(GLenum mode, GLuint start, GLuint end,
GLsizei count, GLenum type, const GLvoid *indices) {
// If we don't support glDrawRangeElements(), just use the original
// glDrawElements() instead.
GLP(DrawElements)(mode, count, type, indices);
}
static void APIENTRY
null_glActiveTexture(GLenum gl_texture_stage) {
// If we don't support multitexture, we'd better not try to request
@ -346,6 +358,27 @@ reset() {
get_extra_extensions();
report_extensions();
if (is_at_least_version(1, 2)) {
_supports_draw_range_elements = true;
_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)
get_extension_func(GLPREFIX_QUOTED, "DrawRangeElements");
} else if (has_extension("EXT_draw_range_elements")) {
_supports_draw_range_elements = true;
_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)
get_extension_func(GLPREFIX_QUOTED, "DrawRangeElementsEXT");
}
if (_supports_draw_range_elements) {
if (_glDrawRangeElements == NULL) {
GLCAT.warning()
<< "glDrawRangeElements advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
_supports_draw_range_elements = false;
}
}
if (!_supports_draw_range_elements) {
_glDrawRangeElements = null_glDrawRangeElements;
}
_supports_3d_texture =
has_extension("GL_EXT_texture3D") || is_at_least_version(1, 2);
@ -1975,6 +2008,128 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::begin_draw_primitives
// Access: Public, Virtual
// Description: Called before a sequence of draw_primitive()
// functions are called, this should prepare the vertex
// buffer if necessary.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
begin_draw_primitives(const qpGeomVertexData *vertex_data) {
DO_PSTATS_STUFF(_draw_primitive_pcollector.start());
GraphicsStateGuardian::begin_draw_primitives(vertex_data);
CPTA_uchar array_data;
int num_components;
qpGeomVertexDataType::NumericType numeric_type;
int start;
int stride;
if (_vertex_data->get_array_info(InternalName::get_vertex(),
array_data, num_components, numeric_type,
start, stride)) {
GLP(VertexPointer)(num_components, get_numeric_type(numeric_type),
stride, array_data + start);
GLP(EnableClientState)(GL_VERTEX_ARRAY);
} else {
GLP(DisableClientState)(GL_VERTEX_ARRAY);
}
bool has_normals = false;
if (wants_normals() &&
_vertex_data->get_array_info(InternalName::get_normal(),
array_data, num_components, numeric_type,
start, stride)) {
GLP(NormalPointer)(get_numeric_type(numeric_type), stride,
array_data + start);
GLP(EnableClientState)(GL_NORMAL_ARRAY);
has_normals = true;
} else {
GLP(DisableClientState)(GL_NORMAL_ARRAY);
}
bool has_colors = false;
if (wants_colors()) {
if (_vertex_data->get_array_info(InternalName::get_color(),
array_data, num_components, numeric_type,
start, stride)) {
if (numeric_type == qpGeomVertexDataType::NT_packed_argb) {
// Temporary hack--this will probably reverse r and b.
GLP(ColorPointer)(4, GL_UNSIGNED_BYTE, stride, array_data + start);
} else {
GLP(ColorPointer)(num_components, get_numeric_type(numeric_type),
stride, array_data + start);
}
GLP(EnableClientState)(GL_COLOR_ARRAY);
has_colors = true;
} else {
// We wanted colors, but the geom didn't have any; just issue
// white.
GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f);
GLP(DisableClientState)(GL_COLOR_ARRAY);
}
} else {
GLP(DisableClientState)(GL_COLOR_ARRAY);
}
if (wants_texcoords() &&
_vertex_data->get_array_info(InternalName::get_texcoord(),
array_data, num_components, numeric_type,
start, stride)) {
GLP(TexCoordPointer)(num_components, get_numeric_type(numeric_type),
stride, array_data + start);
GLP(EnableClientState)(GL_TEXTURE_COORD_ARRAY);
} else {
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
}
// If we have per-vertex colors or normals, we need smooth shading.
// Otherwise we want flat shading for performance reasons.
if (has_colors || has_normals) {
GLP(ShadeModel)(GL_SMOOTH);
} else {
GLP(ShadeModel)(GL_FLAT);
}
issue_scene_graph_color();
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::draw_triangles
// Access: Public, Virtual
// Description: Draws a series of disconnected triangles.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
draw_triangles(qpGeomTriangles *primitive) {
setup_antialias_polygon();
_glDrawRangeElements(GL_TRIANGLES,
primitive->get_min_vertex(),
primitive->get_max_vertex(),
primitive->get_num_vertices(),
GL_UNSIGNED_SHORT, primitive->get_vertices());
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::end_draw_primitives()
// Access: Public, Virtual
// Description: Called after a sequence of draw_primitive()
// functions are called, this should do whatever cleanup
// is appropriate.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
end_draw_primitives() {
GLP(DisableClientState)(GL_VERTEX_ARRAY);
DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::prepare_texture
// Access: Public, Virtual
@ -3762,6 +3917,30 @@ upload_texture_image(CLP(TextureContext) *gtc,
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::get_numeric_type
// Access: Protected, Static
// Description: Maps from the Geom's internal numeric type symbols
// to GL's.
////////////////////////////////////////////////////////////////////
GLenum CLP(GraphicsStateGuardian)::
get_numeric_type(qpGeomVertexDataType::NumericType numeric_type) {
switch (numeric_type) {
case qpGeomVertexDataType::NT_uint8:
return GL_UNSIGNED_BYTE;
case qpGeomVertexDataType::NT_packed_argb:
return GL_UNSIGNED_INT;
case qpGeomVertexDataType::NT_float:
return GL_FLOAT;
}
GLCAT.error()
<< "Invalid NumericType value (" << (int)numeric_type << ")\n";
return GL_UNSIGNED_BYTE;
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::get_texture_target
// Access: Protected
@ -4843,6 +5022,19 @@ finish_modify_state() {
}
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::setup_geom_munger
// Access: Protected, Virtual
// Description: Called after finish_modify_state has completed, this
// method sets up the GeomMunger for rendering with the
// current state.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
setup_geom_munger(PT(qpGeomMunger) munger) {
munger = new CLP(GeomMunger);
GraphicsStateGuardian::setup_geom_munger(munger);
}
////////////////////////////////////////////////////////////////////
// Function: CLP(GraphicsStateGuardian)::free_pointers
// Access: Protected, Virtual

View File

@ -20,6 +20,7 @@
#include "graphicsStateGuardian.h"
#include "geomprimitives.h"
#include "qpgeomVertexDataType.h"
#include "texture.h"
#include "displayRegion.h"
#include "material.h"
@ -48,6 +49,7 @@ class Light;
// system GL version matches or exceeds the GL version in which these
// functions are defined, and the system gl.h sometimes doesn't
// declare these typedefs.
typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
@ -87,6 +89,10 @@ public:
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc);
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc);
virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data);
virtual void draw_triangles(qpGeomTriangles *primitive);
virtual void end_draw_primitives();
INLINE bool draw_display_list(GeomContext *gc);
virtual TextureContext *prepare_texture(Texture *tex);
@ -174,6 +180,7 @@ protected:
virtual void set_blend_mode();
virtual void finish_modify_state();
virtual void setup_geom_munger(PT(qpGeomMunger) munger);
virtual void free_pointers();
@ -212,6 +219,7 @@ protected:
GLint external_format, GLenum component_type,
const unsigned char *image);
static GLenum get_numeric_type(qpGeomVertexDataType::NumericType numeric_type);
GLenum get_texture_target(Texture::TextureType texture_type) const;
GLenum get_texture_wrap_mode(Texture::WrapMode wm);
static GLenum get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps);
@ -296,6 +304,9 @@ protected:
pset<string> _extensions;
public:
bool _supports_draw_range_elements;
PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements;
bool _supports_3d_texture;
PFNGLTEXIMAGE3DPROC _glTexImage3D;
PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D;

View File

@ -24,6 +24,7 @@
#include "glmisc_src.cxx"
#include "glTextureContext_src.cxx"
#include "glGeomContext_src.cxx"
#include "glGeomMunger_src.cxx"
#include "glCgShaderContext_src.cxx"
#include "glGraphicsStateGuardian_src.cxx"

View File

@ -42,6 +42,7 @@
#include "glmisc_src.h"
#include "glTextureContext_src.h"
#include "glGeomContext_src.h"
#include "glGeomMunger_src.h"
#include "glCgShaderContext_src.h"
#include "glGraphicsStateGuardian_src.h"

View File

@ -17,6 +17,18 @@
geomLine.h geomLinestrip.h geomPoint.h geomPolygon.h \
geomQuad.h geomSphere.h geomSprite.I geomSprite.h geomTri.h \
geomTrifan.h geomTristrip.h \
qpgeom.h qpgeom.I \
qpgeomMunger.h qpgeomMunger.I \
qpgeomPrimitive.h qpgeomPrimitive.I \
qpgeomTriangles.h \
qpgeomTristrips.h \
qpgeomTrifans.h \
qpgeomVertexArrayFormat.h qpgeomVertexArrayFormat.I \
qpgeomVertexData.h qpgeomVertexData.I \
qpgeomVertexDataType.h qpgeomVertexDataType.I \
qpgeomVertexFormat.h qpgeomVertexFormat.I \
qpgeomVertexIterator.h qpgeomVertexIterator.I \
internalName.I internalName.h \
material.I material.h materialPool.I materialPool.h \
matrixLens.I matrixLens.h \
orthographicLens.I orthographicLens.h perspectiveLens.I \
@ -27,7 +39,6 @@
texture.I texture.h \
textureContext.I textureContext.h \
texturePool.I texturePool.h \
texCoordName.I texCoordName.h \
textureStage.I textureStage.h
#define INCLUDED_SOURCES \
@ -36,13 +47,26 @@
geomContext.cxx \
geomLine.cxx geomLinestrip.cxx geomPoint.cxx geomPolygon.cxx \
geomQuad.cxx geomSphere.cxx geomSprite.cxx geomTri.cxx \
geomTrifan.cxx geomTristrip.cxx material.cxx \
geomTrifan.cxx geomTristrip.cxx \
qpgeom.cxx \
qpgeomMunger.cxx \
qpgeomPrimitive.cxx \
qpgeomTriangles.cxx \
qpgeomTristrips.cxx \
qpgeomTrifans.cxx \
qpgeomVertexArrayFormat.cxx \
qpgeomVertexData.cxx \
qpgeomVertexDataType.cxx \
qpgeomVertexFormat.cxx \
qpgeomVertexIterator.cxx \
material.cxx \
internalName.cxx \
materialPool.cxx matrixLens.cxx orthographicLens.cxx \
perspectiveLens.cxx \
preparedGraphicsObjects.cxx \
lens.cxx \
savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx \
texCoordName.cxx textureStage.cxx
textureStage.cxx
#define INSTALL_HEADERS \
boundedObject.I boundedObject.h \
@ -52,7 +76,9 @@
geomLine.h \
geomLinestrip.h geomPoint.h geomPolygon.h geomQuad.h geomSphere.h \
geomSprite.I geomSprite.h geomTri.h geomTrifan.h geomTristrip.h \
geomprimitives.h material.I material.h \
geomprimitives.h \
internalName.I internalName.h \
material.I material.h \
materialPool.I materialPool.h matrixLens.I matrixLens.h \
orthographicLens.I orthographicLens.h perspectiveLens.I \
perspectiveLens.h \
@ -62,7 +88,6 @@
texture.I texture.h \
textureContext.I textureContext.h \
texturePool.I texturePool.h \
texCoordName.I texCoordName.h \
textureStage.I textureStage.h
#define IGATESCAN all

View File

@ -22,6 +22,15 @@
#include "drawable.h"
#include "geom.h"
#include "geomprimitives.h"
#include "qpgeom.h"
#include "qpgeomMunger.h"
#include "qpgeomPrimitive.h"
#include "qpgeomTriangles.h"
#include "qpgeomTristrips.h"
#include "qpgeomTrifans.h"
#include "qpgeomVertexArrayFormat.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexFormat.h"
#include "material.h"
#include "orthographicLens.h"
#include "matrixLens.h"
@ -29,7 +38,7 @@
#include "lens.h"
#include "texture.h"
#include "textureStage.h"
#include "texCoordName.h"
#include "internalName.h"
#include "dconfig.h"
#include "string_utils.h"
@ -72,6 +81,12 @@ ConfigVariableBool retained_mode
"GSG. Set it false to use only immediate mode, which sends the "
"vertices to the GSG every frame."));
ConfigVariableBool use_qpgeom
("use-qpgeom", false,
PRC_DESC("A temporary variable while the experimental Geom rewrite is "
"underway. Set this true if you want to use the experimental "
"code. You don't really want to set this true."));
ConfigVariableEnum<BamTextureMode> bam_texture_mode
("bam-texture-mode", BTM_relative,
@ -133,6 +148,15 @@ ConfigureFn(config_gobj) {
GeomTri::init_type();
GeomTrifan::init_type();
GeomTristrip::init_type();
qpGeom::init_type();
qpGeomMunger::init_type();
qpGeomPrimitive::init_type();
qpGeomTriangles::init_type();
qpGeomTristrips::init_type();
qpGeomTrifans::init_type();
qpGeomVertexArrayFormat::init_type();
qpGeomVertexData::init_type();
qpGeomVertexFormat::init_type();
Material::init_type();
OrthographicLens::init_type();
MatrixLens::init_type();
@ -141,7 +165,7 @@ ConfigureFn(config_gobj) {
Texture::init_type();
dDrawable::init_type();
TextureStage::init_type();
TexCoordName::init_type();
InternalName::init_type();
//Registration of writeable object's creation
//functions with BamReader's factory
@ -155,13 +179,20 @@ ConfigureFn(config_gobj) {
GeomTristrip::register_with_read_factory();
GeomTrifan::register_with_read_factory();
GeomSphere::register_with_read_factory();
qpGeom::register_with_read_factory();
qpGeomTriangles::register_with_read_factory();
qpGeomTristrips::register_with_read_factory();
qpGeomTrifans::register_with_read_factory();
qpGeomVertexArrayFormat::register_with_read_factory();
qpGeomVertexData::register_with_read_factory();
qpGeomVertexFormat::register_with_read_factory();
Material::register_with_read_factory();
OrthographicLens::register_with_read_factory();
MatrixLens::register_with_read_factory();
PerspectiveLens::register_with_read_factory();
Texture::register_with_read_factory();
TextureStage::register_with_read_factory();
TexCoordName::register_with_read_factory();
InternalName::register_with_read_factory();
}
ostream &

View File

@ -52,6 +52,8 @@ extern EXPCL_PANDA ConfigVariableBool keep_texture_ram;
extern EXPCL_PANDA ConfigVariableBool keep_geom_ram;
extern EXPCL_PANDA ConfigVariableBool retained_mode;
extern EXPCL_PANDA ConfigVariableBool use_qpgeom;
extern EXPCL_PANDA ConfigVariableEnum<BamTextureMode> bam_texture_mode;
extern EXPCL_PANDA ConfigVariableEnum<AutoTextureScale> textures_power_2;
extern EXPCL_PANDA ConfigVariableEnum<AutoTextureScale> textures_square;

View File

@ -48,7 +48,7 @@ has_any_texcoords() const {
// name, or false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool Geom::
has_texcoords(const TexCoordName *name) const {
has_texcoords(const InternalName *name) const {
TexCoordsByName::const_iterator tci = _texcoords_by_name.find(name);
return (tci != _texcoords_by_name.end());
}
@ -106,11 +106,11 @@ get_colors_array() const {
// returns the default texture coordinates only. In the
// presence of multitexturing, use the version of
// get_texcoords_array() method that takes a
// TexCoordName parameter.
// InternalName parameter.
////////////////////////////////////////////////////////////////////
INLINE PTA_TexCoordf Geom::
get_texcoords_array() const {
return get_texcoords_array(TexCoordName::get_default());
return get_texcoords_array(InternalName::get_texcoord());
}
////////////////////////////////////////////////////////////////////
@ -123,7 +123,7 @@ get_texcoords_array() const {
// texture coordinates with the indicated name.
////////////////////////////////////////////////////////////////////
INLINE PTA_TexCoordf Geom::
get_texcoords_array(const TexCoordName *name) const {
get_texcoords_array(const InternalName *name) const {
TexCoordsByName::const_iterator tci = _texcoords_by_name.find(name);
if (tci != _texcoords_by_name.end()) {
return (*tci).second._texcoords;
@ -174,11 +174,11 @@ get_colors_index() const {
// returns the default texture coordinates only. In the
// presence of multitexturing, use the version of
// get_texcoords_array() method that takes a
// TexCoordName parameter.
// InternalName parameter.
////////////////////////////////////////////////////////////////////
INLINE PTA_ushort Geom::
get_texcoords_index() const {
return get_texcoords_index(TexCoordName::get_default());
return get_texcoords_index(InternalName::get_texcoord());
}
////////////////////////////////////////////////////////////////////
@ -192,7 +192,7 @@ get_texcoords_index() const {
// the geom does not use indexed texcoords.
////////////////////////////////////////////////////////////////////
INLINE PTA_ushort Geom::
get_texcoords_index(const TexCoordName *name) const {
get_texcoords_index(const InternalName *name) const {
TexCoordsByName::const_iterator tci = _texcoords_by_name.find(name);
if (tci != _texcoords_by_name.end()) {
return (*tci).second._tindex;
@ -368,7 +368,7 @@ get_next_normal(NormalIterator &niterator) const {
////////////////////////////////////////////////////////////////////
INLINE Geom::TexCoordIterator Geom::
make_texcoord_iterator() const {
return make_texcoord_iterator(TexCoordName::get_default());
return make_texcoord_iterator(InternalName::get_texcoord());
}
////////////////////////////////////////////////////////////////////
@ -377,7 +377,7 @@ make_texcoord_iterator() const {
// Description:
////////////////////////////////////////////////////////////////////
INLINE Geom::TexCoordIterator Geom::
make_texcoord_iterator(const TexCoordName *texcoord_name) const {
make_texcoord_iterator(const InternalName *texcoord_name) const {
check_config();
TexCoordIterator i;

View File

@ -392,7 +392,7 @@ set_colors(const PTA_Colorf &colors, GeomBindType bind,
// Access: Published
// Description: This single-texturing version of set_texcoords() only
// changes the default texcoords name. Use the version
// of set_texcoords() that takes a TexCoordName
// of set_texcoords() that takes a InternalName
// parameter to set up different texture coordinates for
// different stages of a multitexture pipeline.
////////////////////////////////////////////////////////////////////
@ -402,9 +402,9 @@ set_texcoords(const PTA_TexCoordf &texcoords, GeomBindType bind,
nassertv(bind == G_PER_VERTEX || bind == G_OFF);
if (bind == G_OFF) {
remove_texcoords(TexCoordName::get_default());
remove_texcoords(InternalName::get_texcoord());
} else {
set_texcoords(TexCoordName::get_default(), texcoords, tindex);
set_texcoords(InternalName::get_texcoord(), texcoords, tindex);
}
}
@ -417,9 +417,9 @@ set_texcoords(const PTA_TexCoordf &texcoords, GeomBindType bind,
// remove_texcoords().
////////////////////////////////////////////////////////////////////
void Geom::
set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords,
set_texcoords(const InternalName *name, const PTA_TexCoordf &texcoords,
const PTA_ushort &tindex) {
nassertv(name != (TexCoordName *)NULL);
nassertv(name != (InternalName *)NULL);
#ifndef NDEBUG
// All of the texture coordinates must be either nonindexed, or all
@ -438,7 +438,7 @@ set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords,
def._texcoords = texcoords;
def._tindex = tindex;
if (name == TexCoordName::get_default()) {
if (name == InternalName::get_texcoord()) {
_bind[G_TEXCOORD] = G_PER_VERTEX;
}
@ -454,10 +454,10 @@ set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords,
// set_texcoords().
////////////////////////////////////////////////////////////////////
void Geom::
remove_texcoords(const TexCoordName *name) {
remove_texcoords(const InternalName *name) {
_texcoords_by_name.erase(name);
if (name == TexCoordName::get_default()) {
if (name == InternalName::get_texcoord()) {
_bind[G_TEXCOORD] = G_OFF;
}
@ -529,7 +529,7 @@ void Geom::
get_texcoords(PTA_TexCoordf &texcoords, GeomBindType &bind,
PTA_ushort &tindex) const {
TexCoordsByName::const_iterator tci =
_texcoords_by_name.find(TexCoordName::get_default());
_texcoords_by_name.find(InternalName::get_texcoord());
if (tci != _texcoords_by_name.end()) {
const TexCoordDef &def = (*tci).second;
texcoords = def._texcoords;
@ -573,6 +573,46 @@ prepare(PreparedGraphicsObjects *prepared_objects) {
prepared_objects->enqueue_geom(this);
}
////////////////////////////////////////////////////////////////////
// Function: Geom::get_num_vertices_per_prim
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int Geom::
get_num_vertices_per_prim() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: Geom::get_num_more_vertices_than_components
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int Geom::
get_num_more_vertices_than_components() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: Geom::uses_components
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool Geom::
uses_components() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: Geom::get_length
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int Geom::
get_length(int) const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: Geom::explode
// Access: Published, Virtual
@ -721,7 +761,7 @@ write_verbose(ostream &out, int indent_level) const {
for (tci = _texcoords_by_name.begin();
tci != _texcoords_by_name.end();
++tci) {
const TexCoordName *name = (*tci).first;
const InternalName *name = (*tci).first;
const TexCoordDef &def = (*tci).second;
if (def._tindex != (ushort *)NULL) {
indent(out, indent_level)
@ -762,7 +802,7 @@ setup_multitexcoord_iterator(MultiTexCoordIterator &iterator,
if (no_texcoords.find(stage) == no_texcoords.end()) {
// This stage is not one of the stages that doesn't need
// texcoords issued for it.
const TexCoordName *name = stage->get_texcoord_name();
const InternalName *name = stage->get_texcoord_name();
TexCoordsByName::const_iterator tci = _texcoords_by_name.find(name);
if (tci != _texcoords_by_name.end()) {
// This Geom does have texcoords for this stage.
@ -952,6 +992,24 @@ config() {
}
}
////////////////////////////////////////////////////////////////////
// Function: Geom::draw_immediate
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void Geom::
draw_immediate(GraphicsStateGuardianBase *, GeomContext *) {
}
////////////////////////////////////////////////////////////////////
// Function: Geom::print_draw_immediate
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void Geom::
print_draw_immediate() const {
}
////////////////////////////////////////////////////////////////////
// Function: Geom::calc_tight_bounds
// Access: Public
@ -1118,7 +1176,7 @@ write_datagram(BamWriter *manager, Datagram &me) {
// write the TexCoordsByName pointers if any
TexCoordsByName::const_iterator tci;
for (tci = _texcoords_by_name.begin(); tci != _texcoords_by_name.end(); ++tci) {
CPT(TexCoordName) tc = (*tci).first;
CPT(InternalName) tc = (*tci).first;
manager->write_pointer(me, tc);
WRITE_PTA(manager, me, IPD_TexCoordf::write_datagram, (*tci).second._texcoords);
WRITE_PTA(manager, me, IPD_ushort::write_datagram, (*tci).second._tindex);
@ -1160,16 +1218,16 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
for (ci = _temp_texcoord_set.begin();
ci != _temp_texcoord_set.end();
++ci) {
CPT(TexCoordName) tc = DCAST(TexCoordName, p_list[pi++]);
CPT(InternalName) tc = DCAST(InternalName, p_list[pi++]);
TexCoordDef *def = (*ci);
_texcoords_by_name[tc] = *def;
/*
cerr << "TexCoordName from Geom " << (void *)this
cerr << "InternalName from Geom " << (void *)this
<< " complete pointers " << tc << " " << *tc
<< " = " << def->_texcoords << " and " << def->_tindex << "\n";
*/
delete def;
if (tc == TexCoordName::get_default()) {
if (tc == InternalName::get_texcoord()) {
_bind[G_TEXCOORD] = G_PER_VERTEX;
}
}

View File

@ -34,7 +34,7 @@
#include "pta_TexCoordf.h"
#include "pta_ushort.h"
#include "pta_int.h"
#include "texCoordName.h"
#include "internalName.h"
#include "textureStage.h"
#include "pset.h"
@ -146,9 +146,9 @@ PUBLISHED:
const PTA_ushort &cindex = PTA_ushort());
void set_texcoords(const PTA_TexCoordf &texcoords, GeomBindType bind,
const PTA_ushort &tindex = PTA_ushort());
void set_texcoords(const TexCoordName *name, const PTA_TexCoordf &texcoords,
void set_texcoords(const InternalName *name, const PTA_TexCoordf &texcoords,
const PTA_ushort &tindex = PTA_ushort());
void remove_texcoords(const TexCoordName *name);
void remove_texcoords(const InternalName *name);
public:
// These can't be published because of the pass-by-reference
@ -171,19 +171,19 @@ PUBLISHED:
INLINE GeomBindType get_binding(int attr) const;
INLINE bool has_any_texcoords() const;
INLINE bool has_texcoords(const TexCoordName *name) const;
INLINE bool has_texcoords(const InternalName *name) const;
INLINE PTA_Vertexf get_coords_array() const;
INLINE PTA_Normalf get_normals_array() const;
INLINE PTA_Colorf get_colors_array() const;
INLINE PTA_TexCoordf get_texcoords_array() const;
INLINE PTA_TexCoordf get_texcoords_array(const TexCoordName *name) const;
INLINE PTA_TexCoordf get_texcoords_array(const InternalName *name) const;
INLINE PTA_ushort get_coords_index() const;
INLINE PTA_ushort get_normals_index() const;
INLINE PTA_ushort get_colors_index() const;
INLINE PTA_ushort get_texcoords_index() const;
INLINE PTA_ushort get_texcoords_index(const TexCoordName *name) const;
INLINE PTA_ushort get_texcoords_index(const InternalName *name) const;
INLINE bool are_texcoords_indexed() const;
void prepare(PreparedGraphicsObjects *prepared_objects);
@ -194,16 +194,16 @@ PUBLISHED:
INLINE void set_lengths(const PTA_int &lengths);
INLINE PTA_int get_lengths() const;
virtual int get_num_vertices_per_prim() const=0;
virtual int get_num_more_vertices_than_components() const=0;
virtual bool uses_components() const=0;
virtual int get_num_vertices_per_prim() const;
virtual int get_num_more_vertices_than_components() const;
virtual bool uses_components() const;
INLINE int get_num_vertices() const;
// Returns the length of the indicated primitive. Often this is the
// same for all primitives in the Geom. However, geoms which use
// the lengths array will redefine this appropriately.
virtual int get_length(int prim) const=0;
virtual int get_length(int prim) const;
virtual Geom *explode() const;
virtual PTA_ushort get_tris() const;
@ -223,7 +223,7 @@ public:
INLINE const Normalf &get_next_normal(NormalIterator &niterator) const;
INLINE TexCoordIterator make_texcoord_iterator() const;
INLINE TexCoordIterator make_texcoord_iterator(const TexCoordName *texcoord_name) const;
INLINE TexCoordIterator make_texcoord_iterator(const InternalName *texcoord_name) const;
INLINE const TexCoordf &get_next_texcoord(TexCoordIterator &tciterator) const;
void setup_multitexcoord_iterator(MultiTexCoordIterator &iterator,
const ActiveTextureStages &active_stages,
@ -245,8 +245,8 @@ public:
virtual void config();
// Immediate mode drawing functions - issue graphics commands
virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc) = 0;
virtual void print_draw_immediate() const = 0;
virtual void draw_immediate(GraphicsStateGuardianBase *gsg, GeomContext *gc);
virtual void print_draw_immediate() const;
void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any) const;
@ -277,7 +277,7 @@ protected:
// A pmap, not a phash_map, to save space because it will probably
// have only one element.
typedef pmap<CPT(TexCoordName), TexCoordDef> TexCoordsByName;
typedef pmap<CPT(InternalName), TexCoordDef> TexCoordsByName;
TexCoordsByName _texcoords_by_name;
// Functions to extract component values, one at a time.
@ -286,7 +286,7 @@ protected:
GetNextColor *_get_color;
GetNextTexCoord *_get_texcoord;
// temporary storage until complete_pointers fills in _texcoords_by_name's TexCoordName *
// temporary storage until complete_pointers fills in _texcoords_by_name's InternalName *
typedef pvector<TexCoordDef *> TexCoordDefSet;
TexCoordDefSet _temp_texcoord_set;

View File

@ -11,4 +11,14 @@
#include "geomTri.cxx"
#include "geomTrifan.cxx"
#include "geomTristrip.cxx"
#include "qpgeom.cxx"
#include "qpgeomMunger.cxx"
#include "qpgeomPrimitive.cxx"
#include "qpgeomTriangles.cxx"
#include "qpgeomTristrips.cxx"
#include "qpgeomTrifans.cxx"
#include "qpgeomVertexArrayFormat.cxx"
#include "qpgeomVertexData.cxx"
#include "qpgeomVertexDataType.cxx"
#include "qpgeomVertexFormat.cxx"
#include "qpgeomVertexIterator.cxx"

View File

@ -2,6 +2,7 @@
#include "config_gobj.cxx"
#include "drawable.cxx"
#include "geomContext.cxx"
#include "internalName.cxx"
#include "material.cxx"
#include "materialPool.cxx"
#include "orthographicLens.cxx"
@ -13,5 +14,4 @@
#include "texture.cxx"
#include "textureContext.cxx"
#include "texturePool.cxx"
#include "texCoordName.cxx"
#include "textureStage.cxx"

View File

@ -0,0 +1,185 @@
// Filename: internalName.I
// Created by: masad (15Jul04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: InternalName::make
// Access: Published, Static
// Description: The public interface for constructing an InternalName
// pointer. This will return a new InternalName
// representing the indicated name, if this is the first
// time the particular name has been requested; if the
// name is already in use, it will return the existing
// pointer.
//
// If the string contains the '.' character, the string
// will be divided at the dots and the so-defined
// hierarchy of names will be registered. This is
// handled transparently.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
make(const string &name) {
return get_root()->append(name);
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_parent
// Access: Published
// Description: Return the parent of this InternalName. All names
// have a parent, except the root name.
////////////////////////////////////////////////////////////////////
INLINE InternalName *InternalName::
get_parent() const {
return _parent;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_basename
// Access: Published
// Description: Return the name represented by just this particular
// InternalName object, ignoring its parents names.
// This is everything after the rightmost dot.
////////////////////////////////////////////////////////////////////
INLINE const string &InternalName::
get_basename() const {
return _basename;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_root
// Access: Published, Static
// Description: Returns the standard root InternalName. This is the
// root of all other InternalNames. It has no name
// itself, and it is the only InternalName with no
// parent.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_root() {
if (_root == (InternalName *)NULL) {
_root = new InternalName(NULL, "");
}
return _root;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_error
// Access: Published, Static
// Description: Returns the standard InternalName "error".
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_error() {
if (_error == (InternalName *)NULL) {
_error = InternalName::make("error");
}
return _error;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_vertex
// Access: Published, Static
// Description: Returns the standard InternalName "vertex".
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_vertex() {
if (_vertex == (InternalName *)NULL) {
_vertex = InternalName::make("vertex");
}
return _vertex;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_normal
// Access: Published, Static
// Description: Returns the standard InternalName "normal".
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_normal() {
if (_normal == (InternalName *)NULL) {
_normal = InternalName::make("normal");
}
return _normal;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_tangent
// Access: Published, Static
// Description: Returns the standard InternalName "tangent".
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_tangent() {
if (_tangent == (InternalName *)NULL) {
_tangent = InternalName::make("tangent");
}
return _tangent;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_binormal
// Access: Published, Static
// Description: Returns the standard InternalName "binormal".
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_binormal() {
if (_binormal == (InternalName *)NULL) {
_binormal = InternalName::make("binormal");
}
return _binormal;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_texcoord
// Access: Published, Static
// Description: Returns the standard InternalName "texcoord".
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_texcoord() {
if (_texcoord == (InternalName *)NULL) {
_texcoord = InternalName::make("texcoord");
}
return _texcoord;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_texcoord_name
// Access: Published, Static
// Description: Returns the InternalName "texcoord.name", where name
// is the supplied string. This, by convention,
// represents the named texture coordinate set.
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_texcoord_name(const string &name) {
return get_texcoord()->append(name);
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_color
// Access: Published, Static
// Description: Returns the standard InternalName "color".
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_color() {
if (_color == (InternalName *)NULL) {
_color = InternalName::make("color");
}
return _color;
}
INLINE ostream &
operator << (ostream &out, const InternalName &tcn) {
tcn.output(out);
return out;
}

View File

@ -0,0 +1,231 @@
// Filename: internalName.cxx
// Created by: masad (15Jul04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "internalName.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "bamReader.h"
#include "preparedGraphicsObjects.h"
PT(InternalName) InternalName::_root;
PT(InternalName) InternalName::_error;
PT(InternalName) InternalName::_default;
PT(InternalName) InternalName::_vertex;
PT(InternalName) InternalName::_normal;
PT(InternalName) InternalName::_tangent;
PT(InternalName) InternalName::_binormal;
PT(InternalName) InternalName::_texcoord;
PT(InternalName) InternalName::_color;
TypeHandle InternalName::_type_handle;
TypeHandle InternalName::_texcoord_type_handle;
////////////////////////////////////////////////////////////////////
// Function: InternalName::Constructor
// Access: Private
// Description: Use make() to make a new InternalName instance.
////////////////////////////////////////////////////////////////////
InternalName::
InternalName(InternalName *parent, const string &basename) :
_parent(parent),
_basename(basename)
{
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
InternalName::
~InternalName() {
if (_parent != (const InternalName *)NULL) {
NameTable::iterator ni = _parent->_name_table.find(_basename);
nassertv(ni != _parent->_name_table.end());
_parent->_name_table.erase(ni);
}
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::append
// Access: Published
// Description: Constructs a new InternalName based on this name,
// with the indicated string following it. This is a
// cheaper way to construct a hierarchical name than
// InternalName::make(parent->get_name() + ".basename").
////////////////////////////////////////////////////////////////////
PT(InternalName) InternalName::
append(const string &name) {
if (name.empty()) {
return this;
}
size_t dot = name.rfind('.');
if (dot != string::npos) {
return append(name.substr(0, dot))->append(name.substr(dot + 1));
}
NameTable::iterator ni = _name_table.find(name);
if (ni != _name_table.end()) {
return (*ni).second;
}
PT(InternalName) internal_name = new InternalName(this, name);
_name_table[name] = internal_name;
return internal_name;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_name
// Access: Published
// Description: Returns the complete name represented by the
// InternalName and all of its parents.
////////////////////////////////////////////////////////////////////
string InternalName::
get_name() const {
if (_parent == get_root()) {
return _basename;
} else if (_parent == (InternalName *)NULL) {
return string();
} else {
return _parent->get_name() + "." + _basename;
}
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void InternalName::
output(ostream &out) const {
if (_parent == get_root()) {
out << _basename;
} else if (_parent == (InternalName *)NULL) {
out << "(root)";
} else {
_parent->output(out);
out << '.' << _basename;
}
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::register_with_read_factory
// Access: Public, Static
// Description: Factory method to generate a InternalName object
////////////////////////////////////////////////////////////////////
void InternalName::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
BamReader::get_factory()->register_factory(_texcoord_type_handle, make_texcoord_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::finalize
// Access: Public, Virtual
// Description: Method to ensure that any necessary clean up tasks
// that have to be performed by this object are performed
////////////////////////////////////////////////////////////////////
void InternalName::
finalize() {
// Unref the pointer that we explicitly reffed in make_from_bam().
unref();
// We should never get back to zero after unreffing our own count,
// because we expect to have been stored in a pointer somewhere. If
// we do get to zero, it's a memory leak; the way to avoid this is
// to call unref_delete() above instead of unref(), but this is
// dangerous to do from within a virtual function.
nassertv(get_ref_count() != 0);
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type InternalName is encountered
// in the Bam file. It should create the InternalName
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *InternalName::
make_from_bam(const FactoryParams &params) {
// The process of making a InternalName is slightly
// different than making other Writable objects.
// That is because all creation of InternalNames should
// be done through the make() constructor.
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
// The name is the only thing written to the data stream.
string name = scan.get_string();
// Make a new InternalName with that name (or get the previous one
// if there is one already).
PT(InternalName) me = make(name);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
me->ref();
manager->register_finalize(me);
return me.p();
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::make_texcoord_from_bam
// Access: Protected, Static
// Description: This is a temporary method; it exists only to support
// old bam files (4.11 through 4.17) generated before we
// renamed this class from TexCoordName to InternalName.
////////////////////////////////////////////////////////////////////
TypedWritable *InternalName::
make_texcoord_from_bam(const FactoryParams &params) {
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
string name = scan.get_string();
PT(InternalName) me = get_texcoord_name(name);
me->ref();
manager->register_finalize(me);
return me.p();
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::write_datagram
// Access: Public
// Description: Function to write the important information in
// the particular object to a Datagram
////////////////////////////////////////////////////////////////////
void InternalName::
write_datagram(BamWriter *manager, Datagram &me) {
me.add_string(get_name());
}

View File

@ -0,0 +1,129 @@
// Filename: internalName.h
// Created by: drose (15Jul04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef INTERNALNAME_H
#define INTERNALNAME_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h"
#include "pmap.h"
class FactoryParams;
////////////////////////////////////////////////////////////////////
// Class : InternalName
// Description : Encodes a string name in a hash table, mapping it to
// a pointer. This is used to tokenify names so they
// may be used efficiently in low-level Panda
// structures, for instance to differentiate the
// multiple sets of texture coordinates that might be
// stored on a Geom.
//
// InternalNames are hierarchical, with the '.' used by
// convention as a separator character. You can
// construct a single InternalName as a composition of
// one or more other names, or by giving it a source
// string directly.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA InternalName : public TypedWritableReferenceCount {
private:
InternalName(InternalName *parent, const string &basename);
PUBLISHED:
virtual ~InternalName();
INLINE static PT(InternalName) make(const string &name);
PT(InternalName) append(const string &basename);
INLINE InternalName *get_parent() const;
string get_name() const;
INLINE const string &get_basename() const;
void output(ostream &out) const;
// Some predefined built-in names.
INLINE static PT(InternalName) get_root();
INLINE static PT(InternalName) get_error();
INLINE static PT(InternalName) get_vertex();
INLINE static PT(InternalName) get_normal();
INLINE static PT(InternalName) get_tangent();
INLINE static PT(InternalName) get_binormal();
INLINE static PT(InternalName) get_texcoord();
INLINE static PT(InternalName) get_texcoord_name(const string &name);
INLINE static PT(InternalName) get_color();
private:
PT(InternalName) _parent;
string _basename;
typedef phash_map<string, InternalName *, string_hash> NameTable;
NameTable _name_table;
static PT(InternalName) _root;
static PT(InternalName) _error;
static PT(InternalName) _default;
static PT(InternalName) _vertex;
static PT(InternalName) _normal;
static PT(InternalName) _tangent;
static PT(InternalName) _binormal;
static PT(InternalName) _texcoord;
static PT(InternalName) _color;
public:
// Datagram stuff
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &me);
virtual void finalize();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
static TypedWritable *make_texcoord_from_bam(const FactoryParams &params);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "InternalName",
TypedWritableReferenceCount::get_class_type());
// The _texcoord_type_handle is defined only to support older bam
// files, generated before we renamed the type to InternalName.
register_type(_texcoord_type_handle, "TexCoordName",
TypedWritableReferenceCount::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;
static TypeHandle _texcoord_type_handle;
};
INLINE ostream &operator << (ostream &out, const InternalName &tcn);
#include "internalName.I"
#endif

114
panda/src/gobj/qpgeom.I Normal file
View File

@ -0,0 +1,114 @@
// Filename: qpgeom.I
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_vertex_data
// Access: Published
// Description: Returns a const pointer to the GeomVertexData,
// for application code to directly examine (but not
// modify) the geom's underlying data.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomVertexData) qpGeom::
get_vertex_data() const {
CDReader cdata(_cycler);
return cdata->_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_num_primitives
// Access: Published
// Description: Returns the number of GeomPrimitive objects stored
// within the Geom, each of which represents a number of
// primitives of a particular type.
////////////////////////////////////////////////////////////////////
INLINE int qpGeom::
get_num_primitives() const {
CDReader cdata(_cycler);
return cdata->_primitives.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_primitive
// Access: Published
// Description: Returns a const pointer to the ith GeomPrimitive
// object stored within the Geom. Use this call only to
// inspect the ith object; use modify_primitive() or
// set_primitive() if you want to modify it.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomPrimitive *qpGeom::
get_primitive(int i) const {
CDReader cdata(_cycler);
nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL);
return cdata->_primitives[i];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::modify_primitive
// Access: Published
// Description: Returns a modifiable pointer to the ith GeomPrimitive
// object stored within the Geom, so application code
// can directly manipulate the properties of this
// primitive.
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive *qpGeom::
modify_primitive(int i) {
CDWriter cdata(_cycler);
nassertr(i >= 0 && i < (int)cdata->_primitives.size(), NULL);
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, qpGeomPrimitive *primitive) {
CDWriter cdata(_cycler);
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
cdata->_primitives[i] = primitive;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeom::CData::
CData() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeom::CData::
CData(const qpGeom::CData &copy) :
_data(copy._data),
_primitives(copy._primitives)
{
}
INLINE ostream &
operator << (ostream &out, const qpGeom &obj) {
obj.output(out);
return out;
}

395
panda/src/gobj/qpgeom.cxx Normal file
View File

@ -0,0 +1,395 @@
// Filename: qpgeom.cxx
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeom.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle qpGeom::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeom::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeom::
qpGeom() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeom::
qpGeom(const qpGeom &copy) :
/*
TypedWritableReferenceCount(copy),
BoundedObject(copy),
*/
Geom(copy),
_cycler(copy._cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeom::
operator = (const qpGeom &copy) {
/*
TypedWritableReferenceCount::operator = (copy);
BoundedObject::operator = (copy);
*/
Geom::operator = (copy);
_cycler = copy._cycler;
mark_bound_stale();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeom::
~qpGeom() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::make_copy
// Access: Published, Virtual
// Description: Temporarily redefined from Geom base class.
////////////////////////////////////////////////////////////////////
Geom *qpGeom::
make_copy() const {
return new qpGeom(*this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::modify_vertex_data
// Access: Published
// Description: Returns a modifiable pointer to the GeomVertexData,
// so that application code may directly maniuplate the
// geom's underlying data.
////////////////////////////////////////////////////////////////////
PT(qpGeomVertexData) qpGeom::
modify_vertex_data() {
// Perform copy-on-write: if the reference count on the vertex data
// is greater than 1, assume some other Geom has the same pointer,
// so make a copy of it first.
CDWriter cdata(_cycler);
if (cdata->_data->get_ref_count() > 1) {
cdata->_data = new qpGeomVertexData(*cdata->_data);
}
mark_bound_stale();
return cdata->_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::set_vertex_data
// Access: Published
// Description: Replaces the Geom's underlying vertex data table with
// a completely new table.
////////////////////////////////////////////////////////////////////
void qpGeom::
set_vertex_data(PT(qpGeomVertexData) data) {
CDWriter cdata(_cycler);
cdata->_data = data;
mark_bound_stale();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::add_primitive
// Access: Published
// Description: Adds a new GeomPrimitive structure to the Geom
// object. This specifies a particular subset of
// vertices that are used to define geometric primitives
// of the indicated type.
////////////////////////////////////////////////////////////////////
void qpGeom::
add_primitive(qpGeomPrimitive *primitive) {
CDWriter cdata(_cycler);
cdata->_primitives.push_back(primitive);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::remove_primitive
// Access: Published
// Description: Removes the ith primitive from the list.
////////////////////////////////////////////////////////////////////
void qpGeom::
remove_primitive(int i) {
CDWriter cdata(_cycler);
nassertv(i >= 0 && i < (int)cdata->_primitives.size());
cdata->_primitives.erase(cdata->_primitives.begin() + i);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::clear_primitives
// Access: Published
// Description: Removes all the primitives from the Geom object (but
// keeps the same table of vertices). You may then
// re-add primitives one at a time via calls to
// add_primitive().
////////////////////////////////////////////////////////////////////
void qpGeom::
clear_primitives() {
CDWriter cdata(_cycler);
cdata->_primitives.clear();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeom::
output(ostream &out) const {
CDReader cdata(_cycler);
// Get a list of the primitive types contained within this object.
pset<TypeHandle> types;
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end();
++pi) {
types.insert((*pi)->get_type());
}
out << "Geom [";
pset<TypeHandle>::iterator ti;
for (ti = types.begin(); ti != types.end(); ++ti) {
out << " " << (*ti);
}
out << " ], " << cdata->_data->get_num_vertices() << " vertices.";
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeom::
write(ostream &out, int indent_level) const {
CDReader cdata(_cycler);
// Get a list of the primitive types contained within this object.
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end();
++pi) {
(*pi)->write(out, cdata->_data, indent_level);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::draw
// Access: Public
// Description: Actually draws the Geom with the indicated GSG.
////////////////////////////////////////////////////////////////////
void qpGeom::
draw(GraphicsStateGuardianBase *gsg) const {
// PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects();
CDReader cdata(_cycler);
gsg->begin_draw_primitives(cdata->_data);
Primitives::const_iterator pi;
for (pi = cdata->_primitives.begin();
pi != cdata->_primitives.end();
++pi) {
(*pi)->draw(gsg);
}
gsg->end_draw_primitives();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::recompute_bound
// Access: Protected, Virtual
// Description: Recomputes the dynamic bounding volume for this Geom.
// This includes all of the vertices.
////////////////////////////////////////////////////////////////////
BoundingVolume *qpGeom::
recompute_bound() {
// First, get ourselves a fresh, empty bounding volume.
BoundingVolume *bound = BoundedObject::recompute_bound();
nassertr(bound != (BoundingVolume*)0L, bound);
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
// Now actually compute the bounding volume by putting it around all
// of our vertices.
CDReader cdata(_cycler);
const qpGeomVertexFormat *format = cdata->_data->get_format();
int array_index = format->get_array_with(InternalName::get_vertex());
if (array_index < 0) {
// No vertex data.
return bound;
}
const qpGeomVertexArrayFormat *array_format = format->get_array(array_index);
const qpGeomVertexDataType *data_type =
array_format->get_data_type(InternalName::get_vertex());
int stride = array_format->get_stride();
int start = data_type->get_start();
int num_components = data_type->get_num_components();
CPTA_uchar array_data = cdata->_data->get_array_data(array_index);
if (stride == 3 * sizeof(PN_float32) && start == 0 && num_components == 3 &&
(array_data.size() % stride) == 0) {
// Here's an easy special case: it's a standalone table of vertex
// positions, with nothing else in the middle, so we can use
// directly as an array of LPoint3f's.
const LPoint3f *vertices_begin = (const LPoint3f *)&array_data[0];
const LPoint3f *vertices_end = (const LPoint3f *)&array_data[array_data.size()];
gbv->around(vertices_begin, vertices_end);
} else {
// Otherwise, we have to copy the vertex positions out one at time.
pvector<LPoint3f> vertices;
size_t p = start;
while (p + stride <= array_data.size()) {
const PN_float32 *v = (const PN_float32 *)&array_data[p];
LPoint3f vertex;
qpGeomVertexData::to_vec3(vertex, v, num_components);
vertices.push_back(vertex);
p += stride;
}
const LPoint3f *vertices_begin = &vertices[0];
const LPoint3f *vertices_end = vertices_begin + vertices.size();
gbv->around(vertices_begin, vertices_end);
}
return bound;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// qpGeom.
////////////////////////////////////////////////////////////////////
void qpGeom::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeom::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type qpGeom is encountered
// in the Bam file. It should create the qpGeom
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeom::
make_from_bam(const FactoryParams &params) {
qpGeom *object = new qpGeom;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeom.
////////////////////////////////////////////////////////////////////
void qpGeom::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *qpGeom::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeom::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::CData::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int qpGeom::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeom::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeom.
////////////////////////////////////////////////////////////////////
void qpGeom::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

139
panda/src/gobj/qpgeom.h Normal file
View File

@ -0,0 +1,139 @@
// Filename: qpgeom.h
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOM_H
#define qpGEOM_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "boundedObject.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
#include "qpgeomVertexData.h"
#include "qpgeomPrimitive.h"
#include "pointerTo.h"
#include "geom.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeom
// Description : A container for geometry primitives. This class
// associates one or more GeomPrimitive objects with a
// table of vertices defined by a GeomVertexData object.
// All of the primitives stored in a particular Geom are
// drawn from the same set of vertices (each primitive
// uses a subset of all of the vertices in the table),
// and all of them must be rendered at the same time, in
// the same graphics state.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeom /* : public TypedWritableReferenceCount, public BoundedObject */
// We temporarily inherit from Geom, merely so we can store this
// pointer where a Geom should go, while we have both implementations
// in the codebase. We pick up some additional cruft from Geom that
// we're not really using.
: public Geom
{
PUBLISHED:
qpGeom();
qpGeom(const qpGeom &copy);
void operator = (const qpGeom &copy);
virtual ~qpGeom();
// Temporary.
virtual Geom *make_copy() const;
INLINE CPT(qpGeomVertexData) get_vertex_data() const;
PT(qpGeomVertexData) modify_vertex_data();
void set_vertex_data(PT(qpGeomVertexData) data);
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, qpGeomPrimitive *primitive);
void add_primitive(qpGeomPrimitive *primitive);
void remove_primitive(int i);
void clear_primitives();
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
public:
void draw(GraphicsStateGuardianBase *gsg) const;
protected:
virtual BoundingVolume *recompute_bound();
private:
typedef pvector<PT(qpGeomPrimitive) > Primitives;
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
virtual void fillin(DatagramIterator &scan, BamReader *manager);
PT(qpGeomVertexData) _data;
Primitives _primitives;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
/*TypedWritableReferenceCount::init_type();
BoundedObject::init_type();*/
Geom::init_type();
register_type(_type_handle, "qpGeom",
Geom::get_class_type()
/*TypedWritableReferenceCount::get_class_type(),
BoundedObject::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;
};
INLINE ostream &operator << (ostream &out, const qpGeom &obj);
#include "qpgeom.I"
#endif

View File

@ -0,0 +1,113 @@
// Filename: qpgeomMunger.I
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::is_registered
// Access: Published
// Description: Returns true if this munger has been registered,
// false if it has not. It may not be used for a Geom
// until it has been registered, but once registered, it
// may no longer be modified.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomMunger::
is_registered() const {
return _is_registered;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::register_munger
// Access: Published, Static
// Description: Adds the indicated munger to the registry, if there
// is not an equivalent munger already there; in either
// case, returns the pointer to the equivalent munger
// now in the registry.
//
// This must be called before a munger may be used in a
// Geom. After this call, you should discard the
// original pointer you passed in (which may or may not
// now be invalid) and let its reference count decrement
// normally; you should use only the returned value from
// this point on.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomMunger) qpGeomMunger::
register_munger(qpGeomMunger *munger) {
return get_registry()->register_munger(munger);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::compare_to
// Access: Public
// Description: Provides an arbitrary ordering among all unique
// GeomMungers, so we can store the essentially
// different ones in a big set and throw away the rest.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomMunger::
compare_to(const qpGeomMunger &other) const {
// First, we compare the types; if they are of different types then
// they sort differently.
TypeHandle type = get_type();
TypeHandle other_type = other.get_type();
if (type != other_type) {
return type.get_index() - other_type.get_index();
}
// We only call compare_to_impl() if they have the same type.
return compare_to_impl(&other);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::munge_data
// Access: Public
// Description: Given a source GeomVertexData, converts it if
// necessary to the appropriate data for rendering.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomVertexData) qpGeomMunger::
munge_data(const qpGeomVertexData *data) const {
// We cast away the const pointer, because do_munge_data() needs to
// update caches and stuff, but we trust it not to change any
// user-definable parameters.
return ((qpGeomMunger *)this)->do_munge_data(data);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::munge_format
// Access: Public
// Description: Given a source GeomVertexFormat, converts it if
// necessary to the appropriate format for rendering.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomVertexFormat) qpGeomMunger::
munge_format(const qpGeomVertexFormat *format) const {
// We cast away the const pointer, because do_munge_format() needs
// to update caches and stuff, but we trust it not to change any
// user-definable parameters.
return ((qpGeomMunger *)this)->do_munge_format(format);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::get_registry
// Access: Private
// Description: Returns the global registry object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomMunger::Registry *qpGeomMunger::
get_registry() {
if (_registry == (Registry *)NULL) {
make_registry();
}
return _registry;
}

View File

@ -0,0 +1,282 @@
// Filename: qpgeomMunger.cxx
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomMunger.h"
qpGeomMunger::Registry *qpGeomMunger::_registry = NULL;
TypeHandle qpGeomMunger::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
qpGeomMunger::
qpGeomMunger() :
_is_registered(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomMunger::
~qpGeomMunger() {
if (is_registered()) {
get_registry()->unregister_munger(this);
}
nassertv(_formats.empty());
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::remove_format
// Access: Public
// Description: Removes a prepared GeomVertexFormat from the cache.
////////////////////////////////////////////////////////////////////
void qpGeomMunger::
remove_format(const qpGeomVertexFormat *format) {
// If this assertion is triggered, maybe we accidentally deleted a
// GeomVertexFormat while we were in the process of unregistering,
// causing a recursive re-entry.
nassertv(_is_registered);
Formats::iterator fi;
fi = _formats.find(format);
nassertv(fi != _formats.end());
CPT(qpGeomVertexFormat) derived_format = (*fi).second;
_formats.erase(fi);
// We need to unref the derived format, if we reffed it earlier.
if (derived_format != format) {
derived_format->unref();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::remove_data
// Access: Public
// Description: Removes a prepared GeomVertexData from the cache.
////////////////////////////////////////////////////////////////////
void qpGeomMunger::
remove_data(const qpGeomVertexData *data) {
// If this assertion is triggered, maybe we accidentally deleted a
// GeomVertexData while we were in the process of unregistering,
// causing a recursive re-entry.
nassertv(_is_registered);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::do_munge_data
// Access: Protected
// Description: The protected implementation of munge_data(). This
// exists just to cast away the const pointer.
////////////////////////////////////////////////////////////////////
CPT(qpGeomVertexData) qpGeomMunger::
do_munge_data(const qpGeomVertexData *data) {
nassertr(_is_registered, NULL);
CPT(qpGeomVertexFormat) orig_format = data->get_format();
CPT(qpGeomVertexFormat) new_format = munge_format(orig_format);
if (new_format == orig_format) {
// Trivial case.
return data;
}
return data->convert_to(new_format);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::do_munge_format
// Access: Protected
// Description: The protected implementation of munge_format(). This
// exists just to cast away the const pointer.
////////////////////////////////////////////////////////////////////
CPT(qpGeomVertexFormat) qpGeomMunger::
do_munge_format(const qpGeomVertexFormat *format) {
nassertr(_is_registered, NULL);
nassertr(format->is_registered(), NULL);
Formats::iterator fi;
fi = _formats.find(format);
if (fi != _formats.end()) {
// This format was previously munged, so the answer will be the
// same.
return (*fi).second;
}
// We have to munge this format for the first time.
CPT(qpGeomVertexFormat) derived_format = munge_format_impl(format);
nassertr(derived_format->is_registered(), NULL);
// Store the answer in the map, so we can quickly get it next time.
bool inserted = _formats.insert(Formats::value_type(format, derived_format)).second;
nassertr(inserted, NULL);
// Tell the source format that we have its pointer.
inserted = ((qpGeomVertexFormat *)format)->_mungers.insert(this).second;
nassertr(inserted, NULL);
// We also want to keep a reference count on the derived format, but
// only if it is actually a different pointer from the original
// format--otherwise it would cause a self-referential reference
// count.
if (derived_format != format) {
derived_format->ref();
}
return derived_format;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::munge_format_impl
// Access: Protected, Virtual
// Description: Given a source GeomVertexFormat, converts it if
// necessary to the appropriate format for rendering.
////////////////////////////////////////////////////////////////////
CPT(qpGeomVertexFormat) qpGeomMunger::
munge_format_impl(const qpGeomVertexFormat *orig) {
return orig;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::compare_to_impl
// Access: Protected, Virtual
// Description: Called to compare two GeomMungers who are known to be
// of the same type, for an apples-to-apples comparison.
// This will never be called on two pointers of a
// different type.
////////////////////////////////////////////////////////////////////
int qpGeomMunger::
compare_to_impl(const qpGeomMunger *other) const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::make_registry
// Access: Private
// Description: Returns the global registry object.
////////////////////////////////////////////////////////////////////
void qpGeomMunger::
make_registry() {
if (_registry == (Registry *)NULL) {
_registry = new Registry;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::do_register
// Access: Private
// Description: Called internally when the munger is registered.
////////////////////////////////////////////////////////////////////
void qpGeomMunger::
do_register() {
nassertv(!_is_registered);
nassertv(_formats.empty());
_is_registered = true;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::do_unregister
// Access: Private
// Description: Called internally when the munger is unregistered.
////////////////////////////////////////////////////////////////////
void qpGeomMunger::
do_unregister() {
nassertv(_is_registered);
_is_registered = false;
// Unregistering means we should blow away the cache.
Formats::iterator fi;
for (fi = _formats.begin(); fi != _formats.end(); ++fi) {
const qpGeomVertexFormat *format = (*fi).first;
CPT(qpGeomVertexFormat) derived_format = (*fi).second;
size_t num_erased = ((qpGeomVertexFormat *)format)->_mungers.erase(this);
nassertv(num_erased == 1);
if (derived_format != format) {
derived_format->unref();
}
}
_formats.clear();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::Registry::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
qpGeomMunger::Registry::
Registry() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::Registry::register_munger
// Access: Public
// Description: Adds the indicated munger to the registry, if there
// is not an equivalent munger already there; in either
// case, returns the pointer to the equivalent munger
// now in the registry.
//
// This must be called before a munger may be used in a
// Geom. After this call, you should discard the
// original pointer you passed in (which may or may not
// now be invalid) and let its reference count decrement
// normally; you should use only the returned value from
// this point on.
////////////////////////////////////////////////////////////////////
CPT(qpGeomMunger) qpGeomMunger::Registry::
register_munger(qpGeomMunger *munger) {
if (munger->is_registered()) {
return munger;
}
// Save the incoming pointer in a local PointerTo, so that if it has
// a zero reference count and is not added into the map below, it
// will be automatically deleted when this function returns.
PT(qpGeomMunger) pt_munger = munger;
Mungers::iterator mi = _mungers.insert(munger).first;
qpGeomMunger *new_munger = (*mi);
if (!new_munger->is_registered()) {
new_munger->do_register();
}
return new_munger;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomMunger::Registry::unregister_munger
// Access: Public
// Description: Removes the indicated munger from the registry.
// Normally this should not be done until the munger is
// destructing.
////////////////////////////////////////////////////////////////////
void qpGeomMunger::Registry::
unregister_munger(qpGeomMunger *munger) {
nassertv(munger->is_registered());
Mungers::iterator mi = _mungers.find(munger);
nassertv(mi != _mungers.end());
_mungers.erase(mi);
munger->do_unregister();
}

View File

@ -0,0 +1,121 @@
// Filename: qpgeomMunger.h
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMMUNGER_H
#define qpGEOMMUNGER_H
#include "pandabase.h"
#include "typedReferenceCount.h"
#include "qpgeomVertexFormat.h"
#include "indirectCompareTo.h"
#include "pmap.h"
#include "pset.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomMunger
// Description : Objects of this class are used to convert vertex data
// from a Geom into a format suitable for passing to the
// rendering backend. Typically, the rendering backend
// will create a specialization of this class to handle
// its particular needs (e.g. DXGeomMunger). This class
// is necessary because DirectX and OpenGL have somewhat
// different requirements for vertex format.
//
// This also performs runtime application of state
// changes to the vertex data; for instance, by scaling
// all of the color values in response to a
// ColorScaleAttrib.
//
// A GeomMunger must be registered before it can be
// used, and once registered, the object is constant and
// cannot be changed. All registered GeomMungers that
// perform the same operation will have the same
// pointer.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomMunger : public TypedReferenceCount {
public:
qpGeomMunger();
virtual ~qpGeomMunger();
INLINE bool is_registered() const;
INLINE static CPT(qpGeomMunger) register_munger(qpGeomMunger *munger);
INLINE CPT(qpGeomVertexFormat) munge_format(const qpGeomVertexFormat *format) const;
void remove_format(const qpGeomVertexFormat *format);
INLINE CPT(qpGeomVertexData) munge_data(const qpGeomVertexData *data) const;
void remove_data(const qpGeomVertexData *data);
public:
INLINE int compare_to(const qpGeomMunger &other) const;
protected:
CPT(qpGeomVertexFormat) do_munge_format(const qpGeomVertexFormat *format);
CPT(qpGeomVertexData) do_munge_data(const qpGeomVertexData *data);
virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig);
virtual int compare_to_impl(const qpGeomMunger *other) const;
private:
class Registry;
INLINE static Registry *get_registry();
static void make_registry();
void do_register();
void do_unregister();
typedef pmap<const qpGeomVertexFormat *, const qpGeomVertexFormat *> Formats;
Formats _formats;
bool _is_registered;
typedef pset<qpGeomMunger *, IndirectCompareTo<qpGeomMunger> > Mungers;
class Registry {
public:
Registry();
CPT(qpGeomMunger) register_munger(qpGeomMunger *munger);
void unregister_munger(qpGeomMunger *munger);
Mungers _mungers;
};
static Registry *_registry;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedReferenceCount::init_type();
register_type(_type_handle, "qpGeomMunger",
TypedReferenceCount::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;
};
#include "qpgeomMunger.I"
#endif

View File

@ -0,0 +1,132 @@
// Filename: qpgeomPrimitive.I
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_vertices
// Access: Published
// Description: Returns the number of vertex vertices used by all the
// primitives in this object.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_num_vertices() const {
CDReader cdata(_cycler);
return cdata->_vertices.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_vertex
// Access: Published
// Description: Returns the ith vertex index in the table.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_vertex(int i) const {
CDReader cdata(_cycler);
nassertr(i >= 0 && i < (int)cdata->_vertices.size(), -1);
return cdata->_vertices[i];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_vertices
// Access: Published
// Description: Returns a const pointer to the vertex index array so
// application code can read it directly. Do not
// attempt to modify the returned array; use
// modify_vertices() or set_vertices() for this.
////////////////////////////////////////////////////////////////////
INLINE CPTA_ushort qpGeomPrimitive::
get_vertices() const {
CDReader cdata(_cycler);
return cdata->_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_vertices
// Access: Published
// Description: Returns a const pointer to the primitive lengths
// array so application code can read it directly. Do
// not attempt to modify the returned array; use
// modify_lengths() or set_lengths() for this.
//
// Note that simple primitive types, like triangles, do
// not have a lengths array: since all the primitives
// have the same number of vertices, it is not needed.
////////////////////////////////////////////////////////////////////
INLINE CPTA_int qpGeomPrimitive::
get_lengths() const {
CDReader cdata(_cycler);
return cdata->_lengths;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_min_vertex
// Access: Published
// Description: Returns the minimum vertex index number used by the
// primitives in this object.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_min_vertex() const {
CDReader cdata(_cycler);
if (!cdata->_got_minmax) {
((qpGeomPrimitive *)this)->recompute_minmax();
}
return cdata->_min_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_max_vertex
// Access: Published
// Description: Returns the maximum vertex index number used by the
// primitives in this object.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomPrimitive::
get_max_vertex() const {
CDReader cdata(_cycler);
if (!cdata->_got_minmax) {
((qpGeomPrimitive *)this)->recompute_minmax();
}
return cdata->_max_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive::CData::
CData() :
_got_minmax(true),
_min_vertex(0),
_max_vertex(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeomPrimitive::CData::
CData(const qpGeomPrimitive::CData &copy) :
_vertices(copy._vertices),
_lengths(copy._lengths),
_got_minmax(copy._got_minmax),
_min_vertex(copy._min_vertex),
_max_vertex(copy._max_vertex)
{
}

View File

@ -0,0 +1,520 @@
// Filename: qpgeomPrimitive.cxx
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomPrimitive.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexArrayFormat.h"
#include "qpgeomVertexDataType.h"
#include "internalName.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "indent.h"
TypeHandle qpGeomPrimitive::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomPrimitive::
qpGeomPrimitive() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomPrimitive::
qpGeomPrimitive(const qpGeomPrimitive &copy) :
TypedWritableReferenceCount(copy),
_cycler(copy._cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomPrimitive::
~qpGeomPrimitive() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::add_vertex
// Access: Published
// Description: Adds the indicated vertex to the list of vertex
// indices used by the graphics primitive type. To
// define primitive, you must call add_vertex() for each
// vertex of the new primitve, and then call
// close_primitive() after you have specified the last
// vertex of each primitive.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
add_vertex(int vertex) {
unsigned short short_vertex = vertex;
nassertv((int)short_vertex == vertex);
CDWriter cdata(_cycler);
cdata->_vertices.push_back(short_vertex);
if (cdata->_got_minmax) {
cdata->_min_vertex = min(cdata->_min_vertex, short_vertex);
cdata->_max_vertex = max(cdata->_min_vertex, short_vertex);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::add_consecutive_vertices
// Access: Published
// Description: Adds a consecutive sequence of vertices, beginning at
// start, to the primitive.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
add_consecutive_vertices(int start, int num_vertices) {
int end = (start + num_vertices) - 1;
unsigned short short_start = start;
unsigned short short_end = end;
nassertv((int)short_start == start && (int)short_end == end);
CDWriter cdata(_cycler);
for (unsigned short v = short_start; v <= short_end; ++v) {
cdata->_vertices.push_back(v);
}
if (cdata->_got_minmax) {
cdata->_min_vertex = min(cdata->_min_vertex, short_start);
cdata->_max_vertex = max(cdata->_min_vertex, short_end);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::close_primitive
// Access: Published
// Description: Indicates that the previous n calls to add_vertex(),
// since the last call to close_primitive(), have fully
// defined a new primitive.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
close_primitive() {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
CDWriter cdata(_cycler);
if (num_vertices_per_primitive == 0) {
// This is a complex primitive type like a triangle strip: each
// primitive uses a different number of vertices.
if (cdata->_lengths.empty() ||
cdata->_lengths.back() != (int)cdata->_vertices.size()) {
cdata->_lengths.push_back((int)cdata->_vertices.size());
}
} else {
// This is a simple primitive type like a triangle: each primitive
// uses the same number of vertices. Assert that we added the
// correct number of vertices.
nassertv((int)cdata->_vertices.size() % num_vertices_per_primitive == 0);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::clear_vertices
// Access: Published
// Description: Removes all of the vertices and primitives from the
// object, so they can be re-added.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
clear_vertices() {
CDWriter cdata(_cycler);
cdata->_vertices.clear();
cdata->_lengths.clear();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::modify_vertices
// Access: Published
// Description: Returns a modifiable pointer to the vertex index
// list, so application code can directly fiddle with
// this data. Use with caution, since there are no
// checks that the data will be left in a stable state.
////////////////////////////////////////////////////////////////////
PTA_ushort qpGeomPrimitive::
modify_vertices() {
CDWriter cdata(_cycler);
return cdata->_vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_vertices
// Access: Published
// Description: Completely replaces the vertex index list with a new
// table. Chances are good that you should also replace
// the lengths list with set_lengths() at the same time.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_vertices(PTA_ushort vertices) {
CDWriter cdata(_cycler);
cdata->_vertices = vertices;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::modify_lengths
// Access: Published
// Description: Returns a modifiable pointer to the primitive lengths
// array, so application code can directly fiddle with
// this data. Use with caution, since there are no
// checks that the data will be left in a stable state.
//
// Note that simple primitive types, like triangles, do
// not have a lengths array: since all the primitives
// have the same number of vertices, it is not needed.
////////////////////////////////////////////////////////////////////
PTA_int qpGeomPrimitive::
modify_lengths() {
CDWriter cdata(_cycler);
return cdata->_lengths;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::set_lengths
// Access: Published
// Description: Completely replaces the primitive lengths array with
// a new table. Chances are good that you should also
// replace the vertices list with set_vertices() at the
// same time.
//
// Note that simple primitive types, like triangles, do
// not have a lengths array: since all the primitives
// have the same number of vertices, it is not needed.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
set_lengths(PTA_int lengths) {
CDWriter cdata(_cycler);
cdata->_lengths = lengths;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_vertices_per_primitive
// Access: Published, Virtual
// Description: 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 qpGeomPrimitive::
get_num_vertices_per_primitive() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_num_primitives
// Access: Published
// Description: Returns the number of individual primitives stored
// within this object. All primitives are the same
// type.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_num_primitives() const {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
CDReader cdata(_cycler);
if (num_vertices_per_primitive == 0) {
// This is a complex primitive type like a triangle strip: each
// primitive uses a different number of vertices.
return cdata->_lengths.size();
} else {
// This is a simple primitive type like a triangle: each primitive
// uses the same number of vertices.
return ((int)cdata->_vertices.size() / num_vertices_per_primitive);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_start
// Access: Published
// Description: Returns the element within the _vertices list at which
// the ith primitive starts.
//
// If i is one more than the highest valid primitive
// vertex, the return value will be one more than the
// last valid vertex. Thus, it is always true that the
// vertices used by a particular primitive i are the set
// get_primitive_start(i) <= vi < get_primitive_start(i
// + 1).
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_primitive_start(int i) const {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
if (num_vertices_per_primitive == 0) {
// This is a complex primitive type like a triangle strip: each
// primitive uses a different number of vertices.
CDReader cdata(_cycler);
nassertr(i >= 0 && i <= (int)cdata->_lengths.size(), -1);
if (i == 0) {
return 0;
} else {
return cdata->_lengths[i - 1];
}
} else {
// This is a simple primitive type like a triangle: each primitive
// uses the same number of vertices.
return i * num_vertices_per_primitive;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::get_primitive_num_vertices
// Access: Published
// Description: Returns the number of vertices used by the ith
// primitive.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::
get_primitive_num_vertices(int i) const {
int num_vertices_per_primitive = get_num_vertices_per_primitive();
if (num_vertices_per_primitive == 0) {
// This is a complex primitive type like a triangle strip: each
// primitive uses a different number of vertices.
CDReader cdata(_cycler);
nassertr(i >= 0 && i < (int)cdata->_lengths.size(), 0);
return cdata->_lengths[i];
} else {
// This is a simple primitive type like a triangle: each primitive
// uses the same number of vertices.
return num_vertices_per_primitive;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::decompose
// Access: Published, Virtual
// Description: Decomposes a complex primitive type into a simpler
// primitive type, for instance triangle strips to
// triangles, 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 triangles on the
// primitive without having to write handlers for each
// possible kind of primitive type.
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomPrimitive::
decompose(const qpGeomVertexData *vertex_data) {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
output(ostream &out, const qpGeomVertexData *vertex_data) const {
out << get_type() << ", " << get_num_primitives()
<< ", " << get_num_vertices();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::write
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
write(ostream &out, const qpGeomVertexData *vertex_data,
int indent_level) const {
indent(out, indent_level)
<< get_type() << ":\n";
int num_primitives = get_num_primitives();
for (int i = 0; i < num_primitives; i++) {
indent(out, indent_level + 2)
<< "[";
int begin = get_primitive_start(i);
int end = get_primitive_start(i + 1);
for (int vi = begin; vi < end; vi++) {
out << " " << get_vertex(vi);
}
out << " ]\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::calc_tight_bounds
// Access: Public, Virtual
// Description: Expands min_point and max_point to include all of the
// vertices in the Geom, if any. found_any is set true
// if any points are found. It is the caller's
// responsibility to initialize min_point, max_point,
// and found_any before calling this function.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const qpGeomVertexData *vertex_data) const {
CDReader cdata(_cycler);
const qpGeomVertexFormat *format = vertex_data->get_format();
int array_index = format->get_array_with(InternalName::get_vertex());
if (array_index < 0) {
// No vertex data.
return;
}
const qpGeomVertexArrayFormat *array_format = format->get_array(array_index);
const qpGeomVertexDataType *data_type =
array_format->get_data_type(InternalName::get_vertex());
int stride = array_format->get_stride();
int start = data_type->get_start();
int num_components = data_type->get_num_components();
CPTA_uchar array_data = vertex_data->get_array_data(array_index);
PTA_ushort::const_iterator ii;
for (ii = cdata->_vertices.begin(); ii != cdata->_vertices.end(); ++ii) {
int index = (int)(*ii);
const PN_float32 *v = (const PN_float32 *)&array_data[start + index * stride];
LPoint3f vertex;
qpGeomVertexData::to_vec3(vertex, v, num_components);
if (found_any) {
min_point.set(min(min_point[0], vertex[0]),
min(min_point[1], vertex[1]),
min(min_point[2], vertex[2]));
max_point.set(max(max_point[0], vertex[0]),
max(max_point[1], vertex[1]),
max(max_point[2], vertex[2]));
} else {
min_point = vertex;
max_point = vertex;
found_any = true;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::recompute_minmax
// Access: Private
// Description: Recomputes the _min_vertex and _max_vertex values if
// necessary.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
recompute_minmax() {
CDWriter cdata(_cycler);
if (cdata->_vertices.empty()) {
cdata->_min_vertex = 0;
cdata->_max_vertex = 0;
} else {
PTA_ushort::const_iterator ii = cdata->_vertices.begin();
cdata->_min_vertex = (*ii);
cdata->_max_vertex = (*ii);
++ii;
while (ii != cdata->_vertices.end()) {
cdata->_min_vertex = min(cdata->_min_vertex, (*ii));
cdata->_max_vertex = max(cdata->_min_vertex, (*ii));
++ii;
}
}
cdata->_got_minmax = true;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeomPrimitive.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *qpGeomPrimitive::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int qpGeomPrimitive::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomPrimitive::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeomPrimitive.
////////////////////////////////////////////////////////////////////
void qpGeomPrimitive::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,156 @@
// Filename: qpgeomPrimitive.h
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMPRIMITIVE_H
#define qpGEOMPRIMITIVE_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "luse.h"
#include "pointerTo.h"
#include "pta_ushort.h"
#include "pta_int.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
class qpGeomVertexData;
class GraphicsStateGuardianBase;
class GeomContext;
class FactoryParams;
////////////////////////////////////////////////////////////////////
// Class : qpGeomPrimitive
// Description : This is an abstract base class for a family of
// classes that represent the fundamental geometry
// primitives that may be stored in a Geom.
//
// They all have in common the fact that they are
// defined by tables of vertex data stored in a
// GeomVertexData object. Each GeomPrimitive object
// contains an ordered list of integers, which index
// into the vertex array defined by the GeomVertexData
// and define the particular vertices of the
// GeomVertexData that are used for this primitive.
//
// The meaning of a given arrangement of vertices is
// defined by each individual primitive type; for
// instance, a GeomTriangle renders a triangle from each
// three consecutive vertices, while a GeomTriangleStrip
// renders a strip of (n - 2) connected triangles from
// each sequence of n vertices.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomPrimitive : public TypedWritableReferenceCount {
PUBLISHED:
qpGeomPrimitive();
qpGeomPrimitive(const qpGeomPrimitive &copy);
virtual ~qpGeomPrimitive();
INLINE int get_num_vertices() const;
INLINE int get_vertex(int i) const;
void add_vertex(int vertex);
void add_consecutive_vertices(int start, int num_vertices);
void close_primitive();
void clear_vertices();
INLINE CPTA_ushort get_vertices() const;
PTA_ushort modify_vertices();
void set_vertices(PTA_ushort vertices);
INLINE CPTA_int get_lengths() const;
PTA_int modify_lengths();
void set_lengths(PTA_int lengths);
INLINE int get_min_vertex() const;
INLINE int get_max_vertex() const;
virtual int get_num_vertices_per_primitive() const;
int get_num_primitives() const;
int get_primitive_start(int i) const;
int get_primitive_num_vertices(int i) const;
virtual PT(qpGeomPrimitive) decompose(const qpGeomVertexData *vertex_data);
virtual void output(ostream &out, const qpGeomVertexData *vertex_data) const;
virtual void write(ostream &out, const qpGeomVertexData *vertex_data,
int indent_level) const;
public:
virtual void draw(GraphicsStateGuardianBase *gsg)=0;
virtual void calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const qpGeomVertexData *vertex_data) const;
private:
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
virtual void fillin(DatagramIterator &scan, BamReader *manager);
PTA_ushort _vertices;
PTA_int _lengths;
bool _got_minmax;
unsigned short _min_vertex;
unsigned short _max_vertex;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
void recompute_minmax();
public:
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "qpGeomPrimitive",
TypedWritableReferenceCount::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 qpGeom;
};
#include "qpgeomPrimitive.I"
#endif

View File

@ -0,0 +1,110 @@
// Filename: qpgeomTriangles.cxx
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomTriangles.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle qpGeomTriangles::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTriangles::
qpGeomTriangles() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTriangles::
qpGeomTriangles(const qpGeomTriangles &copy) :
qpGeomPrimitive(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTriangles::
~qpGeomTriangles() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::get_num_vertices_per_primitive
// Access: Published, Virtual
// Description: 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 qpGeomTriangles::
get_num_vertices_per_primitive() const {
return 3;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::draw
// Access: Public, Virtual
// Description: Calls the appropriate method on the GSG to draw the
// primitive.
////////////////////////////////////////////////////////////////////
void qpGeomTriangles::
draw(GraphicsStateGuardianBase *gsg) {
gsg->draw_triangles(this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// qpGeom.
////////////////////////////////////////////////////////////////////
void qpGeomTriangles::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTriangles::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type qpGeom is encountered
// in the Bam file. It should create the qpGeom
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomTriangles::
make_from_bam(const FactoryParams &params) {
qpGeomTriangles *object = new qpGeomTriangles;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}

View File

@ -0,0 +1,68 @@
// Filename: qpgeomTriangles.h
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMTRIANGLES_H
#define qpGEOMTRIANGLES_H
#include "pandabase.h"
#include "qpgeomPrimitive.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomTriangles
// Description : Defines a series of disconnected triangles.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomTriangles : public qpGeomPrimitive {
PUBLISHED:
qpGeomTriangles();
qpGeomTriangles(const qpGeomTriangles &copy);
virtual ~qpGeomTriangles();
virtual int get_num_vertices_per_primitive() const;
public:
virtual void draw(GraphicsStateGuardianBase *gsg);
public:
static void register_with_read_factory();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
qpGeomPrimitive::init_type();
register_type(_type_handle, "qpGeomTriangles",
qpGeomPrimitive::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 qpGeom;
};
#endif

View File

@ -0,0 +1,138 @@
// Filename: qpgeomTrifans.cxx
// Created by: drose (08Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomTrifans.h"
#include "qpgeomTriangles.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle qpGeomTrifans::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTrifans::
qpGeomTrifans() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTrifans::
qpGeomTrifans(const qpGeomTrifans &copy) :
qpGeomPrimitive(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTrifans::
~qpGeomTrifans() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::decompose
// Access: Published, Virtual
// Description: Decomposes a complex primitive type into a simpler
// primitive type, for instance triangle strips to
// triangles, 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 triangles on the
// primitive without having to write handlers for each
// possible kind of primitive type.
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomTrifans::
decompose(const qpGeomVertexData *) {
PT(qpGeomTriangles) triangles = new qpGeomTriangles;
CPTA_ushort vertices = get_vertices();
CPTA_int lengths = get_lengths();
CPTA_ushort::const_iterator vi;
vi = vertices.begin();
CPTA_int::const_iterator li;
for (li = lengths.begin(); li != lengths.end(); ++li) {
int length = (*li);
nassertr(length >= 2, triangles.p());
int v0 = (*vi);
++vi;
int v1 = (*vi);
++vi;
for (int i = 2; i < length; i++) {
triangles->add_vertex(v0);
triangles->add_vertex(v1);
triangles->add_vertex(*vi);
triangles->close_primitive();
++vi;
}
}
return triangles.p();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::draw
// Access: Public, Virtual
// Description: Calls the appropriate method on the GSG to draw the
// primitive.
////////////////////////////////////////////////////////////////////
void qpGeomTrifans::
draw(GraphicsStateGuardianBase *gsg) {
gsg->draw_trifans(this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// qpGeom.
////////////////////////////////////////////////////////////////////
void qpGeomTrifans::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTrifans::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type qpGeom is encountered
// in the Bam file. It should create the qpGeom
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomTrifans::
make_from_bam(const FactoryParams &params) {
qpGeomTrifans *object = new qpGeomTrifans;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}

View File

@ -0,0 +1,68 @@
// Filename: qpgeomTrifans.h
// Created by: drose (08Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMTRIFANS_H
#define qpGEOMTRIFANS_H
#include "pandabase.h"
#include "qpgeomPrimitive.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomTrifans
// Description : Defines a series of triangle fans.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomTrifans : public qpGeomPrimitive {
PUBLISHED:
qpGeomTrifans();
qpGeomTrifans(const qpGeomTrifans &copy);
virtual ~qpGeomTrifans();
virtual PT(qpGeomPrimitive) decompose(const qpGeomVertexData *vertex_data);
public:
virtual void draw(GraphicsStateGuardianBase *gsg);
public:
static void register_with_read_factory();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
qpGeomPrimitive::init_type();
register_type(_type_handle, "qpGeomTrifans",
qpGeomPrimitive::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 qpGeom;
};
#endif

View File

@ -0,0 +1,148 @@
// Filename: qpgeomTristrips.cxx
// Created by: drose (08Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomTristrips.h"
#include "qpgeomTriangles.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle qpGeomTristrips::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTristrips::
qpGeomTristrips() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTristrips::
qpGeomTristrips(const qpGeomTristrips &copy) :
qpGeomPrimitive(copy)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomTristrips::
~qpGeomTristrips() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::decompose
// Access: Published, Virtual
// Description: Decomposes a complex primitive type into a simpler
// primitive type, for instance triangle strips to
// triangles, 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 triangles on the
// primitive without having to write handlers for each
// possible kind of primitive type.
////////////////////////////////////////////////////////////////////
PT(qpGeomPrimitive) qpGeomTristrips::
decompose(const qpGeomVertexData *) {
PT(qpGeomTriangles) triangles = new qpGeomTriangles;
CPTA_ushort vertices = get_vertices();
CPTA_int lengths = get_lengths();
CPTA_ushort::const_iterator vi;
vi = vertices.begin();
CPTA_int::const_iterator li;
for (li = lengths.begin(); li != lengths.end(); ++li) {
int length = (*li);
nassertr(length >= 2, triangles.p());
int v0 = (*vi);
++vi;
int v1 = (*vi);
++vi;
bool reversed = false;
for (int i = 2; i < length; i++) {
if (reversed) {
triangles->add_vertex(v1);
triangles->add_vertex(v0);
reversed = false;
} else {
triangles->add_vertex(v0);
triangles->add_vertex(v1);
reversed = true;
}
triangles->add_vertex(*vi);
v0 = v1;
v1 = *vi;
triangles->close_primitive();
++vi;
}
}
return triangles.p();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::draw
// Access: Public, Virtual
// Description: Calls the appropriate method on the GSG to draw the
// primitive.
////////////////////////////////////////////////////////////////////
void qpGeomTristrips::
draw(GraphicsStateGuardianBase *gsg) {
gsg->draw_tristrips(this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// qpGeom.
////////////////////////////////////////////////////////////////////
void qpGeomTristrips::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomTristrips::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type qpGeom is encountered
// in the Bam file. It should create the qpGeom
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomTristrips::
make_from_bam(const FactoryParams &params) {
qpGeomTristrips *object = new qpGeomTristrips;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}

View File

@ -0,0 +1,68 @@
// Filename: qpgeomTristrips.h
// Created by: drose (08Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMTRISTRIPS_H
#define qpGEOMTRISTRIPS_H
#include "pandabase.h"
#include "qpgeomPrimitive.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomTristrips
// Description : Defines a series of triangle strips.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomTristrips : public qpGeomPrimitive {
PUBLISHED:
qpGeomTristrips();
qpGeomTristrips(const qpGeomTristrips &copy);
virtual ~qpGeomTristrips();
virtual PT(qpGeomPrimitive) decompose(const qpGeomVertexData *vertex_data);
public:
virtual void draw(GraphicsStateGuardianBase *gsg);
public:
static void register_with_read_factory();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
qpGeomPrimitive::init_type();
register_type(_type_handle, "qpGeomTristrips",
qpGeomPrimitive::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 qpGeom;
};
#endif

View File

@ -0,0 +1,121 @@
// Filename: qpgeomVertexArrayFormat.I
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::is_registered
// Access: Published
// Description: Returns true if this format has been registered,
// false if it has not. It may not be used for a Geom
// until it has been registered, but once registered, it
// may no longer be modified.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexArrayFormat::
is_registered() const {
return _is_registered;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::get_stride
// Access: Published
// Description: Returns the total number of bytes reserved in the
// array for each vertex.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexArrayFormat::
get_stride() const {
return _stride;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::set_stride
// Access: Published
// Description: Changes the total number of bytes reserved in the
// array for each vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexArrayFormat::
set_stride(int stride) {
nassertv(!_is_registered);
_stride = stride;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::get_total_bytes
// Access: Published
// Description: Returns the total number of bytes used by the data
// types within the format, including gaps between
// elements.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexArrayFormat::
get_total_bytes() const {
return _total_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::get_pad_to
// Access: Published
// Description: Returns the byte divisor to which the data record
// must be padded to meet hardware limitations. For
// instance, if this is 4, the stride will be
// automatically rounded up to the next multiple of 4
// bytes.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexArrayFormat::
get_pad_to() const {
return _pad_to;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::get_num_data_types
// Access: Published
// Description: Returns the number of different data types in the
// specification.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexArrayFormat::
get_num_data_types() const {
return (int)_data_types.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::get_data_type
// Access: Published
// Description: Returns the ith data types of the specification.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexDataType *qpGeomVertexArrayFormat::
get_data_type(int i) const {
nassertr(i >= 0 && i < (int)_data_types.size(), NULL);
consider_sort_data_types();
return _data_types[i];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::consider_sort_data_types
// Access: Private
// Description: Resorts the _data_types vector if necessary.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexArrayFormat::
consider_sort_data_types() const {
if (_data_types_unsorted) {
((qpGeomVertexArrayFormat *)this)->sort_data_types();
}
}
INLINE ostream &
operator << (ostream &out, const qpGeomVertexArrayFormat &obj) {
obj.output(out);
return out;
}

View File

@ -0,0 +1,556 @@
// Filename: qpgeomVertexArrayFormat.cxx
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexDataType.h"
#include "qpgeomVertexData.h"
#include "indent.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "indirectLess.h"
TypeHandle qpGeomVertexArrayFormat::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayFormat::
qpGeomVertexArrayFormat() :
_is_registered(false),
_stride(0),
_total_bytes(0),
_pad_to(1),
_data_types_unsorted(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayFormat::
qpGeomVertexArrayFormat(const InternalName *name0, int num_components0,
qpGeomVertexDataType::NumericType numeric_type0) :
_is_registered(false),
_stride(0),
_total_bytes(0),
_pad_to(1),
_data_types_unsorted(false)
{
add_data_type(name0, num_components0, numeric_type0);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayFormat::
qpGeomVertexArrayFormat(const InternalName *name0, int num_components0,
qpGeomVertexDataType::NumericType numeric_type0,
const InternalName *name1, int num_components1,
qpGeomVertexDataType::NumericType numeric_type1) :
_is_registered(false),
_stride(0),
_total_bytes(0),
_pad_to(1),
_data_types_unsorted(false)
{
add_data_type(name0, num_components0, numeric_type0);
add_data_type(name1, num_components1, numeric_type1);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayFormat::
qpGeomVertexArrayFormat(const InternalName *name0, int num_components0,
qpGeomVertexDataType::NumericType numeric_type0,
const InternalName *name1, int num_components1,
qpGeomVertexDataType::NumericType numeric_type1,
const InternalName *name2, int num_components2,
qpGeomVertexDataType::NumericType numeric_type2) :
_is_registered(false),
_stride(0),
_total_bytes(0),
_pad_to(1),
_data_types_unsorted(false)
{
add_data_type(name0, num_components0, numeric_type0);
add_data_type(name1, num_components1, numeric_type1);
add_data_type(name2, num_components2, numeric_type2);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayFormat::
qpGeomVertexArrayFormat(const InternalName *name0, int num_components0,
qpGeomVertexDataType::NumericType numeric_type0,
const InternalName *name1, int num_components1,
qpGeomVertexDataType::NumericType numeric_type1,
const InternalName *name2, int num_components2,
qpGeomVertexDataType::NumericType numeric_type2,
const InternalName *name3, int num_components3,
qpGeomVertexDataType::NumericType numeric_type3) :
_is_registered(false),
_stride(0),
_total_bytes(0),
_pad_to(1),
_data_types_unsorted(false)
{
add_data_type(name0, num_components0, numeric_type0);
add_data_type(name1, num_components1, numeric_type1);
add_data_type(name2, num_components2, numeric_type2);
add_data_type(name3, num_components3, numeric_type3);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayFormat::
qpGeomVertexArrayFormat(const qpGeomVertexArrayFormat &copy) :
_is_registered(false),
_stride(copy._stride),
_total_bytes(copy._total_bytes),
_pad_to(copy._pad_to),
_data_types_unsorted(copy._data_types_unsorted)
{
DataTypes::const_iterator dti;
for (dti = copy._data_types.begin(); dti != copy._data_types.end(); ++dti) {
add_data_type(*(*dti));
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
operator = (const qpGeomVertexArrayFormat &copy) {
nassertv(!_is_registered);
_stride = copy._stride;
_total_bytes = copy._total_bytes;
_pad_to = copy._pad_to;
_data_types.clear();
_data_types_by_name.clear();
_data_types_unsorted = false;
DataTypes::const_iterator dti;
for (dti = copy._data_types.begin(); dti != copy._data_types.end(); ++dti) {
add_data_type(*(*dti));
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayFormat::
~qpGeomVertexArrayFormat() {
// Once registered, these things should not be deallocated.
nassertv(!_is_registered);
DataTypes::iterator dti;
for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) {
delete (*dti);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::add_data_type
// Access: Published
// Description: Adds a new data type to the specification. This is a
// table of per-vertex floating-point numbers such as
// "vertex" or "normal"; you must specify where in each
// record the table starts, and how many components
// (dimensions) exist per vertex.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
add_data_type(const InternalName *name, int num_components,
qpGeomVertexDataType::NumericType numeric_type, int start) {
if (start < 0) {
start = _total_bytes;
qpGeomVertexDataType temp_data_type(name, num_components, numeric_type, 0);
int pad_to = temp_data_type.get_component_bytes();
start = ((start + pad_to - 1) / pad_to) * pad_to;
}
add_data_type(qpGeomVertexDataType(name, num_components,
numeric_type, start));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::add_data_type
// Access: Published
// Description: Adds a new data type to the specification. This is a
// table of per-vertex floating-point numbers such as
// "vertex" or "normal"; you must specify where in each
// record the table starts, and how many components
// (dimensions) exist per vertex.
//
// Adding a data type with the same name as a previous
// type, or that overlaps with one or more previous
// types, quietly removes the previous type(s).
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
add_data_type(const qpGeomVertexDataType &data_type) {
nassertv(!_is_registered);
// Make sure there isn't already a data type with this name.
remove_data_type(data_type.get_name());
// Also make sure there aren't any data types that overlap with this
// one.
const qpGeomVertexDataType *orig_data_type = get_data_type(data_type.get_start(), data_type.get_total_bytes());
while (orig_data_type != (const qpGeomVertexDataType *)NULL) {
remove_data_type(orig_data_type->get_name());
orig_data_type = get_data_type(data_type.get_start(), data_type.get_total_bytes());
}
_total_bytes = max(_total_bytes, data_type.get_start() + data_type.get_total_bytes());
_pad_to = max(_pad_to, data_type.get_component_bytes());
_stride = max(_stride, ((_total_bytes + _pad_to - 1) / _pad_to) * _pad_to);
qpGeomVertexDataType *new_data_type = new qpGeomVertexDataType(data_type);
if (!_data_types.empty() && *new_data_type < *_data_types.back()) {
_data_types_unsorted = true;
}
_data_types.push_back(new_data_type);
_data_types_by_name.insert(DataTypesByName::value_type(new_data_type->get_name(), new_data_type));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::remove_data_type
// Access: Published
// Description: Removes the data type with the indicated name, if
// any. This leaves a gap in the byte structure.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
remove_data_type(const InternalName *name) {
nassertv(!_is_registered);
DataTypesByName::iterator ni;
ni = _data_types_by_name.find(name);
if (ni != _data_types_by_name.end()) {
qpGeomVertexDataType *data_type = (*ni).second;
_data_types_by_name.erase(ni);
DataTypes::iterator dti;
dti = find(_data_types.begin(), _data_types.end(), data_type);
nassertv(dti != _data_types.end());
_data_types.erase(dti);
delete data_type;
// Maybe we just removed the tail data_type. If that's so, we
// should recompute _total_bytes to reflect the new tail.
if (_data_types.empty()) {
_total_bytes = 0;
} else {
consider_sort_data_types();
qpGeomVertexDataType *last = _data_types.back();
_total_bytes = last->get_start() + last->get_total_bytes();
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::clear_data_types
// Access: Published
// Description: Removes all data types previously added, sets the
// stride to zero, and prepares to start over.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
clear_data_types() {
_data_types.clear();
_data_types_by_name.clear();
_data_types_unsorted = false;
_stride = 0;
_total_bytes = 0;
_pad_to = 1;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::get_data_type
// Access: Published
// Description: Returns the specification with the indicated name, or
// NULL if the name is not used.
////////////////////////////////////////////////////////////////////
const qpGeomVertexDataType *qpGeomVertexArrayFormat::
get_data_type(const InternalName *name) const {
DataTypesByName::const_iterator ni;
ni = _data_types_by_name.find(name);
if (ni != _data_types_by_name.end()) {
return (*ni).second;
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::get_data_type
// Access: Published
// Description: Returns the first specification that overlaps with
// any of the indicated bytes in the range, or NULL if
// none do.
////////////////////////////////////////////////////////////////////
const qpGeomVertexDataType *qpGeomVertexArrayFormat::
get_data_type(int start_byte, int num_bytes) const {
consider_sort_data_types();
DataTypes::const_iterator dti;
for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) {
const qpGeomVertexDataType *data_type = (*dti);
if (data_type->overlaps_with(start_byte, num_bytes)) {
return data_type;
}
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::is_data_subset_of
// Access: Published
// Description: Returns true if all of the fields in this array
// format are also present and equivalent in the other
// array format, and in the same byte positions, and the
// stride is the same. That is, true if this format can
// share the same data pointer as the other format (with
// possibly some unused gaps).
////////////////////////////////////////////////////////////////////
bool qpGeomVertexArrayFormat::
is_data_subset_of(const qpGeomVertexArrayFormat &other) const {
if (_data_types.size() > other._data_types.size() ||
get_stride() != other.get_stride()) {
return false;
}
consider_sort_data_types();
other.consider_sort_data_types();
size_t i = 0;
size_t j = 0;
while (i < _data_types.size() && j < other._data_types.size()) {
if (*_data_types[i] == *other._data_types[j]) {
++i;
}
++j;
}
// If we reached the end of our list, all fields matched.
return (i == _data_types.size());
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
output(ostream &out) const {
DataTypes::const_iterator dti;
out << "[";
for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) {
const qpGeomVertexDataType *data_type = (*dti);
out << " " << *data_type;
}
out << " ]";
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< "Array format (stride = " << get_stride() << "):\n";
consider_sort_data_types();
DataTypes::const_iterator dti;
for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) {
const qpGeomVertexDataType *data_type = (*dti);
indent(out, indent_level + 2)
<< *data_type << " start at " << data_type->get_start() << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::write_with_data
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
write_with_data(ostream &out, int indent_level,
const qpGeomVertexData *data, int array_index) const {
consider_sort_data_types();
int num_vertices = data->get_num_vertices();
for (int i = 0; i < num_vertices; i++) {
indent(out, indent_level)
<< "vertex index " << i << ":\n";
DataTypes::const_iterator dti;
for (dti = _data_types.begin(); dti != _data_types.end(); ++dti) {
const qpGeomVertexDataType *data_type = (*dti);
int num_values = min(data_type->get_num_values(), 4);
float data_values[4];
data->get_data(array_index, data_type, i, data_values, num_values);
indent(out, indent_level + 2)
<< *data_type->get_name();
for (int v = 0; v < num_values; v++) {
out << " " << data_values[v];
}
out << "\n";
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::compare_to
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
int qpGeomVertexArrayFormat::
compare_to(const qpGeomVertexArrayFormat &other) const {
if (_stride != other._stride) {
return _stride - other._stride;
}
if (_total_bytes != other._total_bytes) {
return _total_bytes - other._total_bytes;
}
if (_pad_to != other._pad_to) {
return _pad_to - other._pad_to;
}
if (_data_types.size() != other._data_types.size()) {
return (int)_data_types.size() - (int)other._data_types.size();
}
consider_sort_data_types();
other.consider_sort_data_types();
for (size_t i = 0; i < _data_types.size(); i++) {
int compare = _data_types[i]->compare_to(*other._data_types[i]);
if (compare != 0) {
return compare;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::sort_data_types
// Access: Private
// Description: Resorts the _data_types vector so that the data types
// are listed in the same order they appear in the
// record.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
sort_data_types() {
sort(_data_types.begin(), _data_types.end(), IndirectLess<qpGeomVertexDataType>());
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::do_register
// Access: Private
// Description: Called internally when the format is registered.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
do_register() {
nassertv(!_is_registered);
_is_registered = true;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// qpGeomVertexArrayFormat.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritableReferenceCount::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int qpGeomVertexArrayFormat::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type qpGeomVertexArrayFormat is
// encountered in the Bam file. It should create the
// qpGeomVertexArrayFormat and extract its information from
// the file.
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomVertexArrayFormat::
make_from_bam(const FactoryParams &params) {
qpGeomVertexArrayFormat *object = new qpGeomVertexArrayFormat;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexArrayFormat::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeomVertexArrayFormat.
////////////////////////////////////////////////////////////////////
void qpGeomVertexArrayFormat::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritableReferenceCount::fillin(scan, manager);
}

View File

@ -0,0 +1,162 @@
// Filename: qpgeomVertexArrayFormat.h
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMVERTEXARRAYFORMAT_H
#define qpGEOMVERTEXARRAYFORMAT_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "qpgeomVertexDataType.h"
#include "pvector.h"
#include "pmap.h"
class qpGeomVertexFormat;
class qpGeomVertexData;
class InternalName;
class FactoryParams;
////////////////////////////////////////////////////////////////////
// Class : qpGeomVertexArrayFormat
// Description : This describes the structure of a single array within
// a Geom data. See GeomVertexFormat for the parent
// class which collects together all of the individual
// GeomVertexArrayFormat objects.
//
// A particular array may include any number of standard
// or user-defined data types. All data types consist
// of a sequence of one or more floating-point numbers;
// the semantic meaning of the data type is implicit
// from its name. The standard array types are named
// "vertex", "normal", "texcoord", "color", "tangent",
// and "binormal"; other data may be stored simply by
// choosing a different name.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomVertexArrayFormat : public TypedWritableReferenceCount {
PUBLISHED:
qpGeomVertexArrayFormat();
qpGeomVertexArrayFormat(const qpGeomVertexArrayFormat &copy);
qpGeomVertexArrayFormat(const InternalName *name0, int num_components0,
qpGeomVertexDataType::NumericType numeric_type0);
qpGeomVertexArrayFormat(const InternalName *name0, int num_components0,
qpGeomVertexDataType::NumericType numeric_type0,
const InternalName *name1, int num_components1,
qpGeomVertexDataType::NumericType numeric_type1);
qpGeomVertexArrayFormat(const InternalName *name0, int num_components0,
qpGeomVertexDataType::NumericType numeric_type0,
const InternalName *name1, int num_components1,
qpGeomVertexDataType::NumericType numeric_type1,
const InternalName *name2, int num_components2,
qpGeomVertexDataType::NumericType numeric_type2);
qpGeomVertexArrayFormat(const InternalName *name0, int num_components0,
qpGeomVertexDataType::NumericType numeric_type0,
const InternalName *name1, int num_components1,
qpGeomVertexDataType::NumericType numeric_type1,
const InternalName *name2, int num_components2,
qpGeomVertexDataType::NumericType numeric_type2,
const InternalName *name3, int num_components3,
qpGeomVertexDataType::NumericType numeric_type3);
void operator = (const qpGeomVertexArrayFormat &copy);
~qpGeomVertexArrayFormat();
INLINE bool is_registered() const;
INLINE int get_stride() const;
INLINE void set_stride(int stride);
INLINE int get_total_bytes() const;
INLINE int get_pad_to() const;
void add_data_type(const InternalName *name, int num_components,
qpGeomVertexDataType::NumericType numeric_type,
int start = -1);
void add_data_type(const qpGeomVertexDataType &data_type);
void remove_data_type(const InternalName *name);
void clear_data_types();
INLINE int get_num_data_types() const;
INLINE const qpGeomVertexDataType *get_data_type(int i) const;
const qpGeomVertexDataType *get_data_type(const InternalName *name) const;
const qpGeomVertexDataType *get_data_type(int start_byte, int num_bytes) const;
bool is_data_subset_of(const qpGeomVertexArrayFormat &other) const;
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
void write_with_data(ostream &out, int indent_level,
const qpGeomVertexData *data, int array_index) const;
public:
int compare_to(const qpGeomVertexArrayFormat &other) const;
private:
INLINE void consider_sort_data_types() const;
void sort_data_types();
void do_register();
bool _is_registered;
const qpGeomVertexFormat *_root_format;
const qpGeomVertexFormat *_parent_format;
int _stride;
int _total_bytes;
int _pad_to;
typedef pvector<qpGeomVertexDataType *> DataTypes;
DataTypes _data_types;
bool _data_types_unsorted;
typedef pmap<const InternalName *, qpGeomVertexDataType *> DataTypesByName;
DataTypesByName _data_types_by_name;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "qpGeomVertexArrayFormat",
TypedWritableReferenceCount::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 qpGeomVertexFormat;
};
INLINE ostream &operator << (ostream &out, const qpGeomVertexArrayFormat &obj);
#include "qpgeomVertexArrayFormat.I"
#endif

View File

@ -0,0 +1,82 @@
// Filename: qpgeomVertexData.I
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_format
// Access: Published
// Description: Returns a pointer to the GeomVertexFormat structure
// that defines this data.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexData::
get_format() const {
return _format;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_num_arrays
// Access: Published
// Description: Returns the number of individual arrays stored within
// the data. This must match
// get_format()->get_num_arrays().
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexData::
get_num_arrays() const {
CDReader cdata(_cycler);
return cdata->_arrays.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_array_data
// Access: Published
// Description: Returns a const pointer to the vertex data for the
// indicated array, for application code to directly
// examine (but not modify) the underlying vertex data.
////////////////////////////////////////////////////////////////////
INLINE CPTA_uchar qpGeomVertexData::
get_array_data(int array) const {
CDReader cdata(_cycler);
nassertr(array >= 0 && array < (int)cdata->_arrays.size(), CPTA_uchar());
return cdata->_arrays[array];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexData::CData::
CData() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexData::CData::
CData(const qpGeomVertexData::CData &copy) :
_arrays(copy._arrays)
{
}
INLINE ostream &
operator << (ostream &out, const qpGeomVertexData &obj) {
obj.output(out);
return out;
}

View File

@ -0,0 +1,650 @@
// Filename: qpgeomVertexData.cxx
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexData.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "pset.h"
TypeHandle qpGeomVertexData::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::Default Constructor
// Access: Private
// Description: Constructs an invalid object. This is only used when
// reading from the bam file.
////////////////////////////////////////////////////////////////////
qpGeomVertexData::
qpGeomVertexData() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexData::
qpGeomVertexData(const qpGeomVertexFormat *format) :
_format(format)
{
nassertv(_format->is_registered());
// Create some empty arrays as required by the format.
CDWriter cdata(_cycler);
cdata->_arrays.insert(cdata->_arrays.end(), _format->get_num_arrays(),
PTA_uchar());
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexData::
qpGeomVertexData(const qpGeomVertexData &copy) :
TypedWritableReferenceCount(copy),
_format(copy._format),
_cycler(copy._cycler)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
operator = (const qpGeomVertexData &copy) {
TypedWritableReferenceCount::operator = (copy);
_format = copy._format;
_cycler = copy._cycler;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexData::
~qpGeomVertexData() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_num_vertices
// Access: Published
// Description: Returns the number of vertices stored within all the
// arrays. All arrays store data for the same n
// vertices.
////////////////////////////////////////////////////////////////////
int qpGeomVertexData::
get_num_vertices() const {
CDReader cdata(_cycler);
nassertr(_format->get_num_arrays() == (int)cdata->_arrays.size(), 0);
if (_format->get_num_arrays() == 0) {
// No arrays means no vertices. Weird but legal.
return 0;
}
// Look up the answer on the first array (since any array will do).
int stride = _format->get_array(0)->get_stride();
return cdata->_arrays[0].size() / stride;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::set_num_vertices
// Access: Published
// Description: Sets the length of the array to n vertices in all of
// the various arrays (presumably by adding vertices).
// The new vertex data is uninitialized.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
set_num_vertices(int n) {
CDWriter cdata(_cycler);
nassertv(_format->get_num_arrays() == (int)cdata->_arrays.size());
for (size_t i = 0; i < cdata->_arrays.size(); i++) {
int stride = _format->get_array(i)->get_stride();
int delta = n - (cdata->_arrays[i].size() / stride);
if (delta != 0) {
if (cdata->_arrays[i].get_ref_count() > 1) {
// Copy-on-write: the array is already reffed somewhere else,
// so we're just going to make a copy.
PTA_uchar new_array;
new_array.reserve(n * stride);
new_array.insert(new_array.end(), n * stride, uchar());
memcpy(new_array, cdata->_arrays[i],
min((size_t)(n * stride), cdata->_arrays[i].size()));
cdata->_arrays[i] = new_array;
} else {
// We've got the only reference to the array, so we can change
// it directly.
if (delta > 0) {
cdata->_arrays[i].insert(cdata->_arrays[i].end(), delta * stride, uchar());
} else {
cdata->_arrays[i].erase(cdata->_arrays[i].begin() + n * stride,
cdata->_arrays[i].end());
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::clear_vertices
// Access: Published
// Description: Removes all of the vertices from the arrays;
// functionally equivalent to set_num_vertices(0) (but
// faster).
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
clear_vertices() {
CDWriter cdata(_cycler);
nassertv(_format->get_num_arrays() == (int)cdata->_arrays.size());
Arrays::iterator ai;
for (ai = cdata->_arrays.begin();
ai != cdata->_arrays.end();
++ai) {
(*ai).clear();
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::modify_array_data
// Access: Published
// Description: Returns a modifiable pointer to the indicated vertex
// array, so that application code may directly
// manipulate the vertices. You should avoid changing
// the length of this array, since all of the arrays
// should be kept in sync--use add_vertices() instead.
////////////////////////////////////////////////////////////////////
PTA_uchar qpGeomVertexData::
modify_array_data(int array) {
// Perform copy-on-write: if the reference count on the vertex data
// is greater than 1, assume some other GeomVertexData has the same
// pointer, so make a copy of it first.
CDWriter cdata(_cycler);
nassertr(array >= 0 && array < (int)cdata->_arrays.size(), PTA_uchar());
if (cdata->_arrays[array].get_ref_count() > 1) {
PTA_uchar orig_data = cdata->_arrays[array];
cdata->_arrays[array] = PTA_uchar();
cdata->_arrays[array].v() = orig_data.v();
}
return cdata->_arrays[array];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::set_array_data
// Access: Published
// Description: Replaces the indicated vertex data array with
// a completely new array. You should be careful that
// the new array has the same length as the old one,
// unless you know what you are doing.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
set_array_data(int array, PTA_uchar array_data) {
CDWriter cdata(_cycler);
nassertv(array >= 0 && array < (int)cdata->_arrays.size());
cdata->_arrays[array] = array_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::set_data
// Access: Published
// Description: Sets the nth vertex to a particular value. Query the
// format to get the array index and data_type
// parameters for the particular data type you want to
// set.
//
// This flavor of set_data() accepts a generic float
// array and a specific number of dimensions. The new
// data will be copied from the num_values elements
// of data.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
set_data(int array, const qpGeomVertexDataType *data_type,
int vertex, const float *data, int num_values) {
int stride = _format->get_array(array)->get_stride();
int element = vertex * stride + data_type->get_start();
{
CDReader cdata(_cycler);
int array_size = (int)cdata->_arrays[array].size();
if (element + data_type->get_total_bytes() > array_size) {
// Whoops, we need more vertices!
set_num_vertices(vertex + 1);
}
}
PTA_uchar array_data = modify_array_data(array);
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
{
nassertv(num_values <= data_type->get_num_values());
for (int i = 0; i < num_values; i++) {
int value = (int)(data[i] * 255.0f);
*(unsigned char *)&array_data[element] = value;
element += 1;
}
}
break;
case qpGeomVertexDataType::NT_packed_argb:
{
nassertv(num_values == 4);
*(PN_uint32 *)&array_data[element] = pack_argb(data);
}
break;
case qpGeomVertexDataType::NT_float:
nassertv(num_values == data_type->get_num_values());
memcpy(&array_data[element], data, data_type->get_total_bytes());
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_data
// Access: Published
// Description: Returns the data associated with the nth vertex for a
// particular value. Query the format to get the array
// index and data_type parameters for the particular
// data type you want to get.
//
// This flavor of get_data() copies its data into a
// generic float array.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, float *data, int num_values) const {
CPTA_uchar array_data = get_array_data(array);
int stride = _format->get_array(array)->get_stride();
int element = vertex * stride + data_type->get_start();
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
{
nassertv(num_values <= data_type->get_num_values());
for (int i = 0; i < num_values; i++) {
int value = *(unsigned char *)&array_data[element];
element += 1;
data[i] = (float)value / 255.0f;
}
}
break;
case qpGeomVertexDataType::NT_packed_argb:
{
nassertv(num_values == 4);
unpack_argb(data, *(PN_uint32 *)&array_data[element]);
}
break;
case qpGeomVertexDataType::NT_float:
nassertv(num_values <= data_type->get_num_values());
memcpy(data, &array_data[element], num_values * sizeof(PN_float32));
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::convert_to
// Access: Published
// Description: Matches up the data types of this format with the
// data types of the other format by name, and copies
// the data vertex-by-vertex to a new set of data arrays
// in the new format.
////////////////////////////////////////////////////////////////////
PT(qpGeomVertexData) qpGeomVertexData::
convert_to(const qpGeomVertexFormat *new_format) const {
int num_vertices = get_num_vertices();
PT(qpGeomVertexData) new_data = new qpGeomVertexData(new_format);
pset<int> done_arrays;
int num_arrays = _format->get_num_arrays();
int array;
// First, check to see if any arrays can be simply appropriated for
// the new format, without changing the data.
for (array = 0; array < num_arrays; ++array) {
const qpGeomVertexArrayFormat *array_format =
_format->get_array(array);
bool array_done = false;
int new_num_arrays = new_format->get_num_arrays();
for (int new_array = 0;
new_array < new_num_arrays && !array_done;
++new_array) {
const qpGeomVertexArrayFormat *new_array_format =
new_format->get_array(new_array);
if (new_array_format->is_data_subset_of(*array_format)) {
// Great! Just use the same data for this one.
new_data->set_array_data(new_array, (PTA_uchar &)get_array_data(array));
array_done = true;
done_arrays.insert(new_array);
}
}
}
// Now make sure the arrays we didn't share are all filled in.
new_data->set_num_vertices(num_vertices);
// Now go back through and copy any data that's left over.
for (array = 0; array < num_arrays; ++array) {
CPTA_uchar array_data = get_array_data(array);
const qpGeomVertexArrayFormat *array_format =
_format->get_array(array);
int num_data_types = array_format->get_num_data_types();
for (int di = 0; di < num_data_types; ++di) {
const qpGeomVertexDataType *data_type = array_format->get_data_type(di);
int new_array = new_format->get_array_with(data_type->get_name());
if (new_array >= 0 && done_arrays.count(new_array) == 0) {
// The data type exists in the new format; we have to copy it.
PTA_uchar new_array_data = new_data->modify_array_data(new_array);
const qpGeomVertexArrayFormat *new_array_format =
new_format->get_array(new_array);
const qpGeomVertexDataType *new_data_type =
new_array_format->get_data_type(data_type->get_name());
new_data_type->copy_records
(new_array_data + new_data_type->get_start(),
new_array_format->get_stride(),
array_data + data_type->get_start(), array_format->get_stride(),
data_type, num_vertices);
}
}
}
return new_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
output(ostream &out) const {
out << get_num_vertices() << ": " << *get_format();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
write(ostream &out, int indent_level) const {
_format->write_with_data(out, indent_level, this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_array_info
// Access: Public
// Description: A convenience function to collect together the
// important parts of the array data for rendering.
// Given the name of a data type, fills in the start of
// the array, the number of floats for each vertex, the
// starting bytes number, and the number of bytes to
// increment for each consecutive vertex.
//
// The return value is true if the named array data
// exists in this record, or false if it does not (in
// which case none of the output parameters are valid).
////////////////////////////////////////////////////////////////////
bool qpGeomVertexData::
get_array_info(const InternalName *name, CPTA_uchar &array_data,
int &num_components,
qpGeomVertexDataType::NumericType &numeric_type,
int &start, int &stride) const {
int array_index;
const qpGeomVertexDataType *data_type;
if (_format->get_array_info(name, array_index, data_type)) {
CDReader cdata(_cycler);
array_data = cdata->_arrays[array_index];
num_components = data_type->get_num_components();
numeric_type = data_type->get_numeric_type();
start = data_type->get_start();
stride = _format->get_array(array_index)->get_stride();
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::to_vec2
// Access: Public, Static
// Description: Converts a data element of arbitrary number of
// dimensions (1 - 4) into a vec2 in a sensible way.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
to_vec2(LVecBase2f &vec, const float *data, int num_values) {
switch (num_values) {
case 1:
vec.set(data[0], 0.0f);
break;
case 2:
case 3:
vec.set(data[0], data[1]);
break;
default: // 4 or more.
vec.set(data[0] / data[3], data[1] / data[3]);
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::to_vec3
// Access: Public, Static
// Description: Converts a data element of arbitrary number of
// dimensions (1 - 4) into a vec3 in a sensible way.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
to_vec3(LVecBase3f &vec, const float *data, int num_values) {
switch (num_values) {
case 1:
vec.set(data[0], 0.0f, 0.0f);
break;
case 2:
vec.set(data[0], data[1], 0.0f);
break;
case 3:
vec.set(data[0], data[1], data[2]);
break;
default: // 4 or more.
vec.set(data[0] / data[3], data[1] / data[3], data[2] / data[3]);
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::to_vec4
// Access: Public, Static
// Description: Converts a data element of arbitrary number of
// dimensions (1 - 4) into a vec4 in a sensible way.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
to_vec4(LVecBase4f &vec, const float *data, int num_values) {
switch (num_values) {
case 1:
vec.set(data[0], 0.0f, 0.0f, 1.0f);
break;
case 2:
vec.set(data[0], data[1], 0.0f, 1.0f);
break;
case 3:
vec.set(data[0], data[1], data[2], 1.0f);
break;
default: // 4 or more.
vec.set(data[0], data[1], data[2], data[3]);
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::pack_argb
// Access: Public, Static
// Description: Packs four floats, stored R, G, B, A, into a
// packed_argb value.
////////////////////////////////////////////////////////////////////
unsigned int qpGeomVertexData::
pack_argb(const float data[4]) {
unsigned int r = ((unsigned int)(data[0] * 255.0f)) & 0xff;
unsigned int g = ((unsigned int)(data[1] * 255.0f)) & 0xff;
unsigned int b = ((unsigned int)(data[2] * 255.0f)) & 0xff;
unsigned int a = ((unsigned int)(data[3] * 255.0f)) & 0xff;
return ((a << 24) | (r << 16) | (g << 8) | b);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::unpack_argb
// Access: Public, Static
// Description: Unpacks a packed_argb value into four floats, stored
// R, G, B, A.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
unpack_argb(float data[4], unsigned int packed_argb) {
data[0] = (float)((packed_argb >> 16) & 0xff) / 255.0f;
data[1] = (float)((packed_argb >> 8) & 0xff) / 255.0f;
data[2] = (float)(packed_argb & 0xff) / 255.0f;
data[3] = (float)((packed_argb >> 24) & 0xff) / 255.0f;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// qpGeomVertexData.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type qpGeomVertexData is encountered
// in the Bam file. It should create the qpGeomVertexData
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomVertexData::
make_from_bam(const FactoryParams &params) {
qpGeomVertexData *object = new qpGeomVertexData;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeomVertexData.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *qpGeomVertexData::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::CData::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int qpGeomVertexData::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeomVertexData.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,155 @@
// Filename: qpgeomVertexData.h
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMVERTEXDATA_H
#define qpGEOMVERTEXDATA_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexDataType.h"
#include "internalName.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
#include "pointerTo.h"
#include "pmap.h"
#include "pvector.h"
#include "pta_uchar.h"
class FactoryParams;
class qpGeomVertexDataType;
////////////////////////////////////////////////////////////////////
// Class : qpGeomVertexData
// Description : This defines the actual numeric vertex data stored in
// a Geom, in the structure defined by a particular
// GeomVertexFormat object.
//
// The data consists of one or more arrays of floats.
// Typically, there will be only one array per Geom, and
// the various data types defined in the
// GeomVertexFormat will be interleaved throughout that
// array. However, it is possible to have multiple
// different arrays, with different combinations of data
// types through each one.
//
// However the data is distributed, the effect is of a
// table of vertices, with a value for each of the
// GeomVertexFormat's data types, stored for each
// vertex.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomVertexData : public TypedWritableReferenceCount {
private:
qpGeomVertexData();
PUBLISHED:
qpGeomVertexData(const qpGeomVertexFormat *format);
qpGeomVertexData(const qpGeomVertexData &copy);
void operator = (const qpGeomVertexData &copy);
virtual ~qpGeomVertexData();
INLINE const qpGeomVertexFormat *get_format() const;
int get_num_vertices() const;
void set_num_vertices(int n);
void clear_vertices();
INLINE int get_num_arrays() const;
INLINE CPTA_uchar get_array_data(int array) const;
PTA_uchar modify_array_data(int array);
void set_array_data(int array, PTA_uchar array_data);
void set_data(int array, const qpGeomVertexDataType *data_type,
int vertex, const float *data, int num_values);
void get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, float *data, int num_values) const;
PT(qpGeomVertexData) convert_to(const qpGeomVertexFormat *new_format) const;
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
public:
bool get_array_info(const InternalName *name, CPTA_uchar &array_data,
int &num_components,
qpGeomVertexDataType::NumericType &numeric_type,
int &start, int &stride) const;
static void to_vec2(LVecBase2f &vec, const float *data, int num_values);
static void to_vec3(LVecBase3f &vec, const float *data, int num_values);
static void to_vec4(LVecBase4f &vec, const float *data, int num_values);
static unsigned int pack_argb(const float data[4]);
static void unpack_argb(float data[4], unsigned int packed_argb);
private:
typedef pvector<PTA_uchar> Arrays;
CPT(qpGeomVertexFormat) _format;
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
virtual void fillin(DatagramIterator &scan, BamReader *manager);
Arrays _arrays;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "qpGeomVertexData",
TypedWritableReferenceCount::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;
};
INLINE ostream &operator << (ostream &out, const qpGeomVertexData &obj);
#include "qpgeomVertexData.I"
#endif

View File

@ -0,0 +1,221 @@
// Filename: qpgeomVertexDataType.I
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexDataType::
qpGeomVertexDataType(const qpGeomVertexDataType &copy) :
_name(copy._name),
_num_components(copy._num_components),
_num_values(copy._num_values),
_numeric_type(copy._numeric_type),
_start(copy._start),
_component_bytes(copy._component_bytes),
_total_bytes(copy._total_bytes)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexDataType::
operator = (const qpGeomVertexDataType &copy) {
_name = copy._name;
_num_components = copy._num_components;
_num_values = copy._num_values;
_numeric_type = copy._numeric_type;
_start = copy._start;
_component_bytes = copy._component_bytes;
_total_bytes = copy._total_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_name
// Access: Published
// Description: Returns the name of this particular data field,
// e.g. "vertex" or "normal". The name may be a
// user-defined string, or it may be one of the standard
// system-defined field types. Only the system-defined
// field types are used for the actual rendering.
////////////////////////////////////////////////////////////////////
INLINE const InternalName *qpGeomVertexDataType::
get_name() const {
return _name;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_num_components
// Access: Published
// Description: Returns the number of components of each data type:
// the number of instances of the NumericType in each
// element. This is usually, but not always, the same
// thing as get_num_values().
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexDataType::
get_num_components() const {
return _num_components;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_num_values
// Access: Published
// Description: Returns the number of numeric values of each data
// type: the number of distinct numeric values that go
// into each element. This is usually, but not always,
// the same thing as get_num_components(); the
// difference is in the case of a composite numeric type
// like NT_packed_argb, which has four numeric values
// per component.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexDataType::
get_num_values() const {
return _num_values;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_numeric_type
// Access: Published
// Description: Returns the token representing the numeric type of
// the data storage.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexDataType::NumericType qpGeomVertexDataType::
get_numeric_type() const {
return _numeric_type;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_start
// Access: Published
// Description: Returns the byte within the array record at which
// this data type starts. This can be set to non-zero
// to implement interleaved arrays.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexDataType::
get_start() const {
return _start;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_component_bytes
// Access: Published
// Description: Returns the number of bytes used by each component
// (that is, by one element of the numeric type).
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexDataType::
get_component_bytes() const {
return _component_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_total_bytes
// Access: Published
// Description: Returns the number of bytes used by the data type:
// component_bytes * num_components.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexDataType::
get_total_bytes() const {
return _total_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::overlaps_with
// Access: Published
// Description: Returns true if this data type overlaps with any of
// the bytes in the indicated range, false if it does
// not.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexDataType::
overlaps_with(int start_byte, int num_bytes) const {
return (_start < start_byte + num_bytes &&
_start + _total_bytes > start_byte);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::compare_to
// Access: Public
// Description: This is used to unquify data types, and hence
// formats, for the GeomVertexFormat registry.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexDataType::
compare_to(const qpGeomVertexDataType &other) const {
if (_name != other._name) {
return _name < other._name ? -1 : 1;
}
if (_num_components != other._num_components) {
return _num_components - other._num_components;
}
if (_numeric_type != other._numeric_type) {
return (int)_numeric_type - (int)other._numeric_type;
}
if (_start != other._start) {
return _start - other._start;
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::operator ==
// Access: Public
// Description: Returns true if the two data types are exactly
// equivalent, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexDataType::
operator == (const qpGeomVertexDataType &other) const {
return compare_to(other) == 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::operator !=
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexDataType::
operator != (const qpGeomVertexDataType &other) const {
return compare_to(other) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::operator <
// Access: Public
// Description: This is used to put data types in order within a
// particular GeomVertexArrayFormat. Note that it is
// *not* in the same space as operator == and operator
// !=.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexDataType::
operator < (const qpGeomVertexDataType &other) const {
if (_start != other._start) {
return _start < other._start;
}
if (_total_bytes < other._total_bytes) {
return _total_bytes < other._total_bytes;
}
return 0;
}
INLINE ostream &
operator << (ostream &out, const qpGeomVertexDataType &obj) {
obj.output(out);
return out;
}

View File

@ -0,0 +1,309 @@
// Filename: qpgeomVertexDataType.cxx
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexDataType.h"
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexDataType::
qpGeomVertexDataType(const InternalName *name, int num_components,
NumericType numeric_type, int start) :
_name(name),
_num_components(num_components),
_num_values(num_components),
_numeric_type(numeric_type),
_start(start)
{
nassertv(num_components > 0 && start >= 0);
switch (numeric_type) {
case NT_uint8:
_component_bytes = 1;
break;
case NT_packed_argb:
_component_bytes = 4; // sizeof(PN_uint32)
_num_values *= 4;
break;
case NT_float:
_component_bytes = 4; // sizeof(PN_float32)
break;
}
_total_bytes = _component_bytes * _num_components;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::error named constructor
// Access: Published
// Description: Returns a data type specifically to represent an
// error condition.
////////////////////////////////////////////////////////////////////
const qpGeomVertexDataType &qpGeomVertexDataType::
error() {
static qpGeomVertexDataType error_result
(InternalName::get_error(), 1, NT_uint8, 0);
return error_result;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
output(ostream &out) const {
out << *get_name() << "(" << get_num_components() << ")";
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_records
// Access: Published
// Description: Copies and converts from one data type to another.
// Copies the num_records records from the "from"
// buffer, encoded with from_type, to the "to" buffer,
// encoded with this current type, converting each one
// as necessary.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_records(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
// Temp for debugging.
static ConfigVariableBool do_copy_generic("copy-generic", false);
if (do_copy_generic) {
copy_generic(to, to_stride, from, from_stride, from_type, num_records);
return;
}
if (get_numeric_type() == from_type->get_numeric_type() &&
get_num_values() == from_type->get_num_values()) {
// An easy case.
copy_no_convert(to, to_stride, from, from_stride, from_type, num_records);
} else if (get_numeric_type() == NT_uint8 && from_type->get_numeric_type() == NT_packed_argb &&
get_num_values() == from_type->get_num_values()) {
copy_argb_to_uint8(to, to_stride, from, from_stride, from_type, num_records);
} else if (get_numeric_type() == NT_packed_argb && from_type->get_numeric_type() == NT_uint8 &&
get_num_values() == from_type->get_num_values()) {
copy_uint8_to_argb(to, to_stride, from, from_stride, from_type, num_records);
} else {
copy_generic(to, to_stride, from, from_stride, from_type, num_records);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_no_convert
// Access: Private
// Description: Quickly copies data without the need to convert it.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_no_convert(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
if (to_stride == _total_bytes && from_stride == _total_bytes) {
// Fantastic! It's just a linear array of this one data type.
// Copy the whole thing all at once.
memcpy(to, from, num_records * _total_bytes);
} else {
// Ok, it's interleaved in with other data. Copy them one record
// at a time.
while (num_records > 0) {
memcpy(to, from, _total_bytes);
to += to_stride;
from += from_stride;
num_records--;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_argb_to_uint8
// Access: Private
// Description: Converts packed_argb to uint8-based r, g, b, a.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_argb_to_uint8(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
while (num_records > 0) {
PN_uint32 packed_argb = *(const PN_uint32 *)from;
to[0] = ((packed_argb >> 16) & 0xff);
to[1] = ((packed_argb >> 8) & 0xff);
to[2] = (packed_argb & 0xff);
to[3] = ((packed_argb >> 24) & 0xff);
to += to_stride;
from += from_stride;
num_records--;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_uint8_to_argb
// Access: Private
// Description: Converts uint8-based r, g, b, a to packed_argb.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_uint8_to_argb(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
while (num_records > 0) {
PN_uint32 packed_argb = ((from[3] << 24) | (from[0] << 16) | (from[1] << 8) | from[2]);
*(PN_uint32 *)to = packed_argb;
to += to_stride;
from += from_stride;
num_records--;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::copy_generic
// Access: Private
// Description: A more general anything-to-anything copy (somewhat
// more expensive than the above).
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
copy_generic(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const {
int num_values_to_copy = min(get_num_values(), from_type->get_num_values());
int num_values_to_fill = get_num_values() - num_values_to_copy;
while (num_records > 0) {
int vi = 0;
while (vi < num_values_to_copy) {
float value = from_type->get_value(from, vi);
set_value(to, vi, value);
++vi;
}
while (vi < num_values_to_fill) {
set_value(to, vi, 0.0f);
++vi;
}
to += to_stride;
from += from_stride;
num_records--;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::get_value
// Access: Private
// Description: Returns the nth value of the data type, expressed as
// a float.
////////////////////////////////////////////////////////////////////
float qpGeomVertexDataType::
get_value(const unsigned char *data, int n) const {
switch (get_numeric_type()) {
case NT_uint8:
return (float)data[n] / 255.0f;
case qpGeomVertexDataType::NT_packed_argb:
{
int element = n / 4;
const PN_uint32 *int_array = (const PN_uint32 *)data;
PN_uint32 packed_argb = int_array[element];
switch (n % 4) {
case 0:
return (float)((packed_argb >> 16) & 0xff) / 255.0f;
case 1:
return (float)((packed_argb >> 8) & 0xff) / 255.0f;
case 2:
return (float)(packed_argb & 0xff) / 255.0f;
case 3:
return (float)((packed_argb >> 24) & 0xff) / 255.0f;
}
}
break;
case qpGeomVertexDataType::NT_float:
{
const PN_float32 *float_array = (const PN_float32 *)data;
return float_array[n];
}
}
return 0.0f;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::set_value
// Access: Private
// Description: Modifies the nth value of the data type.
////////////////////////////////////////////////////////////////////
void qpGeomVertexDataType::
set_value(unsigned char *data, int n, float value) const {
switch (get_numeric_type()) {
case NT_uint8:
data[n] = (int)(value * 255.0f);
break;
case qpGeomVertexDataType::NT_packed_argb:
{
int element = n / 4;
union {
PN_uint32 _packed_argb;
struct {
unsigned char _a;
unsigned char _r;
unsigned char _g;
unsigned char _b;
} _argb;
} color;
PN_uint32 *int_array = (PN_uint32 *)data;
color._packed_argb = int_array[element];
switch (n % 4) {
case 0:
color._argb._r = (int)(value * 255.0f);
break;
case 1:
color._argb._g = (int)(value * 255.0f);
break;
case 2:
color._argb._b = (int)(value * 255.0f);
break;
case 3:
color._argb._a = (int)(value * 255.0f);
break;
}
int_array[element] = color._packed_argb;
}
break;
case qpGeomVertexDataType::NT_float:
PN_float32 *float_array = (PN_float32 *)data;
float_array[n] = value;
break;
}
}

View File

@ -0,0 +1,109 @@
// Filename: qpgeomVertexDataType.h
// Created by: drose (06Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMVERTEXDATATYPE_H
#define qpGEOMVERTEXDATATYPE_H
#include "pandabase.h"
#include "internalName.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomVertexDataType
// Description : This defines how a single data type is interleaved
// within a vertex array stored within a Geom. The
// GeomVertexArrayFormat class maintains a list of these
// to completely define a particular array structure.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomVertexDataType {
PUBLISHED:
enum NumericType {
NT_uint8,
NT_packed_argb, // DirectX style
NT_float,
};
INLINE qpGeomVertexDataType(const InternalName *name, int num_components,
NumericType numeric_type, int start);
INLINE qpGeomVertexDataType(const qpGeomVertexDataType &copy);
INLINE void operator = (const qpGeomVertexDataType &copy);
static const qpGeomVertexDataType &error();
INLINE const InternalName *get_name() const;
INLINE int get_num_components() const;
INLINE int get_num_values() const;
INLINE NumericType get_numeric_type() const;
INLINE int get_start() const;
INLINE int get_component_bytes() const;
INLINE int get_total_bytes() const;
INLINE bool overlaps_with(int start_byte, int num_bytes) const;
void output(ostream &out) const;
public:
INLINE int compare_to(const qpGeomVertexDataType &other) const;
INLINE bool operator == (const qpGeomVertexDataType &other) const;
INLINE bool operator != (const qpGeomVertexDataType &other) const;
INLINE bool operator < (const qpGeomVertexDataType &other) const;
void copy_records(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
private:
void copy_no_convert(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
void copy_argb_to_uint8(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
void copy_uint8_to_argb(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
void copy_generic(unsigned char *to, int to_stride,
const unsigned char *from, int from_stride,
const qpGeomVertexDataType *from_type,
int num_records) const;
float get_value(const unsigned char *data, int n) const;
void set_value(unsigned char *data, int n, float value) const;
private:
CPT(InternalName) _name;
int _num_components;
int _num_values;
NumericType _numeric_type;
int _start;
int _component_bytes;
int _total_bytes;
};
INLINE ostream &operator << (ostream &out, const qpGeomVertexDataType &obj);
#include "qpgeomVertexDataType.I"
#endif

View File

@ -0,0 +1,260 @@
// Filename: qpgeomVertexFormat.I
// Created by: drose (07Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
INLINE ostream &
operator << (ostream &out, const qpGeomVertexFormat &obj) {
obj.output(out);
return out;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::is_registered
// Access: Published
// Description: Returns true if this format has been registered,
// false if it has not. It may not be used for a Geom
// until it has been registered, but once registered, it
// may no longer be modified.
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexFormat::
is_registered() const {
return _is_registered;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::register_format
// Access: Published, Static
// Description: Adds the indicated format to the registry, if there
// is not an equivalent format already there; in either
// case, returns the pointer to the equivalent format
// now in the registry.
//
// This must be called before a format may be used in a
// Geom. After this call, you should discard the
// original pointer you passed in (which may or may not
// now be invalid) and let its reference count decrement
// normally; you should use only the returned value from
// this point on.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomVertexFormat) qpGeomVertexFormat::
register_format(qpGeomVertexFormat *format) {
return get_registry()->register_format(format);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::register_format
// Access: Published, Static
// Description: This flavor of register_format() implicitly creates a
// one-array vertex format from the array definition.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomVertexFormat) qpGeomVertexFormat::
register_format(qpGeomVertexArrayFormat *format) {
return get_registry()->register_format(format);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_num_arrays
// Access: Published
// Description: Returns the number of individual arrays required by
// the format. If the array data is completely
// interleaved, this will be 1; if it is completely
// parallel, this will be the same as the number of data
// types.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexFormat::
get_num_arrays() const {
return _arrays.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_array
// Access: Published
// Description: Returns the description of the nth array used by the
// format.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexArrayFormat *qpGeomVertexFormat::
get_array(int array) const {
nassertr(array >= 0 && array < (int)_arrays.size(), NULL);
return _arrays[array];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3
// Access: Published, Static
// Description: Returns a standard vertex format with just a
// 3-component vertex position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3() {
return get_registry()->_v3;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3n3
// Access: Published, Static
// Description: Returns a standard vertex format with a 3-component
// normal and a 3-component vertex position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3n3() {
return get_registry()->_v3n3;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3t2
// Access: Published, Static
// Description: Returns a standard vertex format with a 2-component
// texture coordinate pair and a 3-component vertex
// position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3t2() {
return get_registry()->_v3t2;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3n3t2
// Access: Published, Static
// Description: Returns a standard vertex format with a 2-component
// texture coordinate pair, a 3-component normal, and a
// 3-component vertex position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3n3t2() {
return get_registry()->_v3n3t2;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3cp
// Access: Published, Static
// Description: Returns a standard vertex format with a packed
// color and a 3-component vertex position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3cp() {
return get_registry()->_v3cp;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3n3cp
// Access: Published, Static
// Description: Returns a standard vertex format with a packed
// color, a 3-component normal, and a 3-component vertex
// position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3n3cp() {
return get_registry()->_v3n3cp;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3cpt2
// Access: Published, Static
// Description: Returns a standard vertex format with a 2-component
// texture coordinate pair, a packed color, and a
// 3-component vertex position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3cpt2() {
return get_registry()->_v3cpt2;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3n3cpt2
// Access: Published, Static
// Description: Returns a standard vertex format with a 2-component
// texture coordinate pair, a packed color, a
// 3-component normal, and a 3-component vertex
// position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3n3cpt2() {
return get_registry()->_v3n3cpt2;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3c4
// Access: Published, Static
// Description: Returns a standard vertex format with a 4-component
// color and a 3-component vertex position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3c4() {
return get_registry()->_v3c4;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3n3c4
// Access: Published, Static
// Description: Returns a standard vertex format with a 4-component
// color, a 3-component normal, and a 3-component vertex
// position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3n3c4() {
return get_registry()->_v3n3c4;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3c4t2
// Access: Published, Static
// Description: Returns a standard vertex format with a 2-component
// texture coordinate pair, a 4-component color, and a
// 3-component vertex position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3c4t2() {
return get_registry()->_v3c4t2;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3n3c4t2
// Access: Published, Static
// Description: Returns a standard vertex format with a 2-component
// texture coordinate pair, a 4-component color, a
// 3-component normal, and a 3-component vertex
// position.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexFormat *qpGeomVertexFormat::
get_v3n3c4t2() {
return get_registry()->_v3n3c4t2;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_registry
// Access: Private
// Description: Returns the global registry object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexFormat::Registry *qpGeomVertexFormat::
get_registry() {
if (_registry == (Registry *)NULL) {
make_registry();
}
return _registry;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Registry::register_format
// Access: Public
// Description: This flavor of register_format() implicitly creates a
// one-array vertex format from the array definition.
////////////////////////////////////////////////////////////////////
INLINE CPT(qpGeomVertexFormat) qpGeomVertexFormat::Registry::
register_format(qpGeomVertexArrayFormat *format) {
return register_format(new qpGeomVertexFormat(format));
}

View File

@ -0,0 +1,632 @@
// Filename: qpgeomVertexFormat.cxx
// Created by: drose (07Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexFormat.h"
#include "qpgeomVertexData.h"
#include "qpgeomMunger.h"
#include "indent.h"
#include "bamReader.h"
#include "bamWriter.h"
qpGeomVertexFormat::Registry *qpGeomVertexFormat::_registry = NULL;
TypeHandle qpGeomVertexFormat::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexFormat::
qpGeomVertexFormat() :
_is_registered(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexFormat::
qpGeomVertexFormat(qpGeomVertexArrayFormat *array_format) :
_is_registered(false)
{
add_array(array_format);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexFormat::
qpGeomVertexFormat(const qpGeomVertexFormat &copy) :
_is_registered(false),
_arrays(copy._arrays)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
operator = (const qpGeomVertexFormat &copy) {
nassertv(!_is_registered);
_arrays = copy._arrays;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexFormat::
~qpGeomVertexFormat() {
if (is_registered()) {
get_registry()->unregister_format(this);
}
nassertv(_mungers.empty());
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::modify_array
// Access: Published
// Description: Returns a modifiable pointer to the indicated array.
// This means duplicating it if it is shared or
// registered.
////////////////////////////////////////////////////////////////////
qpGeomVertexArrayFormat *qpGeomVertexFormat::
modify_array(int array) {
nassertr(!_is_registered, NULL);
nassertr(array >= 0 && array < (int)_arrays.size(), NULL);
if (_arrays[array]->is_registered() ||
_arrays[array]->get_ref_count() > 1) {
_arrays[array] = new qpGeomVertexArrayFormat(*_arrays[array]);
}
return _arrays[array];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::set_array
// Access: Published
// Description: Replaces the definition of the indicated array.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
set_array(int array, qpGeomVertexArrayFormat *format) {
nassertv(!_is_registered);
nassertv(array >= 0 && array < (int)_arrays.size());
_arrays[array] = format;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::remove_array
// Access: Published
// Description: Removes the nth array from the format.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
remove_array(int array) {
nassertv(!_is_registered);
nassertv(array >= 0 && array < (int)_arrays.size());
_arrays.erase(_arrays.begin() + array);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::add_array
// Access: Published
// Description: Adds the indicated array definition to the list of
// arrays included within this vertex format definition.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
add_array(qpGeomVertexArrayFormat *array_format) {
nassertv(!_is_registered);
_arrays.push_back(array_format);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::clear_arrays
// Access: Published
// Description: Removes all of the array definitions from the format
// and starts over.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
clear_arrays() {
nassertv(!_is_registered);
_arrays.clear();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_num_data_types
// Access: Published
// Description: Returns the total number of different data types in
// the specification, across all arrays.
////////////////////////////////////////////////////////////////////
int qpGeomVertexFormat::
get_num_data_types() const {
int num_data_types = 0;
Arrays::const_iterator ai;
for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
num_data_types += (*ai)->get_num_data_types();
}
return num_data_types;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_data_type
// Access: Published
// Description: Returns the ith data type of the specification,
// across all arrays.
////////////////////////////////////////////////////////////////////
const qpGeomVertexDataType *qpGeomVertexFormat::
get_data_type(int i) const {
Arrays::const_iterator ai;
for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
if (i < (*ai)->get_num_data_types()) {
return (*ai)->get_data_type(i);
}
i -= (*ai)->get_num_data_types();
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_array_with
// Access: Published
// Description: Returns the index number of the array with the
// ith data type.
//
// The return value can be passed to get_array_format()
// to get the format of the array. It may also be
// passed to GeomVertexData::get_array_data() or
// get_data() or set_data() to manipulate the actual
// array data.
////////////////////////////////////////////////////////////////////
int qpGeomVertexFormat::
get_array_with(int i) const {
int array_index = 0;
for (array_index = 0; array_index < (int)_arrays.size(); array_index++) {
if (i < _arrays[array_index]->get_num_data_types()) {
return array_index;
}
i -= _arrays[array_index]->get_num_data_types();
}
return -1;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_array_with
// Access: Published
// Description: Returns the index number of the array with the
// indicated data type, or -1 if no arrays contained
// that name.
//
// The return value can be passed to get_array_format()
// to get the format of the array. It may also be
// passed to GeomVertexData::get_array_data() or
// get_data() or set_data() to manipulate the actual
// array data.
//
// This may only be called after the format has been
// registered.
////////////////////////////////////////////////////////////////////
int qpGeomVertexFormat::
get_array_with(const InternalName *name) const {
nassertr(_is_registered, -1);
DataTypesByName::const_iterator ai;
ai = _data_types_by_name.find(name);
if (ai != _data_types_by_name.end()) {
return (*ai).second._array_index;
}
return -1;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_data_type
// Access: Published
// Description: Returns the specification with the indicated name, or
// NULL if the name is not used. Use get_array_with()
// to determine which array this data type is associated
// with.
//
// This may only be called after the format has been
// registered.
////////////////////////////////////////////////////////////////////
const qpGeomVertexDataType *qpGeomVertexFormat::
get_data_type(const InternalName *name) const {
nassertr(_is_registered, NULL);
DataTypesByName::const_iterator ai;
ai = _data_types_by_name.find(name);
if (ai != _data_types_by_name.end()) {
int array_index = (*ai).second._array_index;
int data_type_index = (*ai).second._data_type_index;
nassertr(array_index >= 0 && array_index < (int)_arrays.size(), NULL);
return _arrays[array_index]->get_data_type(data_type_index);
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
output(ostream &out) const {
if (_arrays.empty()) {
out << "(empty)";
} else {
Arrays::const_iterator ai;
ai = _arrays.begin();
out << *(*ai);
++ai;
while (ai != _arrays.end()) {
out << ", " << *(*ai);
++ai;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
write(ostream &out, int indent_level) const {
for (size_t i = 0; i < _arrays.size(); i++) {
indent(out, indent_level)
<< "Array " << i << ":\n";
_arrays[i]->write(out, indent_level + 2);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::write_with_data
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
write_with_data(ostream &out, int indent_level,
const qpGeomVertexData *data) const {
indent(out, indent_level)
<< data->get_num_vertices() << " vertices.\n";
for (size_t i = 0; i < _arrays.size(); i++) {
CPTA_uchar array_data = data->get_array_data(i);
indent(out, indent_level)
<< "Array " << i << " (" << (void *)array_data.p() << "):\n";
_arrays[i]->write_with_data(out, indent_level + 2, data, i);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_array_info
// Access: Public
// Description: Quickly looks up the indicated data type within all
// of the nested arrays and sets array_index and
// data_type appropriately. Returns true if the data
// type exists in this format, false if it does not.
//
// This may only be called after the format has been
// registered.
////////////////////////////////////////////////////////////////////
bool qpGeomVertexFormat::
get_array_info(const InternalName *name, int &array_index,
const qpGeomVertexDataType *&data_type) const {
nassertr(_is_registered, false);
DataTypesByName::const_iterator ai;
ai = _data_types_by_name.find(name);
if (ai != _data_types_by_name.end()) {
array_index = (*ai).second._array_index;
data_type = _arrays[array_index]->get_data_type((*ai).second._data_type_index);
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::compare_to
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
int qpGeomVertexFormat::
compare_to(const qpGeomVertexFormat &other) const {
if (_arrays.size() != other._arrays.size()) {
return (int)_arrays.size() - (int)other._arrays.size();
}
for (size_t i = 0; i < _arrays.size(); i++) {
int compare = _arrays[i]->compare_to(*other._arrays[i]);
if (compare != 0) {
return compare;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::make_registry
// Access: Private
// Description: Returns the global registry object.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
make_registry() {
if (_registry == (Registry *)NULL) {
_registry = new Registry;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::do_register
// Access: Private
// Description: Called internally when the format is registered.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
do_register() {
nassertv(!_is_registered);
nassertv(_data_types_by_name.empty());
nassertv(_mungers.empty());
int array = 0;
for (array = 0; array < (int)_arrays.size(); ++array) {
const qpGeomVertexArrayFormat *array_format = _arrays[array];
if (!array_format->is_registered()) {
((qpGeomVertexArrayFormat *)array_format)->do_register();
}
// Now add the names to the index.
int num_data_types = array_format->get_num_data_types();
for (int i = 0; i < num_data_types; i++) {
const qpGeomVertexDataType *data_type = array_format->get_data_type(i);
pair<DataTypesByName::iterator, bool> result;
result = _data_types_by_name.insert(DataTypesByName::value_type(data_type->get_name(), DataTypeRecord()));
if (!result.second) {
gobj_cat.warning()
<< "Data type " << data_type->get_name() << " repeated in format.\n";
} else {
DataTypeRecord &record = (*result.first).second;
record._array_index = array;
record._data_type_index = i;
}
}
}
_is_registered = true;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::do_unregister
// Access: Private
// Description: Called internally when the format is unregistered.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
do_unregister() {
nassertv(_is_registered);
_is_registered = false;
_data_types_by_name.clear();
Mungers::iterator mi;
for (mi = _mungers.begin(); mi != _mungers.end(); ++mi) {
(*mi)->remove_format(this);
}
_mungers.clear();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// qpGeomVertexFormat.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritableReferenceCount::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int qpGeomVertexFormat::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type qpGeomVertexFormat is
// encountered in the Bam file. It should create the
// qpGeomVertexFormat and extract its information from
// the file.
////////////////////////////////////////////////////////////////////
TypedWritable *qpGeomVertexFormat::
make_from_bam(const FactoryParams &params) {
qpGeomVertexFormat *object = new qpGeomVertexFormat;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new qpGeomVertexFormat.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritableReferenceCount::fillin(scan, manager);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Registry::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
qpGeomVertexFormat::Registry::
Registry() {
_v3 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float));
_v3n3 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float));
_v3t2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
_v3n3t2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
// Define the DirectX-style packed color formats
_v3cp = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb));
_v3n3cp = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb));
_v3cpt2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
_v3n3cpt2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
// Define the OpenGL-style per-byte color formats. This is not the
// same as a packed format, above, because the resulting byte order
// is endian-independent.
_v3c4 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8));
_v3n3c4 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8));
_v3c4t2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
_v3n3c4t2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Registry::register_format
// Access: Public
// Description: Adds the indicated format to the registry, if there
// is not an equivalent format already there; in either
// case, returns the pointer to the equivalent format
// now in the registry.
//
// This must be called before a format may be used in a
// Geom. After this call, you should discard the
// original pointer you passed in (which may or may not
// now be invalid) and let its reference count decrement
// normally; you should use only the returned value from
// this point on.
////////////////////////////////////////////////////////////////////
CPT(qpGeomVertexFormat) qpGeomVertexFormat::Registry::
register_format(qpGeomVertexFormat *format) {
if (format->is_registered()) {
return format;
}
// Save the incoming pointer in a local PointerTo, so that if it has
// a zero reference count and is not added into the map below, it
// will be automatically deleted when this function returns.
PT(qpGeomVertexFormat) pt_format = format;
Formats::iterator fi = _formats.insert(format).first;
qpGeomVertexFormat *new_format = (*fi);
if (!new_format->is_registered()) {
new_format->do_register();
}
return new_format;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::Registry::unregister_format
// Access: Public
// Description: Removes the indicated format from the registry.
// Normally this should not be done until the format is
// destructing.
////////////////////////////////////////////////////////////////////
void qpGeomVertexFormat::Registry::
unregister_format(qpGeomVertexFormat *format) {
nassertv(format->is_registered());
Formats::iterator fi = _formats.find(format);
nassertv(fi != _formats.end());
_formats.erase(fi);
format->do_unregister();
}

View File

@ -0,0 +1,211 @@
// Filename: qpgeomVertexFormat.h
// Created by: drose (07Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMVERTEXFORMAT_H
#define qpGEOMVERTEXFORMAT_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "qpgeomVertexArrayFormat.h"
#include "internalName.h"
#include "luse.h"
#include "pointerTo.h"
#include "pmap.h"
#include "pset.h"
#include "pvector.h"
#include "pta_float.h"
#include "indirectCompareTo.h"
class FactoryParams;
class qpGeomVertexData;
class qpGeomMunger;
////////////////////////////////////////////////////////////////////
// Class : qpGeomVertexFormat
// Description : This class defines the layout of the vertex data
// arrays stored within a Geom. The data within a Geom
// is typically stored within a single interleaved
// array, but it may also be distributed among multiple
// different arrays. Each array is described by a
// qpGeomVertexArrayFormat object, referenced within
// this object.
//
// There are a number of standard pre-defined
// GeomVertexFormat objects, or you may define your own
// as needed. You may also record any combination of
// standard and/or user-defined data types in your
// custom GeomVertexFormat constructions.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomVertexFormat : public TypedWritableReferenceCount {
PUBLISHED:
qpGeomVertexFormat();
qpGeomVertexFormat(qpGeomVertexArrayFormat *array_format);
qpGeomVertexFormat(const qpGeomVertexFormat &copy);
void operator = (const qpGeomVertexFormat &copy);
virtual ~qpGeomVertexFormat();
INLINE bool is_registered() const;
INLINE static CPT(qpGeomVertexFormat) register_format(qpGeomVertexFormat *format);
INLINE static CPT(qpGeomVertexFormat) register_format(qpGeomVertexArrayFormat *format);
INLINE int get_num_arrays() const;
INLINE const qpGeomVertexArrayFormat *get_array(int array) const;
qpGeomVertexArrayFormat *modify_array(int array);
void set_array(int array, qpGeomVertexArrayFormat *format);
void remove_array(int array);
void add_array(qpGeomVertexArrayFormat *array_format);
void clear_arrays();
int get_num_data_types() const;
int get_array_with(int i) const;
const qpGeomVertexDataType *get_data_type(int i) const;
int get_array_with(const InternalName *name) const;
const qpGeomVertexDataType *get_data_type(const InternalName *name) const;
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
void write_with_data(ostream &out, int indent_level,
const qpGeomVertexData *data) const;
// Some standard vertex formats. No particular requirement to use
// one of these, but the DirectX renderers can use these formats
// directly, whereas any other format will have to be converted
// first.
INLINE static const qpGeomVertexFormat *get_v3();
INLINE static const qpGeomVertexFormat *get_v3n3();
INLINE static const qpGeomVertexFormat *get_v3t2();
INLINE static const qpGeomVertexFormat *get_v3n3t2();
// These formats, with the DirectX-style packed color, are not
// supported directly by OpenGL. If you use them, the
// GLGraphicsStateGuardian will automatically convert to OpenGL
// form (with a small runtime overhead).
INLINE static const qpGeomVertexFormat *get_v3cp();
INLINE static const qpGeomVertexFormat *get_v3cpt2();
INLINE static const qpGeomVertexFormat *get_v3n3cp();
INLINE static const qpGeomVertexFormat *get_v3n3cpt2();
// These formats, with an OpenGL-style four-byte color, are not
// supported directly by DirectX. If you use them, the
// DXGraphicsStateGuardian will automatically convert to DirectX
// form (with a larger runtime overhead, since DirectX8, and old
// DirectX9 drivers, require everything to be interleaved together).
INLINE static const qpGeomVertexFormat *get_v3c4();
INLINE static const qpGeomVertexFormat *get_v3c4t2();
INLINE static const qpGeomVertexFormat *get_v3n3c4();
INLINE static const qpGeomVertexFormat *get_v3n3c4t2();
public:
bool get_array_info(const InternalName *name,
int &array_index,
const qpGeomVertexDataType *&data_type) const;
int compare_to(const qpGeomVertexFormat &other) const;
private:
class Registry;
INLINE static Registry *get_registry();
static void make_registry();
void do_register();
void do_unregister();
bool _is_registered;
typedef pvector< PT(qpGeomVertexArrayFormat) > Arrays;
Arrays _arrays;
class DataTypeRecord {
public:
int _array_index;
int _data_type_index;
};
typedef pmap<const InternalName *, DataTypeRecord> DataTypesByName;
DataTypesByName _data_types_by_name;
typedef pset<qpGeomMunger *> Mungers;
Mungers _mungers;
typedef pset<qpGeomVertexFormat *, IndirectCompareTo<qpGeomVertexFormat> > Formats;
class Registry {
public:
Registry();
CPT(qpGeomVertexFormat) register_format(qpGeomVertexFormat *format);
INLINE CPT(qpGeomVertexFormat) register_format(qpGeomVertexArrayFormat *format);
void unregister_format(qpGeomVertexFormat *format);
Formats _formats;
CPT(qpGeomVertexFormat) _v3;
CPT(qpGeomVertexFormat) _v3n3;
CPT(qpGeomVertexFormat) _v3t2;
CPT(qpGeomVertexFormat) _v3n3t2;
CPT(qpGeomVertexFormat) _v3cp;
CPT(qpGeomVertexFormat) _v3n3cp;
CPT(qpGeomVertexFormat) _v3cpt2;
CPT(qpGeomVertexFormat) _v3n3cpt2;
CPT(qpGeomVertexFormat) _v3c4;
CPT(qpGeomVertexFormat) _v3n3c4;
CPT(qpGeomVertexFormat) _v3c4t2;
CPT(qpGeomVertexFormat) _v3n3c4t2;
};
static Registry *_registry;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "qpGeomVertexFormat",
TypedWritableReferenceCount::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 qpGeomVertexFormat::Registry;
friend class qpGeomMunger;
};
INLINE ostream &operator << (ostream &out, const qpGeomVertexFormat &obj);
#include "qpgeomVertexFormat.I"
#endif

View File

@ -0,0 +1,380 @@
// Filename: qpgeomVertexIterator.I
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(qpGeomVertexData *data) :
_data(data),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object. This flavor creates the
// iterator specifically to process the named data type.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(qpGeomVertexData *data, const string &name) :
_data(data),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
set_data_type(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::Constructor
// Access: Published
// Description: Constructs a new iterator to process the vertices of
// the indicated data object. This flavor creates the
// iterator specifically to process the named data type.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexIterator::
qpGeomVertexIterator(qpGeomVertexData *data, const InternalName *name) :
_data(data),
_array(0),
_data_type(NULL),
_start_vertex(0),
_read_vertex(0),
_write_vertex(0)
{
set_data_type(name);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data
// Access: Published
// Description: Returns the current data object that the iterator is
// processing.
////////////////////////////////////////////////////////////////////
INLINE qpGeomVertexData *qpGeomVertexIterator::
get_data() const {
return _data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data_type
// Access: Published
// Description: Sets up the iterator to use the nth data type of the
// GeomVertexFormat, numbering from 0.
//
// This also resets the read and write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data_type(int data_type) {
nassertv(_data->get_format()->get_array_with(data_type) >= 0);
set_data_type(_data->get_format()->get_array_with(data_type),
_data->get_format()->get_data_type(data_type));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data_type
// Access: Published
// Description: Sets up the iterator to use the data type with the
// indicated name.
//
// This also resets the read and write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data_type(const string &name) {
set_data_type(InternalName::make(name));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data_type
// Access: Published
// Description: Sets up the iterator to use the data type with the
// indicated name.
//
// This also resets the read and write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data_type(const InternalName *name) {
nassertv(_data->get_format()->get_array_with(name) >= 0);
set_data_type(_data->get_format()->get_array_with(name),
_data->get_format()->get_data_type(name));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data_type
// Access: Published
// Description: Sets up the iterator to use the indicated data_type
// description on the given array.
//
// This also resets the read and write vertex numbers to
// the start vertex (the same value passed to a previous
// call to set_vertex(), or 0 if set_vertex() was never
// called.)
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data_type(int array, const qpGeomVertexDataType *data_type) {
nassertv(array >= 0 && array < _data->get_num_arrays());
nassertv(data_type != (qpGeomVertexDataType *)NULL);
_array = array;
_data_type = data_type;
_read_vertex = _start_vertex;
_write_vertex = _start_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_array
// Access: Published
// Description: Returns the array index containing the data type that
// the iterator is working on.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_array() const {
return _array;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data_type
// Access: Published
// Description: Returns the description of the data type that the
// iterator is working on.
////////////////////////////////////////////////////////////////////
INLINE const qpGeomVertexDataType *qpGeomVertexIterator::
get_data_type() const {
return _data_type;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_vertex
// Access: Published
// Description: Sets the start, read, and write index to the
// indicated value. The iterator will begin traversing
// from the given vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_vertex(int vertex) {
_start_vertex = vertex;
_read_vertex = vertex;
_write_vertex = vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_start_vertex
// Access: Published
// Description: Returns the vertex index at which the iterator
// started. It will return to this vertex if you reset
// the current data_type.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_start_vertex() const {
return _start_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_read_vertex
// Access: Published
// Description: Returns the current read vertex index of the
// iterator. This is the index whose value will be
// returned by the next call to get_vertex().
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_read_vertex() const {
return _read_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_write_vertex
// Access: Published
// Description: Returns the current write vertex index of the
// iterator. This is the index whose value will be
// modified by the next call to set_vertex().
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_write_vertex() const {
return _write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data1
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data1(float data) {
_data->set_data(_array, _data_type, _write_vertex, &data, 1);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data2
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data2(float x, float y) {
set_data2(LVecBase2f(x, y));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data2
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data2(const LVecBase2f &data) {
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 2);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data3
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data3(float x, float y, float z) {
set_data3(LVecBase3f(x, y, z));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data3
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data3(const LVecBase3f &data) {
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 3);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data4
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data4(float x, float y, float z, float w) {
set_data4(LVecBase4f(x, y, z, w));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data4
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data4(const LVecBase4f &data) {
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 4);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data1
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 1-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE float qpGeomVertexIterator::
get_data1() {
float data;
_data->get_data(_array, _data_type, _read_vertex, &data, 1);
++_read_vertex;
return data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data2
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 2-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase2f qpGeomVertexIterator::
get_data2() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
++_read_vertex;
LVecBase2f result;
qpGeomVertexData::to_vec2(result, data, num_values);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data3
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 3-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase3f qpGeomVertexIterator::
get_data3() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
++_read_vertex;
LVecBase3f result;
qpGeomVertexData::to_vec3(result, data, num_values);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data4
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 4-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase4f qpGeomVertexIterator::
get_data4() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
++_read_vertex;
LVecBase4f result;
qpGeomVertexData::to_vec4(result, data, num_values);
return result;
}

View File

@ -0,0 +1,19 @@
// Filename: qpgeomVertexIterator.cxx
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "qpgeomVertexIterator.h"

View File

@ -0,0 +1,86 @@
// Filename: qpgeomVertexIterator.h
// Created by: drose (10Mar05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef qpGEOMVERTEXITERATOR_H
#define qpGEOMVERTEXITERATOR_H
#include "pandabase.h"
#include "qpgeomVertexData.h"
#include "qpgeomVertexDataType.h"
#include "internalName.h"
#include "luse.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : qpGeomVertexIterator
// Description : This is used to read or write the vertices of a
// GeomVertexData structure, one vertex and data type at
// a time.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA qpGeomVertexIterator {
PUBLISHED:
INLINE qpGeomVertexIterator(qpGeomVertexData *data);
INLINE qpGeomVertexIterator(qpGeomVertexData *data,
const string &name);
INLINE qpGeomVertexIterator(qpGeomVertexData *data,
const InternalName *name);
INLINE qpGeomVertexData *get_data() const;
INLINE void set_data_type(int data_type);
INLINE void set_data_type(const string &name);
INLINE void set_data_type(const InternalName *name);
INLINE void set_data_type(int array, const qpGeomVertexDataType *data_type);
INLINE int get_array() const;
INLINE const qpGeomVertexDataType *get_data_type() const;
INLINE void set_vertex(int vertex);
INLINE int get_start_vertex() const;
INLINE int get_read_vertex() const;
INLINE int get_write_vertex() const;
INLINE void set_data1(float data);
INLINE void set_data2(float x, float y);
INLINE void set_data2(const LVecBase2f &data);
INLINE void set_data3(float x, float y, float z);
INLINE void set_data3(const LVecBase3f &data);
INLINE void set_data4(float x, float y, float z, float w);
INLINE void set_data4(const LVecBase4f &data);
INLINE float get_data1();
INLINE LVecBase2f get_data2();
INLINE LVecBase3f get_data3();
INLINE LVecBase4f get_data4();
private:
PT(qpGeomVertexData) _data;
int _array;
const qpGeomVertexDataType *_data_type;
int _start_vertex;
int _read_vertex;
int _write_vertex;
};
#include "qpgeomVertexIterator.I"
#endif

View File

@ -1,49 +0,0 @@
// Filename: texCoordName.I
// Created by: masad (15Jul04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::get_name
// Access: Published
// Description: Return the name string of this texcoordname
////////////////////////////////////////////////////////////////////
INLINE const string &TexCoordName::
get_name() const {
return _name;
}
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::get_default
// Access: Published, Static
// Description: Returns the default TexCoordName that will be used
// for all geometry that does not give a particular name
// for its UV's
////////////////////////////////////////////////////////////////////
INLINE const TexCoordName *TexCoordName::
get_default() {
if (_default_name == (TexCoordName *)NULL) {
_default_name = TexCoordName::make("default");
}
return _default_name;
}
INLINE ostream &
operator << (ostream &out, const TexCoordName &tcn) {
tcn.output(out);
return out;
}

View File

@ -1,161 +0,0 @@
// Filename: texCoordName.cxx
// Created by: masad (15Jul04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "texCoordName.h"
#include "datagram.h"
#include "datagramIterator.h"
#include "bamReader.h"
#include "preparedGraphicsObjects.h"
TexCoordName::TexCoordsByName TexCoordName::_texcoords_by_name;
CPT(TexCoordName) TexCoordName::_default_name;
TypeHandle TexCoordName::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::Constructor
// Access: Private
// Description: Use make() to make a new TexCoordName instance.
////////////////////////////////////////////////////////////////////
TexCoordName::
TexCoordName(const string &name) {
_name = name;
}
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
TexCoordName::
~TexCoordName() {
TexCoordsByName::iterator ni = _texcoords_by_name.find(_name);
nassertv(ni != _texcoords_by_name.end());
_texcoords_by_name.erase(ni);
}
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::make
// Access: Published
// Description: The public interface for constructing a TexCoordName
// pointer. This will return a new TexCoordName
// associated with the indicated name, if this is the
// first time the particular name has been requested; if
// the name is already in use, it will return the
// existing pointer.
////////////////////////////////////////////////////////////////////
const TexCoordName *TexCoordName::
make(const string &name) {
TexCoordsByName::iterator ni = _texcoords_by_name.find(name);
if (ni != _texcoords_by_name.end()) {
return (*ni).second;
}
TexCoordName *texcoord = new TexCoordName(name);
_texcoords_by_name[name] = texcoord;
return texcoord;
}
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::output
// Access: Published
// Description: output the TexCoordName and its member data
////////////////////////////////////////////////////////////////////
void TexCoordName::
output(ostream &out) const {
out << get_name();
}
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::register_with_read_factory
// Access: Public, Static
// Description: Factory method to generate a TexCoordName object
////////////////////////////////////////////////////////////////////
void TexCoordName::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::finalize
// Access: Public, Virtual
// Description: Method to ensure that any necessary clean up tasks
// that have to be performed by this object are performed
////////////////////////////////////////////////////////////////////
void TexCoordName::
finalize() {
// Unref the pointer that we explicitly reffed in make_from_bam().
unref();
// We should never get back to zero after unreffing our own count,
// because we expect to have been stored in a pointer somewhere. If
// we do get to zero, it's a memory leak; the way to avoid this is
// to call unref_delete() above instead of unref(), but this is
// dangerous to do from within a virtual function.
nassertv(get_ref_count() != 0);
}
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type TexCoordName is encountered
// in the Bam file. It should create the TexCoordName
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *TexCoordName::
make_from_bam(const FactoryParams &params) {
// The process of making a TexCoordName is slightly
// different than making other Writable objects.
// That is because all creation of TexCoordNames should
// be done through the make() constructor.
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
// The name is the only thing written to the data stream.
string name = scan.get_string();
// Make a new TexCoordName with that name (or get the previous one
// if there is one already).
PT(TexCoordName) me = (TexCoordName *)make(name);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
me->ref();
manager->register_finalize(me);
return me.p();
}
////////////////////////////////////////////////////////////////////
// Function: TexCoordName::write_datagram
// Access: Public
// Description: Function to write the important information in
// the particular object to a Datagram
////////////////////////////////////////////////////////////////////
void TexCoordName::
write_datagram(BamWriter *manager, Datagram &me) {
me.add_string(_name);
}

View File

@ -1,92 +0,0 @@
// Filename: texCoordName.h
// Created by: drose (15Jul04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef TEXCOORDNAME_H
#define TEXCOORDNAME_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
class FactoryParams;
////////////////////////////////////////////////////////////////////
// Class : TexCoordName
// Description : Associates a name with a set of texture coordinates,
// for the purpose of storing within a Geom. This is
// used in conjunction with TextureStage to support
// multitexturing.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TexCoordName : public TypedWritableReferenceCount {
private:
TexCoordName(const string &name);
PUBLISHED:
virtual ~TexCoordName();
static const TexCoordName *make(const string &name);
INLINE const string &get_name() const;
void output(ostream &out) const;
INLINE static const TexCoordName *get_default();
private:
string _name;
typedef phash_map<string, TexCoordName *, string_hash> TexCoordsByName;
static TexCoordsByName _texcoords_by_name;
static CPT(TexCoordName) _default_name;
public:
// Datagram stuff
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &me);
virtual void finalize();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "TexCoordName",
TypedWritableReferenceCount::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;
};
INLINE ostream &operator << (ostream &out, const TexCoordName &tcn);
#include "texCoordName.I"
#endif

View File

@ -136,7 +136,7 @@ operator < (const TextureStage &other) const {
// sets, each of which must have a unique name.
////////////////////////////////////////////////////////////////////
INLINE void TextureStage::
set_texcoord_name(const TexCoordName *name) {
set_texcoord_name(const InternalName *name) {
_texcoord_name = name;
}
@ -149,15 +149,15 @@ set_texcoord_name(const TexCoordName *name) {
////////////////////////////////////////////////////////////////////
INLINE void TextureStage::
set_texcoord_name(const string &name) {
_texcoord_name = TexCoordName::make(name);
_texcoord_name = InternalName::get_texcoord_name(name);
}
////////////////////////////////////////////////////////////////////
// Function: TextureStage::get_texcoord_name
// Access: Published
// Description: Returns the TexCoordName
// Description: Returns the InternalName
////////////////////////////////////////////////////////////////////
INLINE const TexCoordName *TextureStage::
INLINE const InternalName *TextureStage::
get_texcoord_name() const {
return _texcoord_name;
}

View File

@ -17,7 +17,7 @@
////////////////////////////////////////////////////////////////////
#include "textureStage.h"
#include "texCoordName.h"
#include "internalName.h"
PT(TextureStage) TextureStage::_default_stage;
UpdateSeq TextureStage::_sort_seq;
@ -34,7 +34,7 @@ TextureStage(const string &name) {
_name = name;
_sort = 0;
_priority = 0;
_texcoord_name = TexCoordName::get_default();
_texcoord_name = InternalName::get_texcoord();
_mode = M_modulate;
_color.set(0.0f, 0.0f, 0.0f, 1.0f);
_rgb_scale = 1;
@ -319,7 +319,7 @@ int TextureStage::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
_texcoord_name = DCAST(TexCoordName, p_list[pi++]);
_texcoord_name = DCAST(InternalName, p_list[pi++]);
return pi;
}

View File

@ -21,7 +21,7 @@
#include "pandabase.h"
#include "texCoordName.h"
#include "internalName.h"
#include "pointerTo.h"
#include "typedWritableReferenceCount.h"
#include "updateSeq.h"
@ -100,9 +100,9 @@ PUBLISHED:
INLINE bool operator < (const TextureStage &other) const;
INLINE void set_texcoord_name(const TexCoordName *name);
INLINE void set_texcoord_name(const InternalName *name);
INLINE void set_texcoord_name(const string &texcoord_name);
INLINE const TexCoordName *get_texcoord_name() const;
INLINE const InternalName *get_texcoord_name() const;
INLINE void set_mode(Mode mode);
INLINE Mode get_mode() const;
@ -170,7 +170,7 @@ private:
string _name;
int _sort;
int _priority;
CPT(TexCoordName) _texcoord_name;
CPT(InternalName) _texcoord_name;
Mode _mode;
Colorf _color;
int _rgb_scale;

View File

@ -116,7 +116,7 @@ scan(PandaNode *node, const RenderState *state, const TransformState *transform)
////////////////////////////////////////////////////////////////////
// Function: MultitexReducer::set_target
// Access: Published
// Description: Specifies the target TextureStage (and TexCoordName)
// Description: Specifies the target TextureStage (and InternalName)
// that will be left on each multitexture node after the
// flatten operation has completed.
////////////////////////////////////////////////////////////////////
@ -544,7 +544,7 @@ bool MultitexReducer::
determine_uv_range(TexCoordf &min_uv, TexCoordf &max_uv,
const MultitexReducer::StageInfo &model_stage,
const MultitexReducer::GeomList &geom_list) const {
const TexCoordName *model_name = model_stage._stage->get_texcoord_name();
const InternalName *model_name = model_stage._stage->get_texcoord_name();
bool got_any = false;
GeomList::const_iterator gi;
@ -799,7 +799,7 @@ make_texture_layer(const NodePath &render,
// coordinates to the target set.
////////////////////////////////////////////////////////////////////
void MultitexReducer::
transfer_geom(GeomNode *geom_node, const TexCoordName *texcoord_name,
transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name,
const MultitexReducer::GeomList &geom_list,
bool preserve_color) {
GeomList::const_iterator gi;
@ -820,8 +820,8 @@ transfer_geom(GeomNode *geom_node, const TexCoordName *texcoord_name,
}
geom->set_coords(coords, geom->get_texcoords_index(_target_stage->get_texcoord_name()));
if (texcoord_name != (const TexCoordName *)NULL) {
geom->set_texcoords(TexCoordName::get_default(),
if (texcoord_name != (const InternalName *)NULL) {
geom->set_texcoords(InternalName::get_texcoord(),
geom->get_texcoords_array(texcoord_name),
geom->get_texcoords_index(texcoord_name));
}

View File

@ -139,7 +139,7 @@ private:
const StageInfo &stage_info,
const GeomList &geom_list,
bool force_use_geom);
void transfer_geom(GeomNode *geom_node, const TexCoordName *texcoord_name,
void transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name,
const GeomList &geom_list, bool preserve_color);
void scan_color(const GeomList &geom_list, Colorf &geom_color,

View File

@ -43,6 +43,10 @@ class GeomTri;
class GeomTristrip;
class GeomTrifan;
class GeomSphere;
class qpGeomVertexData;
class qpGeomTriangles;
class qpGeomTristrips;
class qpGeomTrifans;
class PreparedGraphicsObjects;
class GraphicsOutput;
@ -165,6 +169,12 @@ public:
virtual void draw_trifan(GeomTrifan *geom, GeomContext *gc)=0;
virtual void draw_sphere(GeomSphere *geom, GeomContext *gc)=0;
virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data)=0;
virtual void draw_triangles(qpGeomTriangles *primitive)=0;
virtual void draw_tristrips(qpGeomTristrips *primitive)=0;
virtual void draw_trifans(qpGeomTrifans *primitive)=0;
virtual void end_draw_primitives()=0;
virtual void framebuffer_copy_to_texture
(Texture *tex, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0;
virtual bool framebuffer_copy_to_ram

View File

@ -182,10 +182,10 @@ get_default_collide_mask() {
////////////////////////////////////////////////////////////////////
// Function: GeomNode::count_name
// Access: Private
// Description: Increments the count for the indicated TexCoordName.
// Description: Increments the count for the indicated InternalName.
////////////////////////////////////////////////////////////////////
INLINE void GeomNode::
count_name(GeomNode::NameCount &name_count, const TexCoordName *name) {
count_name(GeomNode::NameCount &name_count, const InternalName *name) {
pair<NameCount::iterator, bool> result =
name_count.insert(NameCount::value_type(name, 1));
if (!result.second) {
@ -196,10 +196,10 @@ count_name(GeomNode::NameCount &name_count, const TexCoordName *name) {
////////////////////////////////////////////////////////////////////
// Function: GeomNode::get_name_count
// Access: Private
// Description: Returns the count for the indicated TexCoordName.
// Description: Returns the count for the indicated InternalName.
////////////////////////////////////////////////////////////////////
INLINE int GeomNode::
get_name_count(const GeomNode::NameCount &name_count, const TexCoordName *name) {
get_name_count(const GeomNode::NameCount &name_count, const InternalName *name) {
NameCount::const_iterator ni;
ni = name_count.find(name);
if (ni != name_count.end()) {

View File

@ -235,7 +235,7 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
int num_on_stages = ta->get_num_on_stages();
for (int si = 0; si < num_on_stages; si++) {
TextureStage *stage = ta->get_on_stage(si);
const TexCoordName *name = stage->get_texcoord_name();
const InternalName *name = stage->get_texcoord_name();
count_name(name_count, name);
}
}
@ -248,7 +248,7 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
int num_stages = tma->get_num_stages();
for (int i = 0; i < num_stages; i++) {
TextureStage *stage = tma->get_stage(i);
const TexCoordName *name = stage->get_texcoord_name();
const InternalName *name = stage->get_texcoord_name();
if (get_name_count(name_count, name) > 1) {
// We can't transform these texcoords, since the name is
// used by more than one active stage.

View File

@ -92,10 +92,10 @@ public:
private:
typedef pvector<GeomEntry> Geoms;
typedef pmap<const TexCoordName *, int> NameCount;
typedef pmap<const InternalName *, int> NameCount;
INLINE void count_name(NameCount &name_count, const TexCoordName *name);
INLINE int get_name_count(const NameCount &name_count, const TexCoordName *name);
INLINE void count_name(NameCount &name_count, const InternalName *name);
INLINE int get_name_count(const NameCount &name_count, const InternalName *name);
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {

View File

@ -150,8 +150,8 @@ transform_vertices(GeomNode *node, const LMatrix4f &mat) {
// Geom was changed, false otherwise.
////////////////////////////////////////////////////////////////////
bool GeomTransformer::
transform_texcoords(Geom *geom, const TexCoordName *from_name,
const TexCoordName *to_name, const LMatrix4f &mat) {
transform_texcoords(Geom *geom, const InternalName *from_name,
const InternalName *to_name, const LMatrix4f &mat) {
bool transformed = false;
nassertr(geom != (Geom *)NULL, false);
@ -201,8 +201,8 @@ transform_texcoords(Geom *geom, const TexCoordName *from_name,
// false otherwise.
////////////////////////////////////////////////////////////////////
bool GeomTransformer::
transform_texcoords(GeomNode *node, const TexCoordName *from_name,
const TexCoordName *to_name, const LMatrix4f &mat) {
transform_texcoords(GeomNode *node, const InternalName *from_name,
const InternalName *to_name, const LMatrix4f &mat) {
bool any_changed = false;
GeomNode::CDWriter cdata(node->_cycler);

View File

@ -26,7 +26,7 @@
class GeomNode;
class RenderState;
class TexCoordName;
class InternalName;
///////////////////////////////////////////////////////////////////
// Class : GeomTransformer
@ -52,11 +52,11 @@ public:
bool transform_vertices(Geom *geom, const LMatrix4f &mat);
bool transform_vertices(GeomNode *node, const LMatrix4f &mat);
bool transform_texcoords(Geom *geom, const TexCoordName *from_name,
const TexCoordName *to_name,
bool transform_texcoords(Geom *geom, const InternalName *from_name,
const InternalName *to_name,
const LMatrix4f &mat);
bool transform_texcoords(GeomNode *node, const TexCoordName *from_name,
const TexCoordName *to_name,
bool transform_texcoords(GeomNode *node, const InternalName *from_name,
const InternalName *to_name,
const LMatrix4f &mat);
bool set_color(Geom *geom, const Colorf &color);