Panda3D
cLwoPolygons.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file cLwoPolygons.cxx
10  * @author drose
11  * @date 2001-04-25
12  */
13 
14 #include "cLwoPolygons.h"
15 #include "lwoToEggConverter.h"
16 #include "cLwoPoints.h"
17 #include "cLwoLayer.h"
18 #include "cLwoSurface.h"
19 
20 #include "lwoPolygonTags.h"
21 #include "lwoTags.h"
23 #include "eggData.h"
24 #include "eggPolygon.h"
25 #include "eggPoint.h"
26 #include "deg_2_rad.h"
27 
28 using std::string;
29 
30 /**
31  * Associates the indicated PolygonTags and Tags with the polygons in this
32  * chunk. This may define features such as per-polygon surfaces, parts, and
33  * smoothing groups.
34  */
36 add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags) {
37  if (_tags != nullptr && _tags != tags) {
38  nout << "Multiple Tags fields in effect on the same polygons.\n";
39  }
40  _tags = tags;
41 
42  IffId type = lwo_ptags->_tag_type;
43 
44  bool inserted = _ptags.insert(PTags::value_type(type, lwo_ptags)).second;
45  if (!inserted) {
46  nout << "Multiple polygon tags on the same polygons of type "
47  << type << "\n";
48 
49  } else {
50  if (type == IffId("SURF")) {
51  _surf_ptags = lwo_ptags;
52  }
53  }
54 }
55 
56 /**
57  * Associates the indicated DiscontinousVertexMap with the polygons. This can
58  * be used in conjunction with (or in place of) the VertexMap associated with
59  * the points set, to define per-polygon UV's etc.
60  */
62 add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad) {
63  IffId map_type = lwo_vmad->_map_type;
64  const string &name = lwo_vmad->_name;
65 
66  bool inserted;
67  if (map_type == IffId("TXUV")) {
68  inserted =
69  _txuv.insert(VMad::value_type(name, lwo_vmad)).second;
70 
71  } else {
72  return;
73  }
74 
75  if (!inserted) {
76  nout << "Multiple discontinous vertex maps on the same polygons of type "
77  << map_type << " named " << name << "\n";
78  }
79 }
80 
81 /**
82  * Returns the surface associated with the given polygon, or NULL if no
83  * surface is associated.
84  */
86 get_surface(int polygon_index) const {
87  if (_surf_ptags == nullptr) {
88  // No surface definitions.
89  return nullptr;
90  }
91 
92  if (!_surf_ptags->has_tag(polygon_index)) {
93  // The polygon isn't tagged.
94  return nullptr;
95  }
96 
97  int tag_index = _surf_ptags->get_tag(polygon_index);
98  if (_tags == nullptr || tag_index < 0 ||
99  tag_index >= _tags->get_num_tags()) {
100  // The tag index is out-of-bounds.
101  nout << "Invalid polygon tag index " << tag_index << "\n";
102  return nullptr;
103  }
104 
105  string tag = _tags->get_tag(tag_index);
106 
107  // Now look up the surface name in the header.
108  CLwoSurface *surface = _converter->get_surface(tag);
109  if (surface == nullptr) {
110  nout << "Unknown surface " << tag << "\n";
111  return nullptr;
112  }
113 
114  return surface;
115 }
116 
117 /**
118  * Returns true if there is a UV of the indicated name associated with the
119  * given vertex of the indicated polygon, false otherwise. If true, fills in
120  * uv with the value.
121  *
122  * This performs a lookup in the optional "discontinuous" vertex mapping,
123  * which provides the ability to map different UV's per each polygon for the
124  * same vertex. If the UV is not defined here, it may also be defined in the
125  * standard vertex map, which is associated with the points themselves.
126  */
128 get_uv(const string &uv_name, int pi, int vi, LPoint2 &uv) const {
129  VMad::const_iterator ni = _txuv.find(uv_name);
130  if (ni == _txuv.end()) {
131  return false;
132  }
133 
134  const LwoDiscontinuousVertexMap *vmad = (*ni).second;
135  if (vmad->_dimension != 2) {
136  nout << "Unexpected dimension of " << vmad->_dimension
137  << " for discontinuous UV map " << uv_name << "\n";
138  return false;
139  }
140 
141  if (!vmad->has_value(pi, vi)) {
142  return false;
143  }
144 
145  PTA_stdfloat value = vmad->get_value(pi, vi);
146 
147  uv.set(value[0], value[1]);
148  return true;
149 }
150 
151 /**
152  * Creates the egg structures associated with this Lightwave object.
153  */
155 make_egg() {
156  // First, we need a temporary group to hold all of the polygons we'll
157  // create.
158  _egg_group = new EggGroup;
159 
160  if (_polygons->_polygon_type == IffId("CURV")) {
161  nout << "Ignoring Catmull-Rom splines.\n";
162 
163  } else if (_polygons->_polygon_type == IffId("PTCH")) {
164  nout << "Treating subdivision patches as ordinary polygons.\n";
165  make_faces();
166 
167  } else if (_polygons->_polygon_type == IffId("MBAL")) {
168  nout << "Ignoring metaballs.\n";
169 
170  } else if (_polygons->_polygon_type == IffId("BONE")) {
171  nout << "Ignoring bones.\n";
172 
173  } else if (_polygons->_polygon_type == IffId("FACE")) {
174  make_faces();
175 
176  } else {
177  nout << "Ignoring unknown geometry type " << _polygons->_polygon_type
178  << ".\n";
179  }
180 }
181 
182 /**
183  * Connects all the egg structures together.
184  */
186 connect_egg() {
187  nassertv(_points->_layer->_egg_group != nullptr);
188  nassertv(_egg_group != nullptr);
189  _points->_layer->_egg_group->steal_children(*_egg_group);
190 }
191 
192 
193 /**
194  * Generates "face" polygons, i.e. actual polygons.
195  */
196 void CLwoPolygons::
197 make_faces() {
198  PN_stdfloat smooth_angle = -1.0;
199 
200  int num_polygons = _polygons->get_num_polygons();
201  for (int pindex = 0; pindex < num_polygons; pindex++) {
202  LwoPolygons::Polygon *poly = _polygons->get_polygon(pindex);
203  CLwoSurface *surface = get_surface(pindex);
204 
205  bool is_valid = true;
206 
207  // Set up the vertices.
208  const LwoPoints *points = _points->_points;
209  int num_points = points->get_num_points();
210  EggVertexPool *egg_vpool = _points->_egg_vpool;
211 
212  // We reverse the vertex ordering to compensate for Lightwave's clockwise
213  // ordering convention. We also want to start with the last vertex, so
214  // that the first convex angle is the first angle in the EggPolygon (for
215  // determining correct normals).
216  PT(EggPrimitive) egg_prim;
217 
218  if (poly->_vertices.size() == 1) {
219  egg_prim = new EggPoint;
220  } else {
221  egg_prim = new EggPolygon;
222  }
223 
224  // First, we have to create a temporary vector of vertices for the
225  // polygon, so we can possibly adjust the properties of these vertices
226  // (like the UV's) in the shader before we create them.
227  vector_PT_EggVertex egg_vertices;
228 
229  int num_vertices = poly->_vertices.size();
230  for (int vi = num_vertices; vi > 0; vi--) {
231  int vindex = poly->_vertices[vi % num_vertices];
232  if (vindex < 0 || vindex >= num_points) {
233  nout << "Invalid vertex index " << vindex << " in polygon.\n";
234  is_valid = false;
235  } else {
236  PT(EggVertex) egg_vertex = new EggVertex;
237  LPoint3d pos = LCAST(double, points->get_point(vindex));
238  egg_vertex->set_pos(pos);
239 
240  // Does the vertex used named UV's?
241  if (surface != nullptr && surface->has_named_uvs()) {
242  string uv_name = surface->get_uv_name();
243  LPoint2 uv;
244  if (get_uv(uv_name, pindex, vindex, uv)) {
245  // This UV is defined in a "discontinuous" map, that associated a
246  // particular UV per each polygon.
247  egg_vertex->set_uv(LCAST(double, uv));
248 
249  } else if (_points->get_uv(uv_name, vindex, uv)) {
250  // The UV does not appear in a discontinuous map, but it is
251  // defined in the points set.
252  egg_vertex->set_uv(LCAST(double, uv));
253  }
254  }
255 
256  egg_vertices.push_back(egg_vertex);
257  }
258  }
259 
260  if (is_valid) {
261  if (surface != nullptr) {
262  surface->apply_properties(egg_prim, egg_vertices, smooth_angle);
263  }
264 
265  // Now add all the vertices officially to the primitive.
266  vector_PT_EggVertex::const_iterator evi;
267  for (evi = egg_vertices.begin(); evi != egg_vertices.end(); ++evi) {
268  EggVertex *egg_vertex = (*evi);
269  EggVertex *new_vertex = egg_vpool->create_unique_vertex(*egg_vertex);
270  egg_prim->add_vertex(new_vertex);
271  }
272 
273  // And add the primitive to its parent.
274  _egg_group->add_child(egg_prim.p());
275  }
276  }
277 
278  CoordinateSystem cs = _converter->get_egg_data()->get_coordinate_system();
279  if (smooth_angle > 0.0) {
280  _egg_group->recompute_vertex_normals(rad_2_deg(smooth_angle), cs);
281  } else {
282  _egg_group->recompute_polygon_normals(cs);
283  }
284 }
eggData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LwoPoints
An array of points that will be referenced by later chunks.
Definition: lwoPoints.h:26
lwoDiscontinuousVertexMap.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lwoPolygonTags.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LwoPoints::get_num_points
int get_num_points() const
Returns the number of points of this group.
Definition: lwoPoints.cxx:26
eggPoint.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CLwoPolygons::connect_egg
void connect_egg()
Connects all the egg structures together.
Definition: cLwoPolygons.cxx:186
LwoDiscontinuousVertexMap::has_value
bool has_value(int polygon_index, int vertex_index) const
Returns true if the map has a value associated with the given index, false otherwise.
Definition: lwoDiscontinuousVertexMap.cxx:30
SomethingToEggConverter::get_egg_data
EggData * get_egg_data()
Returns the EggData structure.
Definition: somethingToEggConverter.I:380
CLwoSurface::has_named_uvs
bool has_named_uvs() const
Returns true if the surface is set up to reference UV's stored on the vertices, by name (as opposed t...
Definition: cLwoSurface.I:30
cLwoPoints.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggPrimitive
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:49
CLwoPolygons::make_egg
void make_egg()
Creates the egg structures associated with this Lightwave object.
Definition: cLwoPolygons.cxx:155
EggData::get_coordinate_system
get_coordinate_system
Returns the coordinate system in which the egg file is defined.
Definition: eggData.h:73
LwoTags::get_tag
std::string get_tag(int n) const
Returns the nth tag of this group.
Definition: lwoTags.cxx:34
CLwoPoints::get_uv
bool get_uv(const std::string &uv_name, int n, LPoint2 &uv) const
Returns true if there is a UV of the indicated name associated with the given vertex,...
Definition: cLwoPoints.cxx:55
IffId
A four-byte chunk ID appearing in an "IFF" file.
Definition: iffId.h:26
CLwoPolygons::get_uv
bool get_uv(const std::string &uv_name, int pi, int vi, LPoint2 &uv) const
Returns true if there is a UV of the indicated name associated with the given vertex of the indicated...
Definition: cLwoPolygons.cxx:128
cLwoPolygons.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertex
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
EggPolygon
A single polygon.
Definition: eggPolygon.h:24
LwoPolygonTags::get_tag
int get_tag(int polygon_index) const
Returns the tag associated with the given polygon index, or -1 if there is no tag associated.
Definition: lwoPolygonTags.cxx:37
LwoToEggConverter::get_surface
CLwoSurface * get_surface(const std::string &name) const
Returns a pointer to the surface definition with the given name, or NULL if there is no such surface.
Definition: lwoToEggConverter.cxx:185
CLwoSurface
This class is a wrapper around LwoSurface and stores additional information useful during the convers...
Definition: cLwoSurface.h:39
LwoDiscontinuousVertexMap
A mapping of floating-point values per integer index.
Definition: lwoDiscontinuousVertexMap.h:28
LwoPolygonTags::has_tag
bool has_tag(int polygon_index) const
Returns true if the map has a tag associated with the given polygon index, false otherwise.
Definition: lwoPolygonTags.cxx:28
LwoPoints::get_point
const LPoint3 & get_point(int n) const
Returns the nth point of this group.
Definition: lwoPoints.cxx:34
LwoPolygons::Polygon
Definition: lwoPolygons.h:41
lwoToEggConverter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CLwoSurface::apply_properties
void apply_properties(EggPrimitive *egg_prim, vector_PT_EggVertex &egg_vertices, PN_stdfloat &smooth_angle)
Applies the color, texture, etc.
Definition: cLwoSurface.cxx:162
LwoPolygonTags
An association of polygons defined in the most recent LwoPolygons chunk to tag ids defined in the mos...
Definition: lwoPolygonTags.h:26
CLwoPolygons::get_surface
CLwoSurface * get_surface(int polygon_index) const
Returns the surface associated with the given polygon, or NULL if no surface is associated.
Definition: cLwoPolygons.cxx:86
deg_2_rad.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cLwoSurface.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertexPool::create_unique_vertex
EggVertex * create_unique_vertex(const EggVertex &copy)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
Definition: eggVertexPool.cxx:472
EggVertexPool
A collection of vertices.
Definition: eggVertexPool.h:41
lwoTags.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LwoTags
An array of tag strings that will be referenced by later chunks.
Definition: lwoTags.h:31
LwoDiscontinuousVertexMap::get_value
PTA_stdfloat get_value(int polygon_index, int vertex_index) const
Returns the mapping value associated with the given index, or an empty PTA_stdfloat if there is no ma...
Definition: lwoDiscontinuousVertexMap.cxx:46
EggGroup
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
EggPoint
A single point, or a collection of points as defined by a single <PointLight> entry.
Definition: eggPoint.h:25
LwoTags::get_num_tags
int get_num_tags() const
Returns the number of tags of this group.
Definition: lwoTags.cxx:26
cLwoLayer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggPolygon.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CLwoPolygons::add_vmad
void add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad)
Associates the indicated DiscontinousVertexMap with the polygons.
Definition: cLwoPolygons.cxx:62
CLwoSurface::get_uv_name
const std::string & get_uv_name() const
Returns the name of the set of UV's that are associated with this surface, if has_named_uvs() is true...
Definition: cLwoSurface.I:40
CLwoPolygons::add_ptags
void add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags)
Associates the indicated PolygonTags and Tags with the polygons in this chunk.
Definition: cLwoPolygons.cxx:36