~ubuntu-branches/ubuntu/intrepid/blender/intrepid-updates

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-08-08 02:45:40 UTC
  • mfrom: (12.1.14 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080808024540-kkjp7ekfivzhuw3l
Tags: 2.46+dfsg-4
* Fix python syntax warning in import_dxf.py, which led to nasty output
  in installation/upgrade logs during byte-compilation, using a patch
  provided by the script author (Closes: #492280):
   - debian/patches/45_fix_python_syntax_warning

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//------------------------------------------------------------------------------
 
2
// Base Primitive class
 
3
//------------------------------------------------------------------------------
 
4
 
 
5
#include "Primitive.h"
 
6
#include "State.h"
 
7
#include "Mathutil.h"
 
8
#include "MicroPolygonGrid.h"
 
9
#include "Framework.h"
 
10
 
 
11
#include "QDRender.h"
 
12
__BEGIN_QDRENDER
 
13
 
 
14
//------------------------------------------------------------------------------
 
15
// PrimVars
 
16
 
 
17
PrimVars::PrimVars() : refc(1)
 
18
{
 
19
}
 
20
 
 
21
PrimVars::~PrimVars()
 
22
{
 
23
        vardata_t** vdt = pvars.first();
 
24
        while (vdt) {
 
25
                delete *vdt;
 
26
                vdt = pvars.next();
 
27
        }
 
28
}
 
29
 
 
30
//------------------------------------------------------------------------------
 
31
// Primitive
 
32
 
 
33
Primitive& Primitive::operator=(const Primitive& p)
 
34
{
 
35
        std_pvar = p.std_pvar;
 
36
        std_dice = p.std_dice;
 
37
        attr = p.attr;
 
38
        xform = p.xform;
 
39
        eye_splits = p.eye_splits;
 
40
        primvars = p.primvars;
 
41
        if (primvars) primvars->incRefCount(); // !!!
 
42
        return *this;
 
43
}
 
44
 
 
45
Primitive::~Primitive()
 
46
{
 
47
        // !!! do not delete attr/xform !!!
 
48
        // delete primvars when no longer referenced
 
49
        if (primvars && primvars->decRefCount()==0) {
 
50
                delete primvars;
 
51
                primvars = NULL;
 
52
        }
 
53
}
 
54
 
 
55
void Primitive::initPrimVars(RtInt n, RtToken tokens[], RtPointer parms[],
 
56
                                int uniformMax, int varyingMax, int vertexMax, int faceVaryingMax)
 
57
{
 
58
        if (n == 0) return; // no params
 
59
        // current transform, not known yet (this function is only called from geom.ctor's)
 
60
        // so have to get from State
 
61
        const Transform xf = State::Instance()->currentTransform();
 
62
        // normal transform
 
63
        Transform nxf = xf;
 
64
        nxf.invert().transpose();
 
65
        char inline_name[256] = {0};
 
66
        for (int i=0; i<n; i++) {
 
67
                if ((!strcmp(tokens[i], RI_P)) ||
 
68
                    (!strcmp(tokens[i], RI_PZ)) ||
 
69
                    (!strcmp(tokens[i], RI_PW)))
 
70
                        continue; // "P" and variants already handled in geom code
 
71
                decParam_t dp = {0, 0, 0};
 
72
                if (!State::Instance()->parameterFromName(tokens[i], dp, inline_name, true)) {
 
73
                        // inline parse error (errmsg already handled in parameterFromName())
 
74
                        continue;
 
75
                }
 
76
                // string variables are in fact legal (though always constant),
 
77
                // but let's just pretend we don't know that...
 
78
                if (dp.ct_flags & DT_STRING) {
 
79
                        printf("[ERROR]: primitive variables of type 'string' are not supported (yet), skipping...\n");
 
80
                        continue;
 
81
                }
 
82
                unsigned int lenmult = 1;
 
83
                if (dp.ct_flags & DT_FLOAT3MASK) // point/vector/normal/color
 
84
                        lenmult = 3;
 
85
                else if (dp.ct_flags & DT_MATRIX)
 
86
                        lenmult = 16;
 
87
                else if ((dp.ct_flags & DT_FLOAT)==0) {
 
88
                        printf("[ERROR]: Unexpected primitive variable data type of '%d' ( '%s' ), skipping...\n", dp.ct_flags, tokens[i]);
 
89
                        continue;
 
90
                }
 
91
                // type 'constant' is always 1
 
92
                dp.numfloats = dp.arlen * lenmult;
 
93
                if (dp.ct_flags & SC_UNIFORM)
 
94
                        dp.numfloats = dp.arlen * uniformMax * lenmult;
 
95
                else if (dp.ct_flags & SC_VARYING)
 
96
                        dp.numfloats = dp.arlen * varyingMax * lenmult;
 
97
                else if (dp.ct_flags & SC_FACEVARYING)
 
98
                        dp.numfloats = dp.arlen * faceVaryingMax * lenmult;
 
99
                else if (dp.ct_flags & SC_VERTEX)
 
100
                        dp.numfloats = dp.arlen * vertexMax * lenmult;
 
101
                // new variable, copy ri array
 
102
                vardata_t* vdt = new vardata_t(dp, new float[dp.numfloats]);
 
103
                memcpy(vdt->data, parms[i], sizeof(float)*dp.numfloats);
 
104
                // transform to current space if necessary
 
105
                if (dp.ct_flags & DT_POINT) {
 
106
                        RtPoint* pa = reinterpret_cast<RtPoint*>(vdt->data);
 
107
                        for (int j=0; j<(dp.numfloats / 3); ++j)
 
108
                                mulPMP(pa[j], *xf.getRtMatrixPtr(), pa[j]);
 
109
                }
 
110
                else if (dp.ct_flags & DT_VECTOR) {
 
111
                        RtVector* va = reinterpret_cast<RtVector*>(vdt->data);
 
112
                        for (int j=0; j<(dp.numfloats / 3); ++j)
 
113
                                mulVMV(va[j], *xf.getRtMatrixPtr(), va[j]);
 
114
                }
 
115
                else if (dp.ct_flags & DT_NORMAL) {
 
116
                        RtNormal* na = reinterpret_cast<RtNormal*>(vdt->data);
 
117
                        for (int j=0; j<(dp.numfloats / 3); ++j)
 
118
                                mulVMV(na[j], *nxf.getRtMatrixPtr(), na[j]); // can use vector multiply here, mulNMN() is not optimized
 
119
                }
 
120
                else if (dp.ct_flags & DT_MATRIX) {
 
121
                        RtMatrix* ma = reinterpret_cast<RtMatrix*>(vdt->data);
 
122
                        for (int j=0; j<(dp.numfloats / 16); ++j)
 
123
                                mulMMM(ma[j], *xf.getRtMatrixPtr(), ma[j]);
 
124
                }
 
125
                const char* varname = (inline_name[0] == 0) ? tokens[i] : inline_name;
 
126
                // if global variable, set corresponding bit in std_pvar
 
127
                unsigned int sa_idx = 0;
 
128
                while (_sl_access[sa_idx].name) {
 
129
                        if (!strcmp(_sl_access[sa_idx].name, varname)) {
 
130
                                std_pvar |= (1 << sa_idx);
 
131
                                break;
 
132
                        }
 
133
                        ++sa_idx;
 
134
                }
 
135
                // 'primvars' only created once, duplicates get reference
 
136
                if (primvars == NULL) primvars = new PrimVars();
 
137
                primvars->pvars.insert(varname, vdt);
 
138
        }
 
139
}
 
140
 
 
141
 
 
142
PrimVars* Primitive::newPrimVars()
 
143
{
 
144
        if (primvars) primvars->decRefCount(); // !!!
 
145
        primvars = new PrimVars();
 
146
        return primvars;
 
147
}
 
148
 
 
149
void Primitive::removePrimVar(const char* name)
 
150
{
 
151
        if (primvars) {
 
152
                vardata_t* vdt = NULL;
 
153
                primvars->pvars.remove(name, vdt);
 
154
                if (vdt) delete vdt;
 
155
        }
 
156
}
 
157
 
 
158
//------------------------------------------------------------------------------
 
159
// Generic dice for linear interpolation of primitive/shader variables
 
160
 
 
161
void Primitive::linear_dice(MicroPolygonGrid &g)
 
162
{
 
163
        if (primvars) {
 
164
                vardata_t** vdt = primvars->pvars.first();
 
165
                if (vdt == NULL) return; // nothing in list
 
166
                float u, v;
 
167
                unsigned int ug, vg, idx = 0;
 
168
                const unsigned int xdim = g.get_xdim(), ydim = g.get_ydim(), nverts = g.get_nverts();
 
169
                float uvl[4];
 
170
                get_uvlim(uvl);
 
171
                const float ud = uvl[1] - uvl[0], vd = uvl[3] - uvl[2];
 
172
                const float du = 1.f/float(xdim), dv = 1.f/float(ydim);
 
173
                while (vdt) {
 
174
                        bool varying = (((*vdt)->param.ct_flags & (SC_VARYING | SC_FACEVARYING | SC_VERTEX)) != 0);
 
175
                        const char* name = primvars->pvars.getName();
 
176
                        if ((*vdt)->param.ct_flags & DT_FLOAT) {
 
177
                                RtFloat* Fgrid = g.findVariable(name);
 
178
                                if (Fgrid == NULL)      // user defined variable, add a new variable and dice
 
179
                                        Fgrid = g.addVariable(name, 1);
 
180
                                const RtFloat* da = (RtFloat*)(*vdt)->data;
 
181
                                if (varying) {
 
182
                                        idx = 0;
 
183
                                        for (vg=0, v=0.f; vg<=ydim; ++vg, v+=dv)
 
184
                                                for (ug=0, u=0.f; ug<=xdim; ++ug, u+=du, ++idx)
 
185
                                                        bilerpF(Fgrid[idx], uvl[0] + u*ud, uvl[2] + v*vd, da[0], da[1], da[2], da[3]);
 
186
                                }
 
187
                                else { // uniform/constant
 
188
                                        for (idx=0; idx<nverts; ++idx)
 
189
                                                Fgrid[idx] = da[0];
 
190
                                }
 
191
                        }
 
192
                        else if ((*vdt)->param.ct_flags & DT_FLOAT3MASK) {
 
193
                                // point/vector/normal/color
 
194
                                RtVector* Vgrid = (RtVector*)g.findVariable(name);
 
195
                                if (Vgrid == NULL)      // user defined variable, add a new variable and dice
 
196
                                        Vgrid = (RtVector*)g.addVariable(name, 3);
 
197
                                const RtVector* da = (RtVector*)(*vdt)->data;
 
198
                                if (varying) {
 
199
                                        idx = 0;
 
200
                                        for (vg=0, v=0.f; vg<=ydim; ++vg, v+=dv)
 
201
                                                for (ug=0, u=0.f; ug<=xdim; ++ug, u+=du, ++idx)
 
202
                                                        bilerp(Vgrid[idx], uvl[0] + u*ud, uvl[2] + v*vd, da[0], da[1], da[2], da[3]);
 
203
                                }
 
204
                                else { // uniform/constant
 
205
                                        for (idx=0; idx<nverts; ++idx)
 
206
                                                Vgrid[idx][0] = da[0][0], Vgrid[idx][1] = da[0][1], Vgrid[idx][2] = da[0][2];
 
207
                                }
 
208
                        }
 
209
                        // matrix/hpoint TODO
 
210
                        // next variable
 
211
                        vdt = primvars->pvars.next();
 
212
                }
 
213
        }
 
214
}
 
215
 
 
216
//------------------------------------------------------------------------------
 
217
// BlurredPrimitive
 
218
// split & dice params of first prim MUST be used for all others!
 
219
 
 
220
BlurredPrimitive::BlurredPrimitive()
 
221
{
 
222
        const Options& opts = State::Instance()->topOptions();
 
223
        shmin = opts.openShutter, shmax = opts.closeShutter;
 
224
}
 
225
 
 
226
BlurredPrimitive::BlurredPrimitive(const BlurredPrimitive& bp) : Primitive()    // init base
 
227
{
 
228
        // copy base prim data
 
229
        static_cast<Primitive&>(*this) = bp;
 
230
        // assuming copy ctor is called because of split(), poses array therefore not copied here, gets new ones
 
231
        motion_xform = bp.motion_xform;
 
232
        shmin = bp.shmin, shmax = bp.shmax;
 
233
}
 
234
 
 
235
BlurredPrimitive::~BlurredPrimitive()
 
236
{
 
237
        for (std::vector<Primitive*>::iterator ai=poses.begin(); ai!=poses.end(); ++ai)
 
238
                delete *ai;
 
239
        poses.clear();
 
240
}
 
241
 
 
242
void BlurredPrimitive::post_init()
 
243
{
 
244
        for (std::vector<Primitive*>::iterator ai=poses.begin(); ai!=poses.end(); ++ai)
 
245
                (*ai)->post_init();
 
246
}
 
247
 
 
248
bool BlurredPrimitive::in_camspace() const
 
249
{
 
250
        if (poses.empty()) return false;
 
251
        return poses[0]->in_camspace();
 
252
}
 
253
 
 
254
bool BlurredPrimitive::boundable()
 
255
{
 
256
        if (poses.empty()) return false;
 
257
        return poses[0]->boundable();
 
258
}
 
259
 
 
260
Bound BlurredPrimitive::bound()
 
261
{
 
262
        if (poses.empty()) return Bound();
 
263
        // combined bound of all primitives
 
264
        Bound b;
 
265
        if (!motion_xform.empty()) {
 
266
                // include transformational mblur
 
267
                Bound tb = poses[0]->bound();
 
268
                tb.transform(&motion_xform[0]);
 
269
                b.include(tb);
 
270
                if (motion_xform.size() == 2) {
 
271
                        if (poses.size() == 2)
 
272
                                tb = poses[1]->bound();
 
273
                        else
 
274
                                tb = poses[0]->bound();
 
275
                        tb.transform(&motion_xform[1]);
 
276
                        b.include(tb);
 
277
                }
 
278
        }
 
279
        else {
 
280
                // poses only
 
281
                for (std::vector<Primitive*>::iterator ai=poses.begin(); ai!=poses.end(); ++ai)
 
282
                        b.include((*ai)->bound());
 
283
        }
 
284
        return b;
 
285
}
 
286
 
 
287
bool BlurredPrimitive::splitable()
 
288
{
 
289
        if (poses.empty()) return false;
 
290
        return poses[0]->splitable();
 
291
}
 
292
 
 
293
// split the blurred primitive(s).
 
294
// This is done by calling the split() func. of each prim in the poses array,
 
295
// using a struct containing the parent BlurredPrimitive and an array, initially empty, which will contain the new split prims.
 
296
// The split function of the underlying primitive then is responsible for creating new BlurredPrimitive(s),
 
297
// and/or appending new copies of the split base primitive.
 
298
// First split() call will create and append, following calls will only append to created bprims in first call.
 
299
// The splitbprims arg here in this function has no meaning.
 
300
void BlurredPrimitive::split(const Framework &f, bool usplit, bool vsplit, splitbprims_t* spb)
 
301
{
 
302
        if (!poses.empty()) {
 
303
                // all primitives must be split with the same parameters
 
304
                splitbprims_t splitbprims;
 
305
                splitbprims.parent = this;
 
306
                for (std::vector<Primitive*>::iterator pose=poses.begin(); pose!=poses.end(); ++pose)
 
307
                        (*pose)->split(f, usplit, vsplit, &splitbprims);
 
308
                // if any created, bprim(s) can now be inserted into framework
 
309
                for (array_t<BlurredPrimitive*>::iterator bi=splitbprims.bprims.begin(); bi!=splitbprims.bprims.end(); ++bi)
 
310
                        f.insert(*bi);
 
311
        }
 
312
}
 
313
 
 
314
bool BlurredPrimitive::diceable(MicroPolygonGrid &g, Hider &h, bool &usplit, bool &vsplit)
 
315
{
 
316
        if (poses.empty()) return false;
 
317
        return poses[0]->diceable(g, h, usplit, vsplit);
 
318
}
 
319
 
 
320
// Pclose arg has no meaning here
 
321
void BlurredPrimitive::dice(MicroPolygonGrid &g, bool Pclose)
 
322
{
 
323
        if (!poses.empty()) {
 
324
                const unsigned int nverts = g.get_nverts();
 
325
                // all primitives must be diced exactly the same
 
326
                if (poses.size() == 2) {
 
327
                        // more than one primitive
 
328
                        poses[0]->dice(g);
 
329
                        // dice shutter close time, dices to '=Pclose' grid (this is the only dice() call in the program where Pclose arg is used)
 
330
                        poses[1]->dice(g, true);
 
331
                        if (motion_xform.size() == 2) {
 
332
                                // transform needed as well
 
333
                                // since this is always done for all grids, this can be extremely expensive, especially camera blur...
 
334
                                // even small shutter times then hardly have any impact on rendertimes.
 
335
                                // Possible solution would be to concatenate transforms for the base prims, so pre-transform would be possible,
 
336
                                // but then memory might be a problem, since re-use of transforms would not happen very often anymore probably... TODO
 
337
                                RtPoint* P_grid = (RtPoint*)g.findVariable("P");
 
338
                                const RtMatrix* mtx0 = motion_xform[0].getRtMatrixPtr();
 
339
                                for (unsigned int i=0; i<nverts; ++i)
 
340
                                        mulPMP(P_grid[i], *mtx0, P_grid[i]);
 
341
                                RtPoint* ePclose_grid = (RtPoint*)g.findVariable("=Pclose");
 
342
                                const RtMatrix* mtx1 = motion_xform[1].getRtMatrixPtr();
 
343
                                for (unsigned int i=0; i<nverts; ++i)
 
344
                                        mulPMP(ePclose_grid[i], *mtx1, ePclose_grid[i]);
 
345
                        }
 
346
                }
 
347
                else if ((poses.size() == 1) && !motion_xform.empty()) {
 
348
                        // single blurred primitive, transform only
 
349
                        poses[0]->dice(g);
 
350
                        RtPoint* P_grid = (RtPoint*)g.findVariable("P");
 
351
                        // since only 'P' diced, add '=Pclose' grid here
 
352
                        RtPoint* ePclose_grid = (RtPoint*)g.addVariable("=Pclose");
 
353
                        const RtMatrix* mtx1 = motion_xform[1].getRtMatrixPtr();
 
354
                        for (unsigned int i=0; i<nverts; ++i)
 
355
                                mulPMP(ePclose_grid[i], *mtx1, P_grid[i]);
 
356
                        // transform orig. P to first motion xform
 
357
                        const RtMatrix* mtx0 = motion_xform[0].getRtMatrixPtr();
 
358
                        for (unsigned int i=0; i<nverts; ++i)
 
359
                                mulPMP(P_grid[i], *mtx0, P_grid[i]);
 
360
                }
 
361
        }
 
362
}
 
363
 
 
364
void BlurredPrimitive::append(Primitive* p)
 
365
{
 
366
        // for now, not more than two primitives, more shutter key times TODO
 
367
        if (poses.size() < 2)
 
368
                poses.push_back(p);
 
369
        else
 
370
                printf("[WARNING]: BlurredPrimitive::append() -> already have two prims\n");
 
371
}
 
372
 
 
373
__END_QDRENDER