Browse Source

dxGeomMunger8

David Rose 21 years ago
parent
commit
915a2671b1

+ 4 - 2
panda/src/display/graphicsStateGuardian.cxx

@@ -599,11 +599,13 @@ finish_decal() {
 //       Access: Public, Virtual
 //  Description: Called before a sequence of draw_primitive()
 //               functions are called, this should prepare the vertex
-//               data for rendering.
+//               data for rendering.  It returns true if the vertices
+//               are ok, false to abort this group of primitives.
 ////////////////////////////////////////////////////////////////////
-void GraphicsStateGuardian::
+bool GraphicsStateGuardian::
 begin_draw_primitives(const qpGeomVertexData *data) {
   _vertex_data = get_geom_munger()->munge_data(data);
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/display/graphicsStateGuardian.h

@@ -142,7 +142,7 @@ public:
   virtual CPT(RenderState) begin_decal_base_second();
   virtual void finish_decal();
 
-  virtual void begin_draw_primitives(const qpGeomVertexData *vertex_data);
+  virtual bool 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);

+ 4 - 1
panda/src/dxgsg8/Sources.pp

@@ -20,7 +20,9 @@
   // need to install these due to external projects that link directly with libpandadx (bartop)  
   #define INSTALL_HEADERS \
     dxgsg8base.h config_dxgsg8.h dxGraphicsStateGuardian8.I dxGraphicsStateGuardian8.h \
-    dxTextureContext8.h d3dfont8.h \
+    dxTextureContext8.h \
+    dxGeomMunger8.h \
+    d3dfont8.h \
     dxGraphicsDevice8.h
 
   // build dxGraphicsStateGuardian separately since its so big
@@ -35,6 +37,7 @@
   #define INCLUDED_SOURCES \
     config_dxgsg8.cxx \
     dxTextureContext8.cxx \
+    dxGeomMunger8.cxx \
     d3dfont8.cxx \
     dxGraphicsDevice8.cxx \
     wdxGraphicsPipe8.cxx wdxGraphicsWindow8.cxx

+ 2 - 0
panda/src/dxgsg8/config_dxgsg8.cxx

@@ -19,6 +19,7 @@
 #include "config_dxgsg8.h"
 #include "dxGraphicsStateGuardian8.h"
 #include "dxTextureContext8.h"
+#include "dxGeomMunger8.h"
 #include "graphicsPipeSelection.h"
 #include "wdxGraphicsWindow8.h"
 #include "wdxGraphicsPipe8.h"
@@ -143,6 +144,7 @@ init_libdxgsg8() {
 
   DXGraphicsStateGuardian8::init_type();
   DXTextureContext8::init_type();
+  DXGeomMunger8::init_type();
 
   wdxGraphicsPipe8::init_type();
   wdxGraphicsWindow8::init_type();

+ 27 - 0
panda/src/dxgsg8/dxGeomMunger8.I

@@ -0,0 +1,27 @@
+// Filename: dxGeomMunger8.I
+// Created by:  drose (11Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: DXGeomMunger8::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE DXGeomMunger8::
+DXGeomMunger8() {
+}

+ 74 - 0
panda/src/dxgsg8/dxGeomMunger8.cxx

@@ -0,0 +1,74 @@
+// Filename: dxGeomMunger8.cxx
+// Created by:  drose (11Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "dxGeomMunger8.h"
+
+TypeHandle DXGeomMunger8::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: DXGeomMunger8::munge_format_impl
+//       Access: Protected, Virtual
+//  Description: Given a source GeomVertexFormat, converts it if
+//               necessary to the appropriate format for rendering.
+////////////////////////////////////////////////////////////////////
+CPT(qpGeomVertexFormat) DXGeomMunger8::
+munge_format_impl(const qpGeomVertexFormat *orig) {
+  // We have to build a completely new format that includes only the
+  // appropriate components, in the appropriate order, in just one
+  // array.
+  PT(qpGeomVertexArrayFormat) new_array_format = new qpGeomVertexArrayFormat;
+
+  const qpGeomVertexDataType *vertex_type = 
+    orig->get_data_type(InternalName::get_vertex());
+  const qpGeomVertexDataType *normal_type = 
+    orig->get_data_type(InternalName::get_normal());
+  const qpGeomVertexDataType *color_type = 
+    orig->get_data_type(InternalName::get_color());
+  const qpGeomVertexDataType *texcoord_type = 
+    orig->get_data_type(InternalName::get_texcoord());
+
+  if (vertex_type != (const qpGeomVertexDataType *)NULL) {
+    new_array_format->add_data_type
+      (InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float);
+  } else {
+    // If we don't have a vertex type, not much we can do.
+    return orig;
+  }
+
+  if (normal_type != (const qpGeomVertexDataType *)NULL) {
+    new_array_format->add_data_type
+      (InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float);
+  }
+
+  if (color_type != (const qpGeomVertexDataType *)NULL) {
+    new_array_format->add_data_type
+      (InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb);
+  }
+
+  // To support multitexture, we will need to add all of the relevant
+  // texcoord types, and in the correct order (or at least in a known
+  // order).  For now, we just add the default texcoords only.
+  if (texcoord_type != (const qpGeomVertexDataType *)NULL) {
+    new_array_format->add_data_type
+      (InternalName::get_texcoord(), texcoord_type->get_num_values(),
+       qpGeomVertexDataType::NT_float);
+  }
+
+  PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(new_array_format);
+  return qpGeomVertexFormat::register_format(new_format);
+}

+ 60 - 0
panda/src/dxgsg8/dxGeomMunger8.h

@@ -0,0 +1,60 @@
+// Filename: dxGeomMunger8.h
+// Created by:  drose (11Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef DXGEOMMUNGER8_H
+#define DXGEOMMUNGER8_H
+
+#include "pandabase.h"
+#include "qpgeomMunger.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : DXGeomMunger8
+// Description : This specialization on GeomMunger finesses vertices
+//               for DirectX rendering.  In particular, it makes sure
+//               colors are stored in DirectX's packed_argb format,
+//               and that all relevant components are packed into a
+//               single array, in the correct order.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDADX DXGeomMunger8 : public qpGeomMunger {
+public:
+  INLINE DXGeomMunger8();
+
+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, "DXGeomMunger8",
+                  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 "dxGeomMunger8.I"
+
+#endif

+ 72 - 23
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -53,6 +53,7 @@
 #include "qpgeomTriangles.h"
 #include "qpgeomTristrips.h"
 #include "qpgeomTrifans.h"
+#include "dxGeomMunger8.h"
 
 #ifdef DO_PSTATS
 #include "pStatTimer.h"
@@ -2585,39 +2586,74 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
 //       Access: Public, Virtual
 //  Description: Called before a sequence of draw_primitive()
 //               functions are called, this should prepare the vertex
-//               buffer if necessary.
+//               data for rendering.  It returns true if the vertices
+//               are ok, false to abort this group of primitives.
 ////////////////////////////////////////////////////////////////////
-void DXGraphicsStateGuardian8::
+bool 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();
+
+  // The munger should have put the "vertex" data at the beginning of
+  // the first array.
+  const qpGeomVertexArrayFormat *array_format = format->get_array(0);
+
+  // Now we have to start with the vertex data, and work up from there
+  // in order, since that's the way the FVF is defined.
+  int n = 0;
+  int num_data_types = array_format->get_num_data_types();
+
+  DWORD fvf = 0;
   
-  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));
+  if (n < num_data_types && 
+      array_format->get_data_type(n)->get_name() == InternalName::get_vertex()) {
+    fvf |= D3DFVF_XYZ;
+    ++n;
   } else {
-    nassert_raise("Unexpected vertex format");
+    // No vertex data, no vertices.
+    return false;
   }
