Panda3D
Loading...
Searching...
No Matches
eggMakeTube.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 eggMakeTube.cxx
10 * @author drose
11 * @date 2003-10-01
12 */
13
14#include "eggMakeTube.h"
15#include "eggGroup.h"
16#include "eggVertexPool.h"
17#include "eggVertex.h"
18#include "eggPolygon.h"
19#include "pointerTo.h"
20#include "look_at.h"
21
22/**
23 *
24 */
25EggMakeTube::
26EggMakeTube() {
27
28 set_program_brief("generate a tube or sphere from geometry in an .egg file");
29 set_program_description
30 ("egg-make-tube generates an egg file representing a \"tube\" model, "
31 "a cylinder capped on both ends by hemispheres. This is similar "
32 "in shape to the CollisionCapsule object within Panda.\n\n"
33 "This program can also generate spheres if you omit -b; in this "
34 "case, you are generating a degenerate tube of length 0.");
35
36 add_option
37 ("a", "x,y,z", 0,
38 "Specify the first endpoint of the tube.",
39 &EggWriter::dispatch_double_triple, nullptr, _point_a);
40
41 add_option
42 ("b", "x,y,z", 0,
43 "Specify the second endpoint of the tube.",
44 &EggWriter::dispatch_double_triple, &_got_point_b, _point_b);
45
46 add_option
47 ("r", "radius", 0,
48 "Specify the radius of the tube. The tube will extend beyond "
49 "the endpoints in each direction by the amount of radius.",
50 &EggWriter::dispatch_double, nullptr, &_radius);
51
52 add_option
53 ("slices", "count", 0,
54 "Specify the number of slices appearing radially around the tube.",
55 &EggWriter::dispatch_int, nullptr, &_num_slices);
56
57 add_option
58 ("crings", "count", 0,
59 "Specify the number of rings appearing in each endcap of the tube.",
60 &EggWriter::dispatch_int, nullptr, &_num_crings);
61
62 add_option
63 ("trings", "count", 0,
64 "Specify the number of rings appearing in the cylindrical body "
65 "of the tube.",
66 &EggWriter::dispatch_int, nullptr, &_num_trings);
67
68 _point_a[0] = 0.0;
69 _point_a[1] = 0.0;
70 _point_a[2] = 0.0;
71
72 _point_b[0] = 0.0;
73 _point_b[1] = 0.0;
74 _point_b[2] = 0.0;
75
76 _radius = 1.0;
77
78 _num_slices = 8;
79 _num_crings = 4;
80 _num_trings = 1;
81}
82
83/**
84 *
85 */
86void EggMakeTube::
87run() {
88 if (!_got_point_b) {
89 _point_b[0] = _point_a[0];
90 _point_b[1] = _point_a[1];
91 _point_b[2] = _point_a[2];
92 }
93
94 // We will generate the vertices in the canonical space (along the y axis),
95 // then transform it to the desired point.
96 LVector3d direction(_point_b[0] - _point_a[0],
97 _point_b[1] - _point_a[1],
98 _point_b[2] - _point_a[2]);
99 _length = direction.length();
100
101 // First, create an enclosing group and a vertex pool.
102 _group = new EggGroup("tube");
103 _data->add_child(_group);
104
105 _vpool = new EggVertexPool("tube");
106 _group->add_child(_vpool);
107
108 // Generate the first endcap.
109 int ri, si;
110 EggVertex *vtx_1;
111 EggVertex *vtx_2;
112
113 for (ri = 0; ri < _num_crings; ri++) {
114 vtx_1 = nullptr;
115 vtx_2 = nullptr;
116 for (si = 0; si <= _num_slices; si++) {
117 EggVertex *vtx_3 = calc_sphere1_vertex(ri, si);
118 EggVertex *vtx_4 = calc_sphere1_vertex(ri + 1, si);
119 add_polygon(vtx_1, vtx_2, vtx_4, vtx_3);
120 vtx_1 = vtx_3;
121 vtx_2 = vtx_4;
122 }
123 }
124
125 // Now the cylinder sides.
126 if (_length != 0.0) {
127 for (ri = 0; ri < _num_trings; ri++) {
128 vtx_1 = nullptr;
129 vtx_2 = nullptr;
130 for (si = 0; si <= _num_slices; si++) {
131 EggVertex *vtx_3 = calc_tube_vertex(ri, si);
132 EggVertex *vtx_4 = calc_tube_vertex(ri + 1, si);
133 add_polygon(vtx_1, vtx_2, vtx_4, vtx_3);
134 vtx_1 = vtx_3;
135 vtx_2 = vtx_4;
136 }
137 }
138 }
139
140 // And the second endcap.
141 for (ri = _num_crings - 1; ri >= 0; ri--) {
142 vtx_1 = nullptr;
143 vtx_2 = nullptr;
144 for (si = 0; si <= _num_slices; si++) {
145 EggVertex *vtx_3 = calc_sphere2_vertex(ri + 1, si);
146 EggVertex *vtx_4 = calc_sphere2_vertex(ri, si);
147 add_polygon(vtx_1, vtx_2, vtx_4, vtx_3);
148 vtx_1 = vtx_3;
149 vtx_2 = vtx_4;
150 }
151 }
152
153 // Now transform the vertices out of the canonical position.
154 LMatrix4d mat;
155 look_at(mat, direction, LVector3d(0.0, 0.0, 1.0), CS_zup_right);
156 mat.set_row(3, LPoint3d(_point_a[0], _point_a[1], _point_a[2]));
157 _group->transform(mat);
158
160}
161
162/**
163 * Calculates a particular vertex on the surface of the first endcap
164 * hemisphere.
165 */
166EggVertex *EggMakeTube::
167calc_sphere1_vertex(int ri, int si) {
168 double r = (double)ri / (double)_num_crings;
169 double s = (double)si / (double)_num_slices;
170
171 // Find the point on the rim, based on the slice.
172 double theta = s * 2.0 * MathNumbers::pi;
173 double x_rim = cos(theta);
174 double z_rim = sin(theta);
175
176 // Now pull that point in towards the pole, based on the ring.
177 double phi = r * 0.5 * MathNumbers::pi;
178 double to_pole = sin(phi);
179
180 double x = _radius * x_rim * to_pole;
181 double y = -_radius * cos(phi);
182 double z = _radius * z_rim * to_pole;
183
184 EggVertex vert;
185 vert.set_pos(LPoint3d(x, y, z));
186
187 return _vpool->create_unique_vertex(vert);
188}
189
190/**
191 * Calculates a vertex on the side of the cylindrical body of the tube.
192 */
193EggVertex *EggMakeTube::
194calc_tube_vertex(int ri, int si) {
195 double r = (double)ri / (double)_num_trings;
196 double s = (double)si / (double)_num_slices;
197
198 // Find the point on the rim, based on the slice.
199 double theta = s * 2.0 * MathNumbers::pi;
200 double x_rim = cos(theta);
201 double z_rim = sin(theta);
202
203 double x = _radius * x_rim;
204 double y = _length * r;
205 double z = _radius * z_rim;
206
207 EggVertex vert;
208 vert.set_pos(LPoint3d(x, y, z));
209
210 return _vpool->create_unique_vertex(vert);
211}
212
213/**
214 * Calculates a particular vertex on the surface of the second endcap
215 * hemisphere.
216 */
217EggVertex *EggMakeTube::
218calc_sphere2_vertex(int ri, int si) {
219 double r = (double)ri / (double)_num_crings;
220 double s = (double)si / (double)_num_slices;
221
222 // Find the point on the rim, based on the slice.
223 double theta = s * 2.0 * MathNumbers::pi;
224 double x_rim = cos(theta);
225 double z_rim = sin(theta);
226
227 // Now pull that point in towards the pole, based on the ring.
228 double phi = r * 0.5 * MathNumbers::pi;
229 double to_pole = sin(phi);
230
231 double x = _radius * x_rim * to_pole;
232 double y = _length + _radius * cos(phi);
233 double z = _radius * z_rim * to_pole;
234
235 EggVertex vert;
236 vert.set_pos(LPoint3d(x, y, z));
237
238 return _vpool->create_unique_vertex(vert);
239}
240
241/**
242 * Adds the polygon defined by the indicated four vertices to the group. If
243 * the first vertex is NULL, does nothing.
244 */
245void EggMakeTube::
246add_polygon(EggVertex *a, EggVertex *b, EggVertex *c, EggVertex *d) {
247 if (a == nullptr) {
248 return;
249 }
250
251 PT(EggPolygon) poly = new EggPolygon;
252 poly->add_vertex(a);
253 if (a != b) {
254 poly->add_vertex(b);
255 }
256 poly->add_vertex(c);
257 if (c != d) {
258 poly->add_vertex(d);
259 }
260
261 _group->add_child(poly.p());
262}
263
264
265int main(int argc, char *argv[]) {
266 EggMakeTube prog;
267 prog.parse_command_line(argc, argv);
268 prog.run();
269 return 0;
270}
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition eggGroup.h:34
A program to generate an egg file representing a tube model, similar in shape to a CollisionCapsule.
Definition eggMakeTube.h:29
void transform(const LMatrix4d &mat)
Applies the indicated transformation to the node and all of its descendants.
Definition eggNode.I:253
A single polygon.
Definition eggPolygon.h:24
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it.
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
void set_pos(double pos)
Sets the vertex position.
Definition eggVertex.I:42
void write_egg_file()
Writes out the egg file as the normal result of the program.
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
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.