1
//----------------------------------------------------------------
4
// These are dealt with by converting them to bilinear patches.
5
// Mean value coordinates for interpolation (see ZbufferHider.cpp)
6
// would seem to be useful here too TODO
7
//----------------------------------------------------------------
11
#include "Framework.h"
16
// helper function, splits convex n-gon into a set of bilinear patches
17
static void splitPolygon(const Primitive& p, const Framework &f, RtPoint* pts,
18
int num_verts, int uni_idx, int* idx_ofs = NULL)
20
const int lastpoint = num_verts-1;
21
int sta = 1, end = MIN2(3, lastpoint);
22
int vary_idx[4]; // data indices, varying == vertex since bilinear patches used
23
// split into set of quads
24
while ((end - sta) == 2) {
26
vary_idx[0] = idx_ofs[0], vary_idx[1] = idx_ofs[sta], vary_idx[2] = idx_ofs[end], vary_idx[3] = idx_ofs[sta+1];
28
vary_idx[0] = 0, vary_idx[1] = sta, vary_idx[2] = end, vary_idx[3] = sta+1;
29
const RtPoint p1 = {pts[vary_idx[0]][0], pts[vary_idx[0]][1], pts[vary_idx[0]][2]};
30
const RtPoint p2 = {pts[vary_idx[1]][0], pts[vary_idx[1]][1], pts[vary_idx[1]][2]};
31
const RtPoint p3 = {pts[vary_idx[2]][0], pts[vary_idx[2]][1], pts[vary_idx[2]][2]};
32
const RtPoint p4 = {pts[vary_idx[3]][0], pts[vary_idx[3]][1], pts[vary_idx[3]][2]};
33
BilinearPatch* bp = new BilinearPatch(p, p1, p2, p3, p4);
34
splitPrimVars(&p, bp, uni_idx, vary_idx, vary_idx);
37
sta = end, end = MIN2(sta+2, lastpoint);
40
// end triangle when odd number of vertices, prbook seems to have some errors...
41
const PrimVars* pv = p.getPrimVars();
42
sklist_t<vardata_t*>& varlist = const_cast<PrimVars*>(pv)->pvars;
43
if (sta != lastpoint) {
44
const int I0 = idx_ofs ? idx_ofs[0] : 0,
45
I1 = idx_ofs ? idx_ofs[sta] : sta,
46
I2 = idx_ofs ? idx_ofs[end] : end;
47
const RtPoint ct = {(pts[I0][0] + pts[I1][0] + pts[I2][0])/3.f,
48
(pts[I0][1] + pts[I1][1] + pts[I2][1])/3.f,
49
(pts[I0][2] + pts[I1][2] + pts[I2][2])/3.f};
50
const RtPoint e1 = {(pts[I0][0] + pts[I1][0])*0.5f,
51
(pts[I0][1] + pts[I1][1])*0.5f,
52
(pts[I0][2] + pts[I1][2])*0.5f};
53
const RtPoint e2 = {(pts[I1][0] + pts[I2][0])*0.5f,
54
(pts[I1][1] + pts[I2][1])*0.5f,
55
(pts[I1][2] + pts[I2][2])*0.5f};
56
const RtPoint e3 = {(pts[I2][0] + pts[I0][0])*0.5f,
57
(pts[I2][1] + pts[I0][1])*0.5f,
58
(pts[I2][2] + pts[I0][2])*0.5f};
59
const RtPoint p1 = {pts[I0][0], pts[I0][1], pts[I0][2]};
60
const RtPoint p2 = {pts[I1][0], pts[I1][1], pts[I1][2]};
61
const RtPoint p3 = {pts[I2][0], pts[I2][1], pts[I2][2]};
62
BilinearPatch* bp1 = new BilinearPatch(p, ct, e3, e1, p1);
63
BilinearPatch* bp2 = new BilinearPatch(p, ct, e1, e2, p2);
64
BilinearPatch* bp3 = new BilinearPatch(p, ct, e2, e3, p3);
66
// primvar split cannot use splitPrimVars() here since new data is interpolated from old
67
// (too complex, simplify)
68
if (pv && (varlist.size() != 0)) {
69
PrimVars *npv1 = NULL, *npv2 = NULL, *npv3 = NULL;
71
vardata_t** vdt = varlist.first();
73
if (npv1 == NULL) npv1 = bp1->newPrimVars();
74
if (npv2 == NULL) npv2 = bp2->newPrimVars();
75
if (npv3 == NULL) npv3 = bp3->newPrimVars();
76
decParam_t& dp = (*vdt)->param;
77
vardata_t* nvdt1 = new vardata_t(dp);
78
vardata_t* nvdt2 = new vardata_t(dp);
79
vardata_t* nvdt3 = new vardata_t(dp);
80
if (dp.ct_flags & SC_CONSTANT) {
81
// nothing to do, just copy
82
nvdt1->data = new float[dp.numfloats];
83
nvdt2->data = new float[dp.numfloats];
84
nvdt3->data = new float[dp.numfloats];
85
memcpy(nvdt1->data, (*vdt)->data, sizeof(float)*dp.numfloats);
86
memcpy(nvdt2->data, (*vdt)->data, sizeof(float)*dp.numfloats);
87
memcpy(nvdt3->data, (*vdt)->data, sizeof(float)*dp.numfloats);
89
else if (dp.ct_flags & SC_UNIFORM) {
90
if (dp.ct_flags & DT_FLOAT) {
91
float *nfa1 = new float[1], *nfa2 = new float[1], *nfa3 = new float[1];
92
const float *ofa = (*vdt)->data;
93
nfa1[0] = nfa2[0] = nfa3[0] = ofa[uni_idx];
98
else if ((dp.ct_flags & DT_MATRIX)==0) {
99
// color/point/vector/normal, pretend vector, doesn't matter, all are 3-float arrays
100
RtVector *nva1 = new RtVector[1], *nva2 = new RtVector[1], *nva3 = new RtVector[1];
101
const RtVector *ova = reinterpret_cast<RtVector*>((*vdt)->data);
102
nva1[0][0] = nva2[0][0] = nva3[0][0] = ova[uni_idx][0];
103
nva1[0][1] = nva2[0][1] = nva3[0][1] = ova[uni_idx][1];
104
nva1[0][2] = nva2[0][2] = nva3[0][2] = ova[uni_idx][2];
105
nvdt1->data = reinterpret_cast<float*>(nva1);
106
nvdt2->data = reinterpret_cast<float*>(nva2);
107
nvdt3->data = reinterpret_cast<float*>(nva3);
110
else if (dp.ct_flags & (SC_VARYING | SC_VERTEX)) {
111
if (dp.ct_flags & DT_FLOAT) {
112
float *nfa1 = new float[4], *nfa2 = new float[4],
113
*nfa3 = new float[4], *ofa = (*vdt)->data;
114
const float ctC = (ofa[I0] + ofa[I1] + ofa[I2])/3.f,
115
e1C = (ofa[I0] + ofa[I1])*0.5f,
116
e2C = (ofa[I1] + ofa[I2])*0.5f,
117
e3C = (ofa[I2] + ofa[I0])*0.5f;
119
nfa1[0] = ctC, nfa1[1] = e3C, nfa1[2] = e1C, nfa1[3] = ofa[I0];
121
nfa2[0] = ctC, nfa2[1] = e1C, nfa2[2] = e2C, nfa2[3] = ofa[I1];
123
nfa3[0] = ctC, nfa3[1] = e2C, nfa3[2] = e3C, nfa3[3] = ofa[I2];
128
else if ((dp.ct_flags & DT_MATRIX)==0) {
129
// color/point/vector/normal, pretend color, doesn't matter, all are 3-float arrays
130
RtColor *nca1 = new RtColor[4], *nca2 = new RtColor[4],
131
*nca3 = new RtColor[4], *oca = reinterpret_cast<RtColor*>((*vdt)->data);
132
const RtColor ctC = {(oca[I0][0] + oca[I1][0] + oca[I2][0])/3.f,
133
(oca[I0][1] + oca[I1][1] + oca[I2][1])/3.f,
134
(oca[I0][2] + oca[I1][2] + oca[I2][2])/3.f};
135
const RtColor e1C = {(oca[I0][0] + oca[I1][0])*0.5f,
136
(oca[I0][1] + oca[I1][1])*0.5f,
137
(oca[I0][2] + oca[I1][2])*0.5f};
138
const RtColor e2C = {(oca[I1][0] + oca[I2][0])*0.5f,
139
(oca[I1][1] + oca[I2][1])*0.5f,
140
(oca[I1][2] + oca[I2][2])*0.5f};
141
const RtColor e3C = {(oca[I2][0] + oca[I0][0])*0.5f,
142
(oca[I2][1] + oca[I0][1])*0.5f,
143
(oca[I2][2] + oca[I0][2])*0.5f};
145
nca1[0][0] = ctC[0], nca1[0][1] = ctC[1], nca1[0][2] = ctC[2];
146
nca1[1][0] = e3C[0], nca1[1][1] = e3C[1], nca1[1][2] = e3C[2];
147
nca1[2][0] = e1C[0], nca1[2][1] = e1C[1], nca1[2][2] = e1C[2];
148
nca1[3][0] = oca[I0][0], nca1[3][1] = oca[I0][1], nca1[3][2] = oca[I0][2];
150
nca2[0][0] = ctC[0], nca2[0][1] = ctC[1], nca2[0][2] = ctC[2];
151
nca2[1][0] = e1C[0], nca2[1][1] = e1C[1], nca2[1][2] = e1C[2];
152
nca2[2][0] = e2C[0], nca2[2][1] = e2C[1], nca2[2][2] = e2C[2];
153
nca2[3][0] = oca[I1][0], nca2[3][1] = oca[I1][1], nca2[3][2] = oca[I1][2];
155
nca3[0][0] = ctC[0], nca3[0][1] = ctC[1], nca3[0][2] = ctC[2];
156
nca3[1][0] = e2C[0], nca3[1][1] = e2C[1], nca3[1][2] = e2C[2];
157
nca3[2][0] = e3C[0], nca3[2][1] = e3C[1], nca3[2][2] = e3C[2];
158
nca3[3][0] = oca[I2][0], nca3[3][1] = oca[I2][1], nca3[3][2] = oca[I2][2];
159
nvdt1->data = reinterpret_cast<float*>(nca1);
160
nvdt2->data = reinterpret_cast<float*>(nca2);
161
nvdt3->data = reinterpret_cast<float*>(nca3);
163
// don't know what to do with matrices yet...
165
char* vname = varlist.getName();
166
npv1->pvars.insert(vname, nvdt1);
167
npv2->pvars.insert(vname, nvdt2);
168
npv3->pvars.insert(vname, nvdt3);
169
vdt = varlist.next();
185
//------------------------------------------------------------------------------
188
Polygon::Polygon(RtInt nverts, RtInt n, RtToken tokens[], RtPointer parms[])
189
: pts(NULL), num_verts(nverts)
191
for (int i=0; i<n; ++i) {
192
if (!strcmp(tokens[i], RI_P)) {
193
pts = new RtPoint[num_verts];
194
memcpy(pts, parms[i], sizeof(RtPoint)*num_verts);
198
Primitive::initPrimVars(n, tokens, parms, 1, nverts, nverts, nverts);
203
if (pts) { delete[] pts; pts = NULL; }
206
Bound Polygon::bound()
209
for (int i=0; i<num_verts; ++i)
216
void Polygon::split(const Framework &f, bool usplit, bool vsplit, splitbprims_t* spb)
218
// usplit/vsplit values don't matter, just splits (never called from diceable())
219
splitPolygon(*this, f, pts, num_verts, 0);
222
// does nothing, print msg in case it is called, should never happen though...
223
void Polygon::dice(MicroPolygonGrid &g, bool Pclose)
225
printf("[ERROR]: Polygon()->dice() called?\n");
228
//------------------------------------------------------------------------------
231
PointsPolygons::PointsPolygons(RtInt npolys, RtInt nverts[], RtInt verts[],
232
RtInt n, RtToken tokens[], RtPointer parms[])
233
: pts(NULL), num_faces(npolys)
235
// sum of verts ( == max possible vertex index == sizeof verts[] array)
236
int sum_faceverts = 0;
237
max_fvert = 0; // highest vertex count per face, and also max possible number of facevarying vars
238
for (int i=0; i<npolys; ++i) {
239
sum_faceverts += nverts[i];
240
max_fvert = MAX2(max_fvert, nverts[i]);
242
vert_per_face = new RtInt[npolys];
243
memcpy(vert_per_face, nverts, sizeof(RtInt)*npolys);
245
// determine number of expected "P" vertices from the highest index referenced (+1) in verts[]
247
for (int i=0; i<sum_faceverts; ++i)
248
num_verts = MAX2(num_verts, verts[i]);
250
vert_idx = new RtInt[sum_faceverts];
251
memcpy(vert_idx, verts, sizeof(RtInt)*sum_faceverts);
254
for (int i=0; i<n; ++i) {
255
if (!strcmp(tokens[i], RI_P)) {
256
pts = new RtPoint[num_verts];
257
memcpy(pts, parms[i], sizeof(RtPoint)*num_verts);
261
Primitive::initPrimVars(n, tokens, parms, npolys, num_verts, num_verts, sum_faceverts);
264
PointsPolygons::~PointsPolygons()
266
if (vert_per_face) { delete[] vert_per_face; vert_per_face = NULL; }
267
if (vert_idx) { delete[] vert_idx; vert_idx = NULL; }
268
if (pts) { delete[] pts; pts = NULL; }
271
Bound PointsPolygons::bound()
274
for (int i=0; i<num_verts; ++i)
281
void PointsPolygons::split(const Framework &f, bool usplit, bool vsplit, splitbprims_t* spb)
283
// usplit/vsplit values don't matter, just splits (never called from diceable())
284
RtInt* pidx = new RtInt[max_fvert];
286
for (int i=0; i<num_faces; ++i) {
287
for (int j=0; j<vert_per_face[i]; ++j)
288
pidx[j] = vert_idx[j + idx];
289
splitPolygon(*this, f, pts, vert_per_face[i], i, pidx);
290
idx += vert_per_face[i];
295
// does nothing, print msg in case it is called, should never happen though...
296
void PointsPolygons::dice(MicroPolygonGrid &g, bool Pclose)
298
printf("[ERROR]: PointsPolygons()->dice() called?\n");