+  if (n < num_data_types && 
+      array_format->get_data_type(n)->get_name() == InternalName::get_normal()) {
+    fvf |= D3DFVF_NORMAL;
+    ++n;
+  }
+  if (n < num_data_types && 
+      array_format->get_data_type(n)->get_name() == InternalName::get_color()) {
+    fvf |= D3DFVF_DIFFUSE;
+    ++n;
+  }
+
+  // For multitexture support, we will need to look for all of the
+  // texcoord names and enable them in order.
+  if (n < num_data_types && 
+      array_format->get_data_type(n)->get_name() == InternalName::get_texcoord()) {
+    const qpGeomVertexDataType *data_type = array_format->get_data_type(n);
+    switch (data_type->get_num_values()) {
+    case 1:
+      fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE1(0);
+      ++n;
+      break;
+    case 2:
+      fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0);
+      ++n;
+      break;
+    case 3:
+      fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0);
+      ++n;
+      break;
+    case 4:
+      fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0);
+      ++n;
+      break;
+    }
+  }
+
+  set_vertex_format(fvf);
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -4016,6 +4052,19 @@ set_blend_mode() {
   enable_blend(false);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian8::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 DXGraphicsStateGuardian8::
+setup_geom_munger(PT(qpGeomMunger) munger) {
+  munger = new DXGeomMunger8;
+  GraphicsStateGuardian::setup_geom_munger(munger);
+}
+
 TypeHandle DXGraphicsStateGuardian8::get_type(void) const {
     return get_class_type();
 }

+ 2 - 1
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -89,7 +89,7 @@ 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 bool begin_draw_primitives(const qpGeomVertexData *vertex_data);
   virtual void draw_triangles(qpGeomTriangles *primitive);
   virtual void end_draw_primitives();
 
@@ -152,6 +152,7 @@ protected:
   virtual void bind_clip_plane(PlaneNode *plane, int plane_id);
 
   virtual void set_blend_mode();
+  virtual void setup_geom_munger(PT(qpGeomMunger) munger);
 
   void free_nondx_resources();            // free local internal buffers
   void free_d3d_device(void);

+ 1 - 0
panda/src/dxgsg8/dxgsg8_composite1.cxx

@@ -1,6 +1,7 @@
 #include "dxgsg8base.h"
 #include "config_dxgsg8.cxx"
 #include "dxTextureContext8.cxx"
+#include "dxGeomMunger8.cxx"
 #include "d3dfont8.cxx"
 #include "wdxGraphicsPipe8.cxx"
 #include "wdxGraphicsWindow8.cxx"

+ 7 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -2013,9 +2013,10 @@ draw_sphere(GeomSphere *geom, GeomContext *gc) {
 //       Access: Public, Virtual
 //  Description: Called before a sequence of draw_primitive()
 //               functions are called, this should prepare the vertex
-//               buffer if necessary.
+//               data for rendering.  It returns true if the vertices
+//               are ok, false to abort this group of primitives.
 ////////////////////////////////////////////////////////////////////
-void CLP(GraphicsStateGuardian)::
+bool CLP(GraphicsStateGuardian)::
 begin_draw_primitives(const qpGeomVertexData *vertex_data) {
   DO_PSTATS_STUFF(_draw_primitive_pcollector.start());
 
@@ -2034,7 +2035,8 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
                        stride, array_data + start);
     GLP(EnableClientState)(GL_VERTEX_ARRAY);
   } else {
-    GLP(DisableClientState)(GL_VERTEX_ARRAY);
+    // No vertex data?  No primitives!
+    return false;
   }
 
   bool has_normals = false;
@@ -2096,6 +2098,8 @@ begin_draw_primitives(const qpGeomVertexData *vertex_data) {
   }
 
   issue_scene_graph_color();
+
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -89,7 +89,7 @@ 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 bool begin_draw_primitives(const qpGeomVertexData *vertex_data);
   virtual void draw_triangles(qpGeomTriangles *primitive);
   virtual void end_draw_primitives();
 

+ 8 - 10
panda/src/gobj/qpgeom.cxx

@@ -207,19 +207,17 @@ write(ostream &out, int indent_level) const {
 ////////////////////////////////////////////////////////////////////
 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);
+  if (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();
   }
-
-  gsg->end_draw_primitives();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -169,7 +169,7 @@ 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 bool 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;