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