Panda3D
cardMaker.cxx
1 // Filename: cardMaker.cxx
2 // Created by: drose (16Mar02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "cardMaker.h"
16 #include "geomNode.h"
17 #include "transformState.h"
18 #include "colorAttrib.h"
19 #include "sceneGraphReducer.h"
20 #include "geom.h"
21 #include "geomTristrips.h"
22 #include "geomVertexWriter.h"
23 #include "geomVertexFormat.h"
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: CardMaker::reset
27 // Access: Public
28 // Description: Resets all the parameters to their initial defaults.
29 ////////////////////////////////////////////////////////////////////
30 void CardMaker::
31 reset() {
32  set_frame(0.0f, 1.0f, 0.0f, 1.0f);
33  set_uv_range(LTexCoord(0.0f, 0.0f), LTexCoord(1.0f, 1.0f));
34 
35  _has_color = false;
36  _color.set(1.0f, 1.0f, 1.0f, 1.0f);
37 
38  _has_normals = true;
39  _source_geometry = (PandaNode *)NULL;
40  _source_frame.set(0.0f, 0.0f, 0.0f, 0.0f);
41 }
42 
43 
44 ////////////////////////////////////////////////////////////////////
45 // Function: CardMaker::generate
46 // Access: Public
47 // Description: Generates a GeomNode that renders the specified
48 // geometry.
49 ////////////////////////////////////////////////////////////////////
50 PT(PandaNode) CardMaker::
51 generate() {
52  if (_source_geometry != (PandaNode *)NULL) {
53  return rescale_source_geometry();
54  }
55 
56  PT(GeomNode) gnode = new GeomNode(get_name());
57 
58  CPT(GeomVertexFormat) format;
59  if (_has_normals) {
60  if (_has_uvs) {
61  if (_has_3d_uvs) {
62  format = GeomVertexFormat::register_format
63  (new GeomVertexArrayFormat
64  (InternalName::get_vertex(), 3,
65  GeomEnums::NT_stdfloat, GeomEnums::C_point,
66  InternalName::get_normal(), 3,
67  GeomEnums::NT_stdfloat, GeomEnums::C_vector,
68  InternalName::get_texcoord(), 3,
69  GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
70  } else {
71  format = GeomVertexFormat::get_v3n3t2();
72  }
73  } else {
74  format = GeomVertexFormat::get_v3n3();
75  }
76  } else {
77  if (_has_uvs) {
78  if (_has_3d_uvs) {
79  format = GeomVertexFormat::register_format
80  (new GeomVertexArrayFormat
81  (InternalName::get_vertex(), 3,
82  GeomEnums::NT_stdfloat, GeomEnums::C_point,
83  InternalName::get_texcoord(), 3,
84  GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
85  } else {
86  format = GeomVertexFormat::get_v3t2();
87  }
88  } else {
89  format = GeomVertexFormat::get_v3();
90  }
91  }
92 
93  PT(GeomVertexData) vdata = new GeomVertexData
94  ("card", format, Geom::UH_static);
95  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
96 
97  vertex.add_data3(_ul_pos);
98  vertex.add_data3(_ll_pos);
99  vertex.add_data3(_ur_pos);
100  vertex.add_data3(_lr_pos);
101 
102  if (_has_uvs) {
103  GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
104  texcoord.add_data3(_ul_tex);
105  texcoord.add_data3(_ll_tex);
106  texcoord.add_data3(_ur_tex);
107  texcoord.add_data3(_lr_tex);
108  }
109 
110  if (_has_normals) {
111  GeomVertexWriter normal(vdata, InternalName::get_normal());
112  LVector3 n;
113  n = (_ll_pos - _ul_pos).cross(_ur_pos - _ul_pos);
114  n.normalize();
115  normal.add_data3(n);
116  n = (_lr_pos - _ll_pos).cross(_ul_pos - _ll_pos);
117  n.normalize();
118  normal.add_data3(n);
119  n = (_ul_pos - _ur_pos).cross(_lr_pos - _ur_pos);
120  n.normalize();
121  normal.add_data3(n);
122  n = (_ur_pos - _lr_pos).cross(_ll_pos - _lr_pos);
123  n.normalize();
124  normal.add_data3(n);
125  }
126 
127  PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
128  strip->set_shade_model(Geom::SM_uniform);
129  strip->add_next_vertices(4);
130  strip->close_primitive();
131 
132  PT(Geom) geom = new Geom(vdata);
133  geom->add_primitive(strip);
134 
135  CPT(RenderState) state = RenderState::make_empty();
136  if (_has_color) {
137  state = RenderState::make(ColorAttrib::make_flat(_color));
138  }
139 
140  gnode->add_geom(geom, state);
141 
142  return gnode.p();
143 }
144 
145 ////////////////////////////////////////////////////////////////////
146 // Function: CardMaker::set_uv_range
147 // Access: Public
148 // Description: Sets the range of UV's that will be applied to the
149 // vertices. If set_has_uvs() is true (as it is by
150 // default), the vertices will be generated with the
151 // indicated range of UV's, which will be useful if a
152 // texture is applied.
153 ////////////////////////////////////////////////////////////////////
154 void CardMaker::
155 set_uv_range(const LTexCoord3 &ll, const LTexCoord3 &lr, const LTexCoord3 &ur, const LTexCoord3 &ul) {
156  _ll_tex = ll;
157  _lr_tex = lr;
158  _ur_tex = ur;
159  _ul_tex = ul;
160  _has_uvs = true;
161  _has_3d_uvs = true;
162 }
163 
164 ////////////////////////////////////////////////////////////////////
165 // Function: CardMaker::set_uv_range
166 // Access: Public
167 // Description: Sets the range of UV's that will be applied to the
168 // vertices. If set_has_uvs() is true (as it is by
169 // default), the vertices will be generated with the
170 // indicated range of UV's, which will be useful if a
171 // texture is applied.
172 ////////////////////////////////////////////////////////////////////
173 void CardMaker::
174 set_uv_range(const LTexCoord &ll, const LTexCoord &lr, const LTexCoord &ur, const LTexCoord &ul) {
175  _ll_tex.set(ll[0], ll[1], 0.0f);
176  _lr_tex.set(lr[0], lr[1], 0.0f);
177  _ur_tex.set(ur[0], ur[1], 0.0f);
178  _ul_tex.set(ul[0], ul[1], 0.0f);
179  _has_uvs = true;
180  _has_3d_uvs = false;
181 }
182 
183 ////////////////////////////////////////////////////////////////////
184 // Function: CardMaker::set_uv_range
185 // Access: Public
186 // Description: Sets the range of UV's that will be applied to the
187 // vertices. If set_has_uvs() is true (as it is by
188 // default), the vertices will be generated with the
189 // indicated range of UV's, which will be useful if a
190 // texture is applied.
191 ////////////////////////////////////////////////////////////////////
192 void CardMaker::
193 set_uv_range(const LTexCoord &ll, const LTexCoord &ur) {
194  _ll_tex.set(ll[0], ll[1], 0.0f);
195  _lr_tex.set(ur[0], ll[1], 0.0f);
196  _ur_tex.set(ur[0], ur[1], 0.0f);
197  _ul_tex.set(ll[0], ur[1], 0.0f);
198  _has_uvs = true;
199  _has_3d_uvs = false;
200 }
201 
202 ////////////////////////////////////////////////////////////////////
203 // Function: CardMaker::set_uv_range
204 // Access: Public
205 // Description: Sets the range of UV's that will be applied to the
206 // vertices. If set_has_uvs() is true (as it is by
207 // default), the vertices will be generated with the
208 // indicated range of UV's, which will be useful if a
209 // texture is applied.
210 ////////////////////////////////////////////////////////////////////
211 void CardMaker::
212 set_uv_range(const LVector4 &x, const LVector4 &y, const LVector4 &z) {
213  _ll_tex.set(x[0], y[0], z[0]);
214  _lr_tex.set(x[1], y[1], z[1]);
215  _ur_tex.set(x[2], y[2], z[2]);
216  _ul_tex.set(x[3], y[3], z[3]);
217  _has_uvs = true;
218  _has_3d_uvs = true;
219 }
220 
221 ////////////////////////////////////////////////////////////////////
222 // Function: CardMaker::set_uv_range_cube
223 // Access: Public
224 // Description: Sets the range of UV's that will be applied to the
225 // vertices appropriately for a cube-map face.
226 ////////////////////////////////////////////////////////////////////
227 void CardMaker::
228 set_uv_range_cube(int face) {
229  LVector4 varya(-1, 1, 1, -1);
230  LVector4 varyb(-1, -1, 1, 1);
231  LVector4 fixed( 1, 1, 1, 1);
232  switch(face) {
233  case 0: set_uv_range( fixed, -varyb, -varya); break; // positive_x
234  case 1: set_uv_range(-fixed, -varyb, varya); break; // negative_x
235  case 2: set_uv_range( varya, fixed, varyb); break; // positive_y
236  case 3: set_uv_range( varya, -fixed, -varyb); break; // negative_y
237  case 4: set_uv_range( varya, -varyb, fixed); break; // positive_z
238  case 5: set_uv_range(-varya, -varyb, -fixed); break; // negative_z
239  }
240 }
241 
242 ////////////////////////////////////////////////////////////////////
243 // Function: CardMaker::set_uv_range
244 // Access: Public
245 // Description: Sets the range of UV's that will be applied to the
246 // vertices appropriately to show the non-pad region
247 // of the texture.
248 ////////////////////////////////////////////////////////////////////
249 void CardMaker::
250 set_uv_range(const Texture *tex) {
251  nassertv(tex->get_texture_type() == Texture::TT_2d_texture);
252  int nonpadx = tex->get_x_size() - tex->get_pad_x_size();
253  int nonpady = tex->get_y_size() - tex->get_pad_y_size();
254  double maxu = (nonpadx*1.0) / tex->get_x_size();
255  double maxv = (nonpady*1.0) / tex->get_y_size();
256  set_uv_range(LTexCoord(0.0,0.0), LTexCoord(maxu,maxv));
257 }
258 
259 ////////////////////////////////////////////////////////////////////
260 // Function: CardMaker::rescale_source_geometry
261 // Access: Private
262 // Description: Generates the card by rescaling the source geometry
263 // appropriately.
264 ////////////////////////////////////////////////////////////////////
265 PT(PandaNode) CardMaker::
266 rescale_source_geometry() {
267  PT(PandaNode) root = _source_geometry->copy_subgraph();
268 
269  // Determine the translate and scale appropriate for our geometry.
270  LVector3 frame_max = _ll_pos.fmax(_lr_pos.fmax(_ur_pos.fmax(_ul_pos)));
271  LVector3 frame_min = _ll_pos.fmin(_lr_pos.fmin(_ur_pos.fmax(_ul_pos)));
272  LVector3 frame_ctr = (frame_max + frame_min) * 0.5f;
273 
274  LVector3 geom_center((_source_frame[0] + _source_frame[1]) * 0.5f,
275  frame_ctr[1],
276  (_source_frame[2] + _source_frame[3]) * 0.5f);
277 
278  LVector3 scale((frame_max[0] - frame_min[0]) / (_source_frame[1] - _source_frame[0]),
279  0.0,
280  (frame_max[2] - frame_min[2]) / (_source_frame[3] - _source_frame[2]));
281 
282  LVector3 trans = frame_ctr - geom_center;
283 
284  CPT(TransformState) transform =
285  TransformState::make_pos_hpr_scale(trans, LPoint3(0.0f, 0.0f, 0.0f), scale);
286  root->set_transform(transform);
287 
288  if (_has_color) {
289  root->set_attrib(ColorAttrib::make_flat(_color));
290  }
291 
292  // Now flatten out the geometry as much as we can.
293  SceneGraphReducer reducer;
294  reducer.apply_attribs(root);
295  reducer.flatten(root, ~0);
296 
297  return root;
298 }
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
int get_pad_y_size() const
Returns size of the pad region.
Definition: texture.I:720
TextureType get_texture_type() const
Returns the overall interpretation of the texture.
Definition: texture.I:859
void set_frame(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top)
Sets the size of the card.
Definition: cardMaker.I:65
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:75
An interface for simplifying ("flattening") scene graphs by eliminating unneeded nodes and collapsing...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
Defines a series of triangle strips.
Definition: geomTristrips.h:25
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
int get_pad_x_size() const
Returns size of the pad region.
Definition: texture.I:709
void set_uv_range_cube(int face)
Sets the range of UV's that will be applied to the vertices appropriately for a cube-map face...
Definition: cardMaker.cxx:228
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
Definition: geom.h:58
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
This is a four-component vector distance.
Definition: lvector4.h:91
int flatten(PandaNode *root, int combine_siblings_bits)
Simplifies the graph by removing unnecessary nodes and nodes.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:53
void apply_attribs(PandaNode *node, int attrib_types=~(TT_clip_plane|TT_cull_face|TT_apply_texture_color))
Walks the scene graph, accumulating attribs of the indicated types, applying them to the vertices...
int get_y_size() const
Returns the height of the texture image in texels.
Definition: texture.I:650
void set_uv_range(const LTexCoord &ll, const LTexCoord &ur)
Sets the range of UV's that will be applied to the vertices.
Definition: cardMaker.cxx:193
This is a two-component point in space.
Definition: lpoint2.h:92
bool normalize()
Normalizes the vector in place.
Definition: lvecBase3.h:783
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:37
void reset()
Resets all the parameters to their initial defaults.
Definition: cardMaker.cxx:31
int get_x_size() const
Returns the width of the texture image in texels.
Definition: texture.I:638