nurb_norm.c
Go to the documentation of this file.
1 /* N U R B _ N O R M . C
3  *
4  * Copyright (c) 1991-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
21 /** @{ */
22 /** @file primitives/bspline/nurb_norm.c
23  *
24  * Calculate and return the normal of a surface given the U, V
25  * parametric values.
26  *
27  */
28 /** @} */
29
30 #include "common.h"
31
32 #include "bio.h"
33
34 #include "vmath.h"
35 #include "raytrace.h"
36 #include "nurb.h"
37
38
39 /**
40  * If the order of the surface is linear either direction than
41  * approximate it.
42  */
43 void
44 rt_nurb_s_norm(struct face_g_snurb *srf, fastf_t u, fastf_t v, fastf_t *norm)
45 {
46  struct face_g_snurb *usrf, *vsrf;
47  point_t uvec, vvec;
48  fastf_t p;
49  fastf_t se[4], ue[4], ve[4];
50  int i;
51
52  /* Case (linear, lienar) find the normal from the polygon */
53  if (srf->order[0] == 2 && srf->order[1] == 2) {
54  /* Find the correct span to get the normal */
55  rt_nurb_s_eval(srf, u, v, se);
56
57  p = 0.0;
58  for (i = 0; i < srf->u.k_size -1; i++) {
59  if (srf->u.knots[i] <= u
60  && u < srf->u.knots[i+1]) {
61  p = srf->u.knots[i];
62
63  if (ZERO(u - p))
64  p = srf->u.knots[i+1];
65  if (ZERO(u - p) && i > 1)
66  p = srf->u.knots[i-1];
67  }
68  }
69
70  rt_nurb_s_eval(srf, p, v, ue);
71
72  p = 0.0;
73  for (i = 0; i < srf->v.k_size -1; i++) {
74  if (srf->v.knots[i] < v
75  && !ZERO(srf->v.knots[i+1])) {
76  p = srf->v.knots[i];
77  if (ZERO(v - p))
78  p = srf->v.knots[i+1];
79  if (ZERO(v - p) && i > 1)
80  p = srf->v.knots[i-1];
81  }
82  }
83
84  rt_nurb_s_eval(srf, u, p, ve);
85
86  if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
87  ue[0] = ue[0] / ue[3];
88  ue[1] = ue[1] / ue[3];
89  ue[2] = ue[2] / ue[3];
90  ue[3] = ue[3] / ue[3];
91
92  ve[0] = ve[0] / ve[3];
93  ve[1] = ve[1] / ve[3];
94  ve[2] = ve[2] / ve[3];
95  ve[3] = ve[3] / ve[3];
96
97  }
98
99  VSUB2(uvec, se, ue);
100  VSUB2(vvec, se, ve);
101
102  VCROSS(norm, uvec, vvec);
103  VUNITIZE(norm);
104
105  return;
106
107  }
108  /* Case (linear, > linear) Use the linear direction to approximate
109  * the tangent to the surface
110  */
111  if (srf->order[0] == 2 && srf->order[1] > 2) {
112  rt_nurb_s_eval(srf, u, v, se);
113
114  p = 0.0;
115  for (i = 0; i < srf->u.k_size -1; i++) {
116  if (srf->u.knots[i] <= u
117  && u < srf->u.knots[i+1]) {
118  p = srf->u.knots[i];
119
120  if (ZERO(u - p))
121  p = srf->u.knots[i+1];
122  if (ZERO(u - p) && i > 1)
123  p = srf->u.knots[i-1];
124  }
125  }
126
127  rt_nurb_s_eval(srf, p, v, ue);
128
129  vsrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_COL);
130
131  rt_nurb_s_eval(vsrf, u, v, ve);
132
133  if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
134  fastf_t w, inv_w;
135
136  w = se[3];
137  inv_w = 1.0 / w;
138
139  ve[0] = (inv_w * ve[0]) -
140  ve[3] / (w * w) * se[0];
141  ve[1] = (inv_w * ve[1]) -
142  ve[3] / (w * w) * se[1];
143  ve[2] = (inv_w * ve[2]) -
144  ve[3] / (w * w) * se[2];
145
146  ue[0] = ue[0] / ue[3];
147  ue[1] = ue[1] / ue[3];
148  ue[2] = ue[2] / ue[3];
149  ue[3] = ue[3] / ue[3];
150
151  se[0] = se[0] / se[3];
152  se[1] = se[1] / se[3];
153  se[2] = se[2] / se[3];
154  se[3] = se[3] / se[3];
155  }
156
157  VSUB2(uvec, se, ue);
158
159  VCROSS(norm, uvec, ve);
160  VUNITIZE(norm);
161
162  rt_nurb_free_snurb(vsrf, (struct resource *)NULL);
163  return;
164  }
165  if (srf->order[1] == 2 && srf->order[0] > 2) {
166  rt_nurb_s_eval(srf, u, v, se);
167
168  p = 0.0;
169  for (i = 0; i < srf->v.k_size -1; i++) {
170  if (srf->v.knots[i] <= v
171  && v < srf->v.knots[i+1]) {
172  p = srf->v.knots[i];
173
174  if (ZERO(v - p))
175  p = srf->v.knots[i+1];
176  if (ZERO(v - p) && i > 1)
177  p = srf->v.knots[i-1];
178  }
179  }
180
181  rt_nurb_s_eval(srf, u, p, ve);
182
183  usrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_ROW);
184
185  rt_nurb_s_eval(usrf, u, v, ue);
186
187  if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
188  fastf_t w, inv_w;
189
190  w = se[3];
191  inv_w = 1.0 / w;
192
193  ue[0] = (inv_w * ue[0]) -
194  ue[3] / (w * w) * se[0];
195  ue[1] = (inv_w * ue[1]) -
196  ue[3] / (w * w) * se[1];
197  ue[2] = (inv_w * ue[2]) -
198  ue[3] / (w * w) * se[2];
199
200  ve[0] = ve[0] / ve[3];
201  ve[1] = ve[1] / ve[3];
202  ve[2] = ve[2] / ve[3];
203  ve[3] = ve[3] / ve[3];
204
205  se[0] = se[0] / se[3];
206  se[1] = se[1] / se[3];
207  se[2] = se[2] / se[3];
208  se[3] = se[3] / se[3];
209  }
210
211  VSUB2(vvec, se, ve);
212
213  VCROSS(norm, ue, vvec);
214  VUNITIZE(norm);
215
216  rt_nurb_free_snurb(usrf, (struct resource *)NULL);
217  return;
218  }
219
220  /* Case Non Rational (order > 2, order > 2) */
221  if (!RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
222
223  usrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_ROW);
224  vsrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_COL);
225
226  rt_nurb_s_eval(usrf, u, v, ue);
227  rt_nurb_s_eval(vsrf, u, v, ve);
228
229  VCROSS(norm, ue, ve);
230  VUNITIZE(norm);
231
232  rt_nurb_free_snurb(usrf, (struct resource *)NULL);
233  rt_nurb_free_snurb(vsrf, (struct resource *)NULL);
234
235  return;
236  }
237
238  /* Case Rational (order > 2, order > 2) */
239  if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
240  fastf_t w, inv_w;
241  vect_t unorm, vnorm;
242
243  rt_nurb_s_eval(srf, u, v, se);
244
245  usrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_ROW);
246  vsrf = (struct face_g_snurb *) rt_nurb_s_diff(srf, RT_NURB_SPLIT_COL);
247
248  rt_nurb_s_eval(usrf, u, v, ue);
249
250  rt_nurb_s_eval(vsrf, u, v, ve);
251
252  w = se[3];
253  inv_w = 1.0 / w;
254
255  for (i = 0; i < 3; i++) {
256  unorm[i] = (inv_w * ue[i]) -
257  ue[3] / (w*w) * se[i];
258  vnorm[i] = (inv_w * ve[i]) -
259  ve[3] / (w*w) * se[i];
260  }
261
262  VCROSS(norm, unorm, vnorm);
263  VUNITIZE(norm);
264
265  rt_nurb_free_snurb(usrf, (struct resource *)NULL);
266  rt_nurb_free_snurb(vsrf, (struct resource *)NULL);
267
268  return;
269  }
270  return;
271 }
272
273
274 /*
275  * Local Variables:
276  * mode: C
277  * tab-width: 8
278  * indent-tabs-mode: t
279  * c-file-style: "stroustrup"
280  * End:
281  * ex: shiftwidth=4 tabstop=8
282  */
void rt_nurb_free_snurb(struct face_g_snurb *srf, struct resource *res)
Definition: nurb_util.c:127