~ubuntu-branches/ubuntu/maverick/blender/maverick

« back to all changes in this revision

Viewing changes to extern/qdune/primitives/Quadrics.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Khashayar Naderehvandi, Khashayar Naderehvandi, Alessio Treglia
  • Date: 2009-01-22 16:53:59 UTC
  • mfrom: (14.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090122165359-v0996tn7fbit64ni
Tags: 2.48a+dfsg-1ubuntu1
[ Khashayar Naderehvandi ]
* Merge from debian experimental (LP: #320045), Ubuntu remaining changes:
  - Add patch correcting header file locations.
  - Add libvorbis-dev and libgsm1-dev to Build-Depends.
  - Use avcodec_decode_audio2() in source/blender/src/hddaudio.c

[ Alessio Treglia ]
* Add missing previous changelog entries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//-------------------------------------------
2
 
// The standard renderman quadric primitives
3
 
//-------------------------------------------
4
 
 
5
 
#include "Quadrics.h"
6
 
#include "Mathutil.h"
7
 
#include "State.h"
8
 
 
9
 
__BEGIN_QDRENDER
10
 
 
11
 
//------------------------------------------------------------------------------
12
 
// functions used for bound calculation
13
 
 
14
 
// 2D polar to cartesian
15
 
inline Point3 polar2D(float radius, float theta)
16
 
{
17
 
        return Point3(cosf(theta)*radius, sinf(theta)*radius, 0);
18
 
}
19
 
 
20
 
// parametric 2D bound calc.
21
 
inline Bound bounds2DSweepL(float rmin, float rmax, float tmin, float tmax)
22
 
{
23
 
        Bound b;
24
 
        b.include(polar2D(rmin, tmin));
25
 
        b.include(polar2D(rmax, tmin));
26
 
        b.include(polar2D(rmin, tmax));
27
 
        b.include(polar2D(rmax, tmax));
28
 
        if ((tmin < (float)M_PI_2) && (tmax > (float)M_PI_2)) b.include(polar2D(rmax, (float)M_PI_2));
29
 
        if ((tmin < (float)M_PI) && (tmax > (float)M_PI)) b.include(polar2D(rmax, (float)M_PI));
30
 
        if ((tmin < float(M_PI+M_PI_2)) && (tmax > float(M_PI+M_PI_2))) b.include(polar2D(rmax, float(M_PI+M_PI_2)));
31
 
        return b;
32
 
}
33
 
 
34
 
// only used by torus
35
 
inline Bound bounds2DSweepR(float r, float phimin, float phimax)
36
 
{
37
 
        Bound b;
38
 
        b.include(polar2D(r, phimin));
39
 
        b.include(polar2D(r, phimax));
40
 
        for (int i=-3; i<4; i++) {
41
 
                const float ip = i*(float)M_PI_2;
42
 
                if ((phimin < ip) && (phimax > ip)) b.include(polar2D(r, ip));
43
 
        }
44
 
        return b;
45
 
}
46
 
 
47
 
// only used by hyperboloid
48
 
inline Bound bounds2DSweepP(const Point3 &P, float tmin, float tmax)
49
 
{
50
 
        Bound b;
51
 
        const float r = sqrt(P.x*P.x + P.y*P.y);
52
 
        const float delta = ((P.x==0.f) && (P.y==0.f)) ? 0.f : atan2f(P.y, P.x);
53
 
        tmin += delta;
54
 
        tmax += delta;
55
 
        b.include(polar2D(r, tmin));
56
 
        b.include(polar2D(r, tmax));
57
 
        // quadrant points
58
 
        for (int i=-1; i<6; i++) {
59
 
                const float ip = i*(float)M_PI_2;
60
 
                if ((tmin < ip) && (tmax > ip)) b.include(polar2D(r, ip));
61
 
        }
62
 
        return b;
63
 
}
64
 
 
65
 
//------------------------------------------------------------------------------
66
 
// Quadric primitives (including quartic torus)
67
 
// all angle values that specify the extent are clamped to (0, 360) range
68
 
 
69
 
//------------------------------------------------------------------------------
70
 
// Disk
71
 
 
72
 
Disk::Disk():height(1), radius(1), thetamax(2.f*(float)M_PI)
73
 
{
74
 
}
75
 
 
76
 
Disk::Disk(float _height, float _radius, float _thetamax,
77
 
                                        RtInt n, RtToken tokens[], RtPointer parms[])
78
 
                                        : height(_height), radius(_radius)
79
 
{
80
 
        radians(thetamax, CLAMP(ABS(_thetamax), 0.f, 360.f));
81
 
        Primitive::initPrimVars(n, tokens, parms, 1, 4, 4, 4);
82
 
}
83
 
 
84
 
Bound Disk::bound()
85
 
{
86
 
        Bound b = bounds2DSweepL(radius*(1.f-vmax), radius*(1.f-vmin), umin*thetamax, umax*thetamax);
87
 
        b.minmax[0].z = b.minmax[1].z = height;
88
 
        b.addEpsilon();
89
 
        b.transform(xform);
90
 
        return b;
91
 
}
92
 
 
93
 
void Disk::eval(float u, float v, RtPoint P, RtVector dPdu, RtVector dPdv) const
94
 
{
95
 
        const float t = u*thetamax;
96
 
        const float sint = sinf(t), cost = cosf(t);
97
 
        float r = radius*(1.f - v);
98
 
        P[0] = r*cost, P[1] = r*sint, P[2] = height;
99
 
        if (dPdu && dPdv) {
100
 
                r = radius*thetamax;
101
 
                dPdu[0] = -r*sint, dPdu[1] = r*cost, dPdu[2] = 0;
102
 
                dPdv[0] = -radius*cost, dPdv[1] = -radius*sint, dPdv[2] = 0;
103
 
        }
104
 
}
105
 
 
106
 
//------------------------------------------------------------------------------
107
 
// Sphere, uses reference counted data to test if that would improve
108
 
// memory usage, but probably can be removed.
109
 
// Probably doesn't help much, unless the sphere is split often.
110
 
 
111
 
Sphere::Sphere(float _radius, float _zmin, float _zmax, float _thetamax,
112
 
                                                        RtInt n, RtToken tokens[], RtPointer parms[])
113
 
{
114
 
        spdata = new spData();
115
 
        spdata->radius = _radius;
116
 
        // keep zmin/zmax within +/- radius range
117
 
        spdata->zmin = MAX2(-spdata->radius, _zmin);
118
 
        spdata->zmax = MIN2(spdata->radius, _zmax);
119
 
        if (spdata->radius<=0.f) spdata->radius = 1e-5f;
120
 
        radians(spdata->thetamax, CLAMP(ABS(_thetamax), 0.f, 360.f));
121
 
        spdata->alphamin = asinf(CLAMP(spdata->zmin/spdata->radius, -1.f, 1.f));
122
 
        spdata->alphadelta = asinf(CLAMP(spdata->zmax/spdata->radius, -1.f, 1.f)) - spdata->alphamin;
123
 
        Primitive::initPrimVars(n, tokens, parms, 1, 4, 4, 4);
124
 
}
125
 
 
126
 
Sphere::~Sphere()
127
 
{
128
 
        if (spdata && (--spdata->refc == 0)) {
129
 
                delete spdata;
130
 
                spdata = NULL;
131
 
        }
132
 
}
133
 
 
134
 
Bound Sphere::bound()
135
 
{
136
 
        const float avmin = spdata->alphamin + vmin*spdata->alphadelta;
137
 
        const float avmax = spdata->alphamin + vmax*spdata->alphadelta;
138
 
        const float rvmin = cosf(avmin)*spdata->radius;
139
 
        const float rvmax = cosf(avmax)*spdata->radius;
140
 
        const float rmin = MIN2(rvmin, rvmax);
141
 
        const float rmax = ((avmin<0.f) && (avmax>0.f)) ? spdata->radius : (MAX2(rvmin, rvmax));
142
 
        Bound b = bounds2DSweepL(rmin, rmax, umin*spdata->thetamax, umax*spdata->thetamax);
143
 
        b.minmax[0].z = sinf(avmin)*spdata->radius;
144
 
        b.minmax[1].z = sinf(avmax)*spdata->radius;
145
 
        b.addEpsilon();
146
 
        b.transform(xform);
147
 
        return b;
148
 
}
149
 
 
150
 
void Sphere::eval(float u, float v, RtPoint P, RtVector dPdu, RtVector dPdv) const
151
 
{
152
 
        // correction for singularity at poles (only needed for correct normals, probably precision issue, get correct results for 0,0 in py)
153
 
        u = MAX2(1e-6f, u), v = MAX2(1e-6f, v);
154
 
        const float alpha = spdata->alphamin + v*spdata->alphadelta;
155
 
        const float car = cosf(alpha)*spdata->radius, t = u*spdata->thetamax;
156
 
        const float sint = sinf(t), cost = cosf(t), sina = sinf(alpha);
157
 
        P[0] = cost*car, P[1] = sint*car, P[2] = sina*spdata->radius;
158
 
        if (dPdu && dPdv) {
159
 
                dPdu[0] = -spdata->thetamax*sint*car, dPdu[1] = spdata->thetamax*cost*car, dPdu[2] = 0;
160
 
                const float ar = spdata->alphadelta*spdata->radius;
161
 
                const float sar = -sina*ar;
162
 
                dPdv[0] = cost*sar, dPdv[1] = sint*sar, dPdv[2] = cosf(alpha)*ar;
163
 
        }
164
 
}
165
 
 
166
 
Parametric* Sphere::duplicateSelf()
167
 
{
168
 
        Sphere* sp = new Sphere(*this);
169
 
        if (spdata) spdata->refc++;
170
 
        return sp;
171
 
}
172
 
 
173
 
//------------------------------------------------------------------------------
174
 
// Cylinder
175
 
 
176
 
Cylinder::Cylinder(): radius(1), zmin(-1), zmax(1), thetamax(2.f*(float)M_PI)
177
 
{
178
 
}
179
 
 
180
 
Cylinder::Cylinder(float _radius, float _zmin, float _zmax, float _thetamax,
181
 
                                                                        RtInt n, RtToken tokens[], RtPointer parms[])
182
 
                                                                        : radius(_radius), zmin(_zmin), zmax(_zmax)
183
 
{
184
 
        radians(thetamax, CLAMP(ABS(_thetamax), 0.f, 360.f));
185
 
        Primitive::initPrimVars(n, tokens, parms, 1, 4, 4, 4);
186
 
}
187
 
 
188
 
Bound Cylinder::bound()
189
 
{
190
 
        Bound b = bounds2DSweepL(radius, radius, umin*thetamax, umax*thetamax);
191
 
        b.minmax[0].z = zmin + vmin*(zmax-zmin);
192
 
        b.minmax[1].z = zmin + vmax*(zmax-zmin);
193
 
        b.addEpsilon();
194
 
        b.transform(xform);
195
 
        return b;
196
 
}
197
 
 
198
 
void Cylinder::eval(float u, float v, RtPoint P, RtVector dPdu, RtVector dPdv) const
199
 
{
200
 
        const float t = u*thetamax;
201
 
        const float sint = sinf(t), cost = cosf(t);
202
 
        if (dPdu && dPdv) {
203
 
                const float tr = thetamax*radius;
204
 
                dPdu[0] = -sint*tr, dPdu[1] = cost*tr;
205
 
                dPdu[2] = dPdv[0] = dPdv[1] = 0, dPdv[2] = zmax - zmin;
206
 
                P[0] = cost*radius, P[1] = sint*radius, P[2] = zmin + v*dPdv[2];
207
 
                return;
208
 
        }
209
 
        P[0] = cost*radius, P[1] = sint*radius, P[2] = zmin + v*(zmax - zmin);
210
 
}
211
 
 
212
 
//------------------------------------------------------------------------------
213
 
// Cone
214
 
 
215
 
Cone::Cone(): height(1), radius(1), thetamax(2.f*(float)M_PI)
216
 
{
217
 
}
218
 
 
219
 
Cone::Cone(float _height, float _radius, float _thetamax,
220
 
                                        RtInt n, RtToken tokens[], RtPointer parms[])
221
 
                                        : height(_height), radius(_radius)
222
 
{
223
 
        radians(thetamax, CLAMP(ABS(_thetamax), 0.f, 360.f));
224
 
        Primitive::initPrimVars(n, tokens, parms, 1, 4, 4, 4);
225
 
}
226
 
 
227
 
Bound Cone::bound()
228
 
{
229
 
        Bound b = bounds2DSweepL(radius*(1.f-vmax), radius*(1.f-vmin), umin*thetamax, umax*thetamax);
230
 
        b.minmax[0].z = vmin*height;
231
 
        b.minmax[1].z = vmax*height;
232
 
        b.addEpsilon();
233
 
        b.transform(xform);
234
 
        return b;
235
 
}
236
 
 
237
 
void Cone::eval(float u, float v, RtPoint P, RtVector dPdu, RtVector dPdv) const
238
 
{
239
 
        const float t = u*thetamax, rv = radius*(1.f - v);
240
 
        const float sint = sinf(t), cost = cosf(t);
241
 
        P[0] = cost*rv, P[1] = sint*rv, P[2] = v*height;
242
 
        if (dPdu && dPdv) {
243
 
                const float tr = thetamax*radius*(1.f - v);
244
 
                dPdu[0] = -sint*tr, dPdu[1] = cost*tr, dPdu[2] = 0;
245
 
                dPdv[0] = -cost*radius, dPdv[1] = -sint*radius, dPdv[2] = height;
246
 
        }
247
 
}
248
 
 
249
 
//------------------------------------------------------------------------------
250
 
// Paraboloid
251
 
 
252
 
Paraboloid::Paraboloid(): scale(1), rmax(1), zmin(0), zmax(1), thetamax(2.f*(float)M_PI)
253
 
{
254
 
}
255
 
 
256
 
Paraboloid::Paraboloid(float _rmax, float _zmin, float _zmax, float _thetamax,
257
 
                                                                                        RtInt n, RtToken tokens[], RtPointer parms[])
258
 
{
259
 
        rmax = _rmax;
260
 
        // zmin cannot be negative in this case
261
 
        zmin = (_zmin<0.f) ? 0.f : _zmin;
262
 
        zmax = (_zmax<0.f) ? 0.f : _zmax;
263
 
        scale = rmax;
264
 
        if (zmax!=0.f) scale /= sqrt(zmax);
265
 
        radians(thetamax, CLAMP(ABS(_thetamax), 0.f, 360.f));
266
 
        Primitive::initPrimVars(n, tokens, parms, 1, 4, 4, 4);
267
 
}
268
 
 
269
 
Bound Paraboloid::bound()
270
 
{
271
 
        const float z1 = zmin + vmin*(zmax-zmin);
272
 
        const float z2 = zmin + vmax*(zmax-zmin);
273
 
        Bound b = bounds2DSweepL(sqrt(z1)*scale, sqrt(z2)*scale, umin*thetamax, umax*thetamax);
274
 
        b.minmax[0].z = z1;
275
 
        b.minmax[1].z = z2;
276
 
        b.addEpsilon();
277
 
        b.transform(xform);
278
 
        return b;
279
 
}
280
 
 
281
 
void Paraboloid::eval(float u, float v, RtPoint P, RtVector dPdu, RtVector dPdv) const
282
 
{
283
 
        const float t = u*thetamax;
284
 
        const float sint = sinf(t), cost = cosf(t);
285
 
        const float dz = zmax - zmin;
286
 
        const float z = zmin + v*dz;
287
 
        const float x = sqrt(z)*scale;
288
 
        P[0] = x*cost, P[1] = x*sint, P[2] = z;
289
 
        if (dPdu && dPdv) {
290
 
                float zt = sqrt(z);
291
 
                const float xt = zt*scale*thetamax;
292
 
                dPdu[0] = -xt*sint, dPdu[1] = xt*cost, dPdu[2] = 0;
293
 
                if (zt>0.f) zt = 1.f/zt;
294
 
                const float dx = (0.5f*dz*zt)*scale;
295
 
                dPdv[0] = dx*cost, dPdv[1] = dx*sint, dPdv[2] = dz;
296
 
        }
297
 
}
298
 
 
299
 
//------------------------------------------------------------------------------
300
 
// Hyperboloid
301
 
 
302
 
Hyperboloid::Hyperboloid(): p1(-1,1,0), p2(1,-1,0), thetamax(2.f*(float)M_PI)
303
 
{
304
 
}
305
 
 
306
 
Hyperboloid::Hyperboloid(const Point3 &_point1, const Point3 &_point2, float _thetamax,
307
 
                                                                                                RtInt n, RtToken tokens[], RtPointer parms[])
308
 
                                                                                                : p1(_point1), p2(_point2)
309
 
{
310
 
        radians(thetamax, CLAMP(ABS(_thetamax), 0.f, 360.f));
311
 
        Primitive::initPrimVars(n, tokens, parms, 1, 4, 4, 4);
312
 
}
313
 
 
314
 
Bound Hyperboloid::bound()
315
 
{
316
 
        Point3 pMin = p1 + (p2 - p1)*vmin, pMax = p1 + (p2 - p1)*vmax;
317
 
        const float ut1 = umin*thetamax, ut2 = umax*thetamax;
318
 
        Bound b = bounds2DSweepP(pMin, ut1, ut2);
319
 
        b.include(bounds2DSweepP(pMax, ut1, ut2));
320
 
        b.minmax[0].z = MIN2(pMin.z, pMax.z);
321
 
        b.minmax[1].z = MAX2(pMin.z, pMax.z);
322
 
        b.addEpsilon();
323
 
        b.transform(xform);
324
 
        return b;
325
 
}
326
 
 
327
 
void Hyperboloid::eval(float u, float v, RtPoint P, RtVector dPdu, RtVector dPdv) const
328
 
{
329
 
        const float x = p1.x + (p2.x - p1.x)*v;
330
 
        const float y = p1.y + (p2.y - p1.y)*v;
331
 
        const float t = u*thetamax;
332
 
        const float sint = sinf(t), cost = cosf(t);
333
 
        const float dx = p2.x-p1.x, dy = p2.y-p1.y,  dz = p2.z-p1.z;;
334
 
        P[0] = x*cost - y*sint, P[1] = x*sint + y*cost, P[2] = p1.z + dz*v;
335
 
        if (dPdu && dPdv) {
336
 
                const float xt = thetamax*(p1.x + dx*v), yt = thetamax*(p1.y + dy*v);
337
 
                dPdu[0] = -xt*sint - yt*cost, dPdu[1] = xt*cost - yt*sint, dPdu[2] = 0;
338
 
                dPdv[0] = dx*cost - dy*sint, dPdv[1] = dx*sint + dy*cost, dPdv[2] = dz;
339
 
        }
340
 
}
341
 
 
342
 
//------------------------------------------------------------------------------
343
 
// Torus
344
 
 
345
 
Torus::Torus(): majrad(1), minrad(0.25), phimin(0), phimax(2.f*(float)M_PI), thetamax(2.f*(float)M_PI)
346
 
{
347
 
}
348
 
 
349
 
Torus::Torus(float _majrad, float _minrad, float _phimin, float _phimax, float _thetamax,
350
 
                                                RtInt n, RtToken tokens[], RtPointer parms[])
351
 
                                                : majrad(_majrad), minrad(_minrad)
352
 
{
353
 
        radians(phimin, CLAMP(ABS(_phimin), 0.f, 360.f));
354
 
        radians(phimax, CLAMP(ABS(_phimax), 0.f, 360.f));
355
 
        radians(thetamax, CLAMP(ABS(_thetamax), 0.f, 360.f));
356
 
        Primitive::initPrimVars(n, tokens, parms, 1, 4, 4, 4);
357
 
}
358
 
 
359
 
Bound Torus::bound()
360
 
{
361
 
        const float myPhimin = vmin*(phimax - phimin) + phimin;
362
 
        const float myPhimax = vmax*(phimax - phimin) + phimin;
363
 
        Bound a = bounds2DSweepR(minrad, myPhimin, myPhimax);
364
 
        const float rmin = a.minmax[0].x + majrad;
365
 
        const float rmax = a.minmax[1].x + majrad;
366
 
        Bound b = bounds2DSweepL(rmin, rmax, umin*thetamax, umax*thetamax);
367
 
        b.minmax[0].z = a.minmax[0].y;
368
 
        b.minmax[1].z = a.minmax[1].y;
369
 
        b.addEpsilon();
370
 
        b.transform(xform);
371
 
        return b;
372
 
}
373
 
 
374
 
void Torus::eval(float u, float v, RtPoint P, RtVector dPdu, RtVector dPdv) const
375
 
{
376
 
        const float dphi = phimax - phimin;
377
 
        const float phi = v*dphi + phimin;
378
 
        const float sinp = sinf(phi), cosp = cosf(phi);
379
 
        const float sx = cosp*minrad + majrad;
380
 
        const float t = u*thetamax;
381
 
        const float sint = sinf(t), cost = cosf(t);
382
 
        P[0] = sx*cost, P[1] = sx*sint, P[2] = sinp*minrad;
383
 
        if (dPdu && dPdv) {
384
 
                const float sxt = sx*thetamax;
385
 
                dPdu[0] = -sxt*sint, dPdu[1] = sxt*cost, dPdu[2] = 0;
386
 
                const float dsx = -dphi*sinp*minrad;
387
 
                dPdv[0] = dsx*cost, dPdv[1] = dsx*sint, dPdv[2] = dphi*cosp*minrad;
388
 
        }
389
 
}
390
 
 
391
 
__END_QDRENDER
392