Panda3D
Loading...
Searching...
No Matches
eggNurbsSurface.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 eggNurbsSurface.cxx
10 * @author drose
11 * @date 2000-02-15
12 */
13
14#include "eggNurbsSurface.h"
15
16#include "indent.h"
17
18TypeHandle EggNurbsSurface::_type_handle;
19
20/**
21 * Makes a copy of this object.
22 */
24make_copy() const {
25 return new EggNurbsSurface(*this);
26}
27
28/**
29 * Prepares a new surface definition with the indicated order and number of
30 * knots in each dimension. This also implies a particular number of vertices
31 * in each dimension as well (the number of knots minus the order), but it is
32 * up to the user to add the correct number of vertices to the surface by
33 * repeatedly calling push_back().
34 */
36setup(int u_order, int v_order,
37 int num_u_knots, int num_v_knots) {
38 _u_order = u_order;
39 _v_order = v_order;
40 _u_knots.clear();
41 _v_knots.clear();
42
43 int i;
44 _u_knots.reserve(num_u_knots);
45 for (i = 0; i < num_u_knots; i++) {
46 _u_knots.push_back((double)i);
47 }
48 _v_knots.reserve(num_v_knots);
49 for (i = 0; i < num_v_knots; i++) {
50 _v_knots.push_back((double)i);
51 }
52}
53
54/**
55 * Directly changes the number of knots in the U direction. This will either
56 * add zero-valued knots onto the end, or truncate knot values from the end,
57 * depending on whether the list is being increased or decreased. If
58 * possible, it is preferable to use the setup() method instead of directly
59 * setting the number of knots, as this may result in an invalid surface.
60 */
62set_num_u_knots(int num) {
63 if ((int)_u_knots.size() >= num) {
64 // Truncate knot values at the end.
65 _u_knots.erase(_u_knots.begin() + num, _u_knots.end());
66 } else {
67 // Append knot values to the end.
68 _u_knots.reserve(num);
69 for (int i = _u_knots.size(); i < num; i++) {
70 _u_knots.push_back(0.0);
71 }
72 }
73}
74
75/**
76 * Directly changes the number of knots in the V direction. This will either
77 * add zero-valued knots onto the end, or truncate knot values from the end,
78 * depending on whether the list is being increased or decreased. If
79 * possible, it is preferable to use the setup() method instead of directly
80 * setting the number of knots, as this may result in an invalid surface.
81 */
83set_num_v_knots(int num) {
84 if ((int)_v_knots.size() >= num) {
85 // Truncate knot values at the end.
86 _v_knots.erase(_v_knots.begin() + num, _v_knots.end());
87 } else {
88 // Append knot values to the end.
89 _v_knots.reserve(num);
90 for (int i = _v_knots.size(); i < num; i++) {
91 _v_knots.push_back(0.0);
92 }
93 }
94}
95
96/**
97 * Returns true if the NURBS parameters are all internally consistent (e.g.
98 * it has the right number of vertices to match its number of knots and order
99 * in each dimension), or false otherwise.
100 */
102is_valid() const {
103 if (_u_order < 1 || _u_order > 4 || _v_order < 1 || _v_order > 4) {
104 // Invalid order.
105 return false;
106 }
107
108 if (get_num_cvs() != (int)size()) {
109 // Wrong number of CV's.
110 return false;
111 }
112
113 // Do all the knot values monotonically increase?
114 int i;
115 for (i = 1; i < get_num_u_knots(); i++) {
116 if (get_u_knot(i) < get_u_knot(i - 1)) {
117 return false;
118 }
119 }
120 for (i = 1; i < get_num_v_knots(); i++) {
121 if (get_v_knot(i) < get_v_knot(i - 1)) {
122 return false;
123 }
124 }
125
126 // Everything's looking good!
127 return true;
128}
129
130/**
131 * Returns true if the surface appears to be closed in the U direction. Since
132 * the Egg syntax does not provide a means for explicit indication of closure,
133 * this has to be guessed at by examining the surface itself.
134 */
136is_closed_u() const {
137 // Technically, the surface is closed if the CV's at the end are repeated
138 // from the beginning. We'll do a cheesy test for expediency's sake: the
139 // surface is closed if the first n knots are not repeated. I think this
140 // will catch all the normal surfaces we're likely to see.
141
142 int i;
143 for (i = 1; i < get_u_order(); i++) {
144 if (get_u_knot(i) != get_u_knot(i-1)) {
145 return true;
146 }
147 }
148 return false;
149}
150
151/**
152 * Returns true if the surface appears to be closed in the V direction. Since
153 * the Egg syntax does not provide a means for explicit indication of closure,
154 * this has to be guessed at by examining the surface itself.
155 */
157is_closed_v() const {
158 int i;
159 for (i = 1; i < get_v_order(); i++) {
160 if (get_v_knot(i) != get_v_knot(i-1)) {
161 return true;
162 }
163 }
164 return false;
165}
166
167/**
168 * Writes the nurbsSurface to the indicated output stream in Egg format.
169 */
171write(std::ostream &out, int indent_level) const {
172 write_header(out, indent_level, "<NurbsSurface>");
173
174 Trims::const_iterator ti;
175 for (ti = _trims.begin(); ti != _trims.end(); ++ti) {
176 indent(out, indent_level + 2) << "<Trim> {\n";
177 Loops::const_iterator li;
178 for (li = (*ti).begin(); li != (*ti).end(); ++li) {
179 indent(out, indent_level + 4) << "<Loop> {\n";
180 Curves::const_iterator ci;
181 for (ci = (*li).begin(); ci != (*li).end(); ++ci) {
182 (*ci)->write(out, indent_level + 6);
183 }
184 indent(out, indent_level + 4) << "}\n";
185 }
186 indent(out, indent_level + 2) << "}\n";
187 }
188
189 if (get_u_subdiv() != 0) {
190 indent(out, indent_level + 2)
191 << "<Scalar> U-subdiv { " << get_u_subdiv() << " }\n";
192 }
193 if (get_v_subdiv() != 0) {
194 indent(out, indent_level + 2)
195 << "<Scalar> V-subdiv { " << get_v_subdiv() << " }\n";
196 }
197 indent(out, indent_level + 2)
198 << "<Order> { " << get_u_order() << " " << get_v_order() << " }\n";
199 indent(out, indent_level + 2)
200 << "<U-Knots> {\n";
201 write_long_list(out, indent_level+4, _u_knots.begin(), _u_knots.end(),
202 "", "", 72);
203 indent(out, indent_level + 2)
204 << "}\n";
205 indent(out, indent_level + 2)
206 << "<V-Knots> {\n";
207 write_long_list(out, indent_level+4, _v_knots.begin(), _v_knots.end(),
208 "", "", 72);
209 indent(out, indent_level + 2)
210 << "}\n";
211
212 write_body(out, indent_level+2);
213
214 Curves::const_iterator ci;
215 for (ci = _curves_on_surface.begin(); ci != _curves_on_surface.end(); ++ci) {
216 (*ci)->write(out, indent_level + 2);
217 }
218
219 indent(out, indent_level) << "}\n";
220}
221
222/**
223 * The recursive implementation of apply_texmats().
224 */
225void EggNurbsSurface::
226r_apply_texmats(EggTextureCollection &textures) {
227 // A NURBS cannot safely apply texture matrices, so we leave it alone.
228}
void write_header(std::ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
A parametric NURBS surface.
void setup(int u_order, int v_order, int num_u_knots, int num_v_knots)
Prepares a new surface definition with the indicated order and number of knots in each dimension.
void set_num_v_knots(int num)
Directly changes the number of knots in the V direction.
int get_u_order() const
Returns the order of the surface in the U direction.
int get_num_cvs() const
Returns the total number of control vertices that *should* be defined for the surface.
bool is_closed_u() const
Returns true if the surface appears to be closed in the U direction.
bool is_closed_v() const
Returns true if the surface appears to be closed in the V direction.
virtual EggNurbsSurface * make_copy() const override
Makes a copy of this object.
get_num_u_knots
Returns the number of knots in the U direction.
void set_num_u_knots(int num)
Directly changes the number of knots in the U direction.
int get_v_order() const
Returns the order of the surface in the V direction.
get_v_knot
Returns the nth knot value defined in the V direction.
bool is_valid() const
Returns true if the NURBS parameters are all internally consistent (e.g.
virtual void write(std::ostream &out, int indent_level) const override
Writes the nurbsSurface to the indicated output stream in Egg format.
get_u_knot
Returns the nth knot value defined in the U direction.
get_num_v_knots
Returns the number of knots in the V direction.
int get_v_subdiv() const
Returns the requested number of subdivisions in the U direction, or 0 if no particular subdivisions h...
Definition eggSurface.I:82
int get_u_subdiv() const
Returns the requested number of subdivisions in the U direction, or 0 if no particular subdivisions h...
Definition eggSurface.I:62
This is a collection of textures by TRef name.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void write_long_list(std::ostream &out, int indent_level, InputIterator ifirst, InputIterator ilast, std::string first_prefix="", std::string later_prefix="", int max_col=72)
Writes a list of things to the indicated output stream, with a space separating each item.
Definition indent.I:22