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  */
35 void CLwoPolygons::
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  */
61 void CLwoPolygons::
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  */
127 bool CLwoPolygons::
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  */
154 void CLwoPolygons::
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  */
185 void CLwoPolygons::
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 }
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:47
int get_num_points() const
Returns the number of points of this group.
Definition: lwoPoints.cxx:26
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad)
Associates the indicated DiscontinousVertexMap with the polygons.
void add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags)
Associates the indicated PolygonTags and Tags with the polygons in this chunk.
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...
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...
std::string get_tag(int n) const
Returns the nth tag of this group.
Definition: lwoTags.cxx:34
An association of polygons defined in the most recent LwoPolygons chunk to tag ids defined in the mos...
EggData * get_egg_data()
Returns the EggData structure.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_tag(int polygon_index) const
Returns the tag associated with the given polygon index, or -1 if there is no tag associated.
An array of tag strings that will be referenced by later chunks.
Definition: lwoTags.h:31
A single point, or a collection of points as defined by a single <PointLight> entry.
Definition: eggPoint.h:25
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
void make_egg()
Creates the egg structures associated with this Lightwave object.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
const LPoint3 & get_point(int n) const
Returns the nth point of this group.
Definition: lwoPoints.cxx:34
This class is a wrapper around LwoSurface and stores additional information useful during the convers...
Definition: cLwoSurface.h:39
CLwoSurface * get_surface(int polygon_index) const
Returns the surface associated with the given polygon, or NULL if no surface is associated.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void apply_properties(EggPrimitive *egg_prim, vector_PT_EggVertex &egg_vertices, PN_stdfloat &smooth_angle)
Applies the color, texture, etc.
int get_num_tags() const
Returns the number of tags of this group.
Definition: lwoTags.cxx:26
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A single polygon.
Definition: eggPolygon.h:24
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
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
get_coordinate_system
Returns the coordinate system in which the egg file is defined.
Definition: eggData.h:73
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A four-byte chunk ID appearing in an "IFF" file.
Definition: iffId.h:26
void connect_egg()
Connects all the egg structures together.
A mapping of floating-point values per integer index.
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.
A collection of vertices.
Definition: eggVertexPool.h:41
bool has_tag(int polygon_index) const
Returns true if the map has a tag associated with the given polygon index, false otherwise.
An array of points that will be referenced by later chunks.
Definition: lwoPoints.h:26