27
25
* ***** END GPL LICENSE BLOCK *****
28
/** \file blender/render/intern/raytrace/rayobject.cpp
29
33
#include <assert.h>
31
#include "BKE_utildefines.h"
35
#include "MEM_guardedalloc.h"
32
37
#include "BLI_math.h"
38
#include "BLI_utildefines.h"
33
40
#include "DNA_material_types.h"
35
#include "RE_raytrace.h"
36
#include "render_types.h"
42
#include "rayintersection.h"
37
43
#include "rayobject.h"
38
44
#include "raycounter.h"
41
* Determines the distance that the ray must travel to hit the bounding volume of the given node
42
* Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe
43
* [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9]
45
int RE_rayobject_bb_intersect_test(const Isect *isec, const float *_bb)
47
const float *bb = _bb;
49
float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0];
50
float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0];
51
float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1];
52
float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1];
53
float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2];
54
float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2];
56
RE_RC_COUNT(isec->raycounter->bb.test);
58
if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0;
59
if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0;
60
if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return 0;
61
RE_RC_COUNT(isec->raycounter->bb.hit);
67
/* only for self-intersecting test with current render face (where ray left) */
68
static int intersection2(VlakRen *face, float r0, float r1, float r2, float rx1, float ry1, float rz1)
70
float co1[3], co2[3], co3[3], co4[3];
71
float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22;
72
float m0, m1, m2, divdet, det, det1;
75
VECCOPY(co1, face->v1->co);
76
VECCOPY(co2, face->v2->co);
45
#include "render_types.h"
49
* note we force always inline here, because compiler refuses to otherwise
50
* because function is too long. Since this is code that is called billions
51
* of times we really do want to inline. */
53
MALWAYS_INLINE RayObject* rayface_from_coords(RayFace *rayface, void *ob, void *face,
54
float *v1, float *v2, float *v3, float *v4)
59
copy_v3_v3(rayface->v1, v1);
60
copy_v3_v3(rayface->v2, v2);
61
copy_v3_v3(rayface->v3, v3);
79
VECCOPY(co3, face->v4->co);
80
VECCOPY(co4, face->v3->co);
65
copy_v3_v3(rayface->v4, v4);
84
VECCOPY(co3, face->v3->co);
98
divdet= t00*x0+t01*x1+t02*x2;
103
det1= m0*x0+m1*x1+m2*x2;
108
if(u1<ISECT_EPSILON) {
109
det= t00*(m1*r2-m2*r1);
110
det+= t01*(m2*r0-m0*r2);
111
det+= t02*(m0*r1-m1*r0);
114
if(v<ISECT_EPSILON && (u1 + v) > -(1.0f+ISECT_EPSILON)) {
126
divdet= t20*x0+t21*x1+t22*x2;
130
if(u2<ISECT_EPSILON) {
131
det= t20*(m1*r2-m2*r1);
132
det+= t21*(m2*r0-m0*r2);
133
det+= t22*(m0*r1-m1*r0);
136
if(v<ISECT_EPSILON && (u2 + v) >= -(1.0f+ISECT_EPSILON)) {
145
static inline int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr)
73
return RE_rayobject_unalignRayFace(rayface);
76
MALWAYS_INLINE void rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr)
78
rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : NULL);
80
if (obi->transform_primitives)
82
mul_m4_v3(obi->mat, rayface->v1);
83
mul_m4_v3(obi->mat, rayface->v2);
84
mul_m4_v3(obi->mat, rayface->v3);
86
if (RE_rayface_isQuad(rayface))
87
mul_m4_v3(obi->mat, rayface->v4);
91
RayObject* RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr)
93
return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0);
98
RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr)
103
return RE_rayobject_unalignVlakPrimitive(face);
106
/* Checks for ignoring faces or materials */
108
MALWAYS_INLINE int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr)
147
110
/* for baking selected to active non-traceable materials might still
148
111
* be in the raytree */
149
if(!(vlr->mat->mode & MA_TRACEBLE))
112
if (!(vlr->flag & R_TRACEBLE))
152
115
/* I know... cpu cycle waste, might do smarter once */
153
if(is->mode==RE_RAY_MIRROR)
116
if (is->mode==RE_RAY_MIRROR)
154
117
return !(vlr->mat->mode & MA_ONLYCAST);
156
119
return (is->lay & obi->lay);
159
static inline int vlr_check_intersect_solid(Isect *is, ObjectInstanceRen* obi, VlakRen *vlr)
122
MALWAYS_INLINE int vlr_check_intersect_solid(Isect *UNUSED(is), ObjectInstanceRen* UNUSED(obi), VlakRen *vlr)
161
124
/* solid material types only */
162
125
if (vlr->mat->material_type == MA_TYPE_SURFACE)
168
static inline int vlr_check_bake(Isect *is, ObjectInstanceRen* obi, VlakRen *vlr)
170
return (obi->obr->ob != is->userdata);
173
static inline int rayface_check_cullface(RayFace *face, Isect *is)
177
/* don't intersect if the ray faces along the face normal */
178
if(face->quad) normal_quad_v3( nor,face->v1, face->v2, face->v3, face->v4);
179
else normal_tri_v3( nor,face->v1, face->v2, face->v3);
181
return (INPR(nor, is->vec) < 0);
184
/* ray - triangle or quad intersection */
185
/* this function shall only modify Isect if it detects an hit */
186
static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is)
188
float co1[3],co2[3],co3[3],co4[3]={0};
189
float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2;
190
float m0, m1, m2, divdet, det1;
194
if(is->orig.ob == face->ob && is->orig.face == face->face)
131
MALWAYS_INLINE int vlr_check_bake(Isect *is, ObjectInstanceRen* obi, VlakRen *UNUSED(vlr))
133
return (obi->obr->ob != is->userdata) && (obi->obr->ob->flag & SELECT);
136
/* Ray Triangle/Quad Intersection */
138
MALWAYS_INLINE int isec_tri_quad(float start[3], float dir[3], RayFace *face, float uv[2], float *lambda)
140
float co1[3], co2[3], co3[3], co4[3];
141
float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1, l;
144
quad= RE_rayface_isQuad(face);
146
copy_v3_v3(co1, face->v1);
147
copy_v3_v3(co2, face->v2);
148
copy_v3_v3(co3, face->v3);
152
/* intersect triangle */
153
sub_v3_v3v3(t0, co3, co2);
154
sub_v3_v3v3(t1, co3, co1);
156
cross_v3_v3v3(x, r, t1);
157
divdet= dot_v3v3(t0, x);
159
sub_v3_v3v3(m, start, co3);
160
det1= dot_v3v3(m, x);
162
if (divdet != 0.0f) {
166
if (v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) {
169
cross_v3_v3v3(cros, m, t0);
170
u= divdet*dot_v3v3(cros, r);
172
if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON)) {
173
l= divdet*dot_v3v3(cros, t1);
175
/* check if intersection is within ray length */
176
if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
186
/* intersect second triangle in quad */
188
copy_v3_v3(co4, face->v4);
189
sub_v3_v3v3(t0, co3, co4);
190
divdet= dot_v3v3(t0, x);
192
if (divdet != 0.0f) {
196
if (v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) {
199
cross_v3_v3v3(cros, m, t0);
200
u= divdet*dot_v3v3(cros, r);
202
if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON)) {
203
l= divdet*dot_v3v3(cros, t1);
205
if (l >- RE_RAYTRACE_EPSILON && l < *lambda) {
207
uv[1]= -(1.0f + v + u);
219
/* Simpler yes/no Ray Triangle/Quad Intersection */
221
MALWAYS_INLINE int isec_tri_quad_neighbour(float start[3], float dir[3], RayFace *face)
223
float co1[3], co2[3], co3[3], co4[3];
224
float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1;
227
quad= RE_rayface_isQuad(face);
229
copy_v3_v3(co1, face->v1);
230
copy_v3_v3(co2, face->v2);
231
copy_v3_v3(co3, face->v3);
233
negate_v3_v3(r, dir); /* note, different than above function */
235
/* intersect triangle */
236
sub_v3_v3v3(t0, co3, co2);
237
sub_v3_v3v3(t1, co3, co1);
239
cross_v3_v3v3(x, r, t1);
240
divdet= dot_v3v3(t0, x);
242
sub_v3_v3v3(m, start, co3);
243
det1= dot_v3v3(m, x);
245
if (divdet != 0.0f) {
249
if (v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) {
252
cross_v3_v3v3(cros, m, t0);
253
u= divdet*dot_v3v3(cros, r);
255
if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON))
260
/* intersect second triangle in quad */
262
copy_v3_v3(co4, face->v4);
263
sub_v3_v3v3(t0, co3, co4);
264
divdet= dot_v3v3(t0, x);
266
if (divdet != 0.0f) {
270
if (v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) {
273
cross_v3_v3v3(cros, m, t0);
274
u= divdet*dot_v3v3(cros, r);
276
if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON))
285
/* RayFace intersection with checks and neighbor verifaction included,
286
* Isect is modified if the face is hit. */
288
MALWAYS_INLINE int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is)
293
/* avoid self-intersection */
294
if (is->orig.ob == face->ob && is->orig.face == face->face)
197
297
/* check if we should intersect this face */
198
if(is->skip & RE_SKIP_VLR_RENDER_CHECK)
200
if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0)
203
else if(is->skip & RE_SKIP_VLR_NON_SOLID_MATERIAL)
205
if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0)
207
if(vlr_check_intersect_solid(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
210
else if(is->skip & RE_SKIP_VLR_BAKE_CHECK) {
211
if(vlr_check_bake(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0)
215
if(is->skip & RE_SKIP_CULLFACE)
217
if(rayface_check_cullface(face, is) == 0)
298
if (is->check == RE_CHECK_VLR_RENDER)
300
if (vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
303
else if (is->check == RE_CHECK_VLR_NON_SOLID_MATERIAL)
305
if (vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
307
if (vlr_check_intersect_solid(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
310
else if (is->check == RE_CHECK_VLR_BAKE) {
311
if (vlr_check_bake(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0)
221
316
RE_RC_COUNT(is->raycounter->faces.test);
224
VECCOPY(co1, face->v1);
225
VECCOPY(co2, face->v2);
226
if(RE_rayface_isQuad(face))
228
VECCOPY(co3, face->v4);
229
VECCOPY(co4, face->v3);
233
VECCOPY(co3, face->v3);
251
divdet= t00*x0+t01*x1+t02*x2;
253
m0= is->start[0]-co3[0];
254
m1= is->start[1]-co3[1];
255
m2= is->start[2]-co3[2];
256
det1= m0*x0+m1*x1+m2*x2;
262
if(u<ISECT_EPSILON && u>-(1.0f+ISECT_EPSILON)) {
263
float cros0, cros1, cros2;
265
cros0= m1*t02-m2*t01;
266
cros1= m2*t00-m0*t02;
267
cros2= m0*t01-m1*t00;
268
v= divdet*(cros0*r0 + cros1*r1 + cros2*r2);
270
if(v<ISECT_EPSILON && (u + v) > -(1.0f+ISECT_EPSILON)) {
271
labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12);
273
if(labda>-ISECT_EPSILON && labda<is->labda) {
280
if(ok==0 && RE_rayface_isQuad(face)) {
286
divdet= t20*x0+t21*x1+t22*x2;
291
if(u<ISECT_EPSILON && u>-(1.0f+ISECT_EPSILON)) {
292
float cros0, cros1, cros2;
293
cros0= m1*t22-m2*t21;
294
cros1= m2*t20-m0*t22;
295
cros2= m0*t21-m1*t20;
296
v= divdet*(cros0*r0 + cros1*r1 + cros2*r2);
298
if(v<ISECT_EPSILON && (u + v) >-(1.0f+ISECT_EPSILON)) {
299
labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12);
301
if(labda>-ISECT_EPSILON && labda<is->labda) {
311
/* when a shadow ray leaves a face, it can be little outside the edges of it, causing
312
intersection to be detected in its neighbour face */
313
if(is->skip & RE_SKIP_VLR_NEIGHBOUR)
319
ok= isec_tri_quad(is->start, is->dir, face, uv, &dist);
323
/* when a shadow ray leaves a face, it can be little outside the edges
324
* of it, causing intersection to be detected in its neighbor face */
325
if (is->skip & RE_SKIP_VLR_NEIGHBOUR)
315
if(labda < 0.1f && is->orig.ob == face->ob)
327
if (dist < 0.1f && is->orig.ob == face->ob)
317
329
VlakRen * a = (VlakRen*)is->orig.face;
318
330
VlakRen * b = (VlakRen*)face->face;
320
/* so there's a shared edge or vertex, let's intersect ray with face
321
itself, if that's true we can safely return 1, otherwise we assume
322
the intersection is invalid, 0 */
323
if(a->v1==b->v1 || a->v2==b->v1 || a->v3==b->v1 || a->v4==b->v1
332
/* so there's a shared edge or vertex, let's intersect ray with
333
* face itself, if that's true we can safely return 1, otherwise
334
* we assume the intersection is invalid, 0 */
335
if (a->v1==b->v1 || a->v2==b->v1 || a->v3==b->v1 || a->v4==b->v1
324
336
|| a->v1==b->v2 || a->v2==b->v2 || a->v3==b->v2 || a->v4==b->v2
325
337
|| a->v1==b->v3 || a->v2==b->v3 || a->v3==b->v3 || a->v4==b->v3
326
|| (b->v4 && (a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || a->v4==b->v4)))
327
if(!intersection2((VlakRen*)a, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2]))
338
|| (b->v4 && (a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || a->v4==b->v4))) {
339
/* create RayFace from original face, transformed if necessary */
341
ObjectInstanceRen *ob= (ObjectInstanceRen*)is->orig.ob;
342
rayface_from_vlak(&origface, ob, (VlakRen*)is->orig.face);
344
if (!isec_tri_quad_neighbour(is->start, is->dir, &origface))
435
421
int RE_rayobject_intersect(RayObject *r, Isect *i)
437
if(RE_rayobject_isRayFace(r))
423
if (RE_rayobject_isRayFace(r))
439
425
return intersect_rayface(r, (RayFace*) RE_rayobject_align(r), i);
441
else if(RE_rayobject_isVlakPrimitive(r))
427
else if (RE_rayobject_isVlakPrimitive(r))
443
429
//TODO optimize (useless copy to RayFace to avoid duplicate code)
444
430
VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r);
446
RE_rayface_from_vlak(&nface, face->ob, face->face);
448
if(face->ob->transform_primitives)
450
mul_m4_v3(face->ob->mat, nface.v1);
451
mul_m4_v3(face->ob->mat, nface.v2);
452
mul_m4_v3(face->ob->mat, nface.v3);
453
if(RE_rayface_isQuad(&nface))
454
mul_m4_v3(face->ob->mat, nface.v4);
432
rayface_from_vlak(&nface, face->ob, face->face);
457
434
return intersect_rayface(r, &nface, i);
459
else if(RE_rayobject_isRayAPI(r))
436
else if (RE_rayobject_isRayAPI(r))
461
r = RE_rayobject_align( r );
462
return r->api->raycast( r, i );
465
return 0; /* wont reach this, quiet compilers */
438
r = RE_rayobject_align(r);
439
return r->api->raycast(r, i);
468
449
void RE_rayobject_add(RayObject *r, RayObject *o)
470
r = RE_rayobject_align( r );
471
return r->api->add( r, o );
451
r = RE_rayobject_align(r);
452
return r->api->add(r, o);
474
455
void RE_rayobject_done(RayObject *r)
476
r = RE_rayobject_align( r );
457
r = RE_rayobject_align(r);
480
461
void RE_rayobject_free(RayObject *r)
482
r = RE_rayobject_align( r );
463
r = RE_rayobject_align(r);
467
float RE_rayobject_cost(RayObject *r)
469
if (RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r))
473
else if (RE_rayobject_isRayAPI(r))
475
r = RE_rayobject_align(r);
476
return r->api->cost(r);
486
486
void RE_rayobject_merge_bb(RayObject *r, float *min, float *max)
488
if(RE_rayobject_isRayFace(r))
488
if (RE_rayobject_isRayFace(r))
490
490
RayFace *face = (RayFace*) RE_rayobject_align(r);
492
DO_MINMAX( face->v1, min, max );
493
DO_MINMAX( face->v2, min, max );
494
DO_MINMAX( face->v3, min, max );
495
if(RE_rayface_isQuad(face)) DO_MINMAX( face->v4, min, max );
492
DO_MINMAX(face->v1, min, max);
493
DO_MINMAX(face->v2, min, max);
494
DO_MINMAX(face->v3, min, max);
495
if (RE_rayface_isQuad(face)) DO_MINMAX(face->v4, min, max);
497
else if(RE_rayobject_isVlakPrimitive(r))
497
else if (RE_rayobject_isVlakPrimitive(r))
499
499
VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r);
501
RE_rayface_from_vlak(&nface, face->ob, face->face);
503
if(face->ob->transform_primitives)
505
mul_m4_v3(face->ob->mat, nface.v1);
506
mul_m4_v3(face->ob->mat, nface.v2);
507
mul_m4_v3(face->ob->mat, nface.v3);
508
if(RE_rayface_isQuad(&nface))
509
mul_m4_v3(face->ob->mat, nface.v4);
512
DO_MINMAX( nface.v1, min, max );
513
DO_MINMAX( nface.v2, min, max );
514
DO_MINMAX( nface.v3, min, max );
515
if(RE_rayface_isQuad(&nface)) DO_MINMAX( nface.v4, min, max );
517
else if(RE_rayobject_isRayAPI(r))
519
r = RE_rayobject_align( r );
520
r->api->bb( r, min, max );
525
float RE_rayobject_cost(RayObject *r)
527
if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r))
531
else if(RE_rayobject_isRayAPI(r))
533
r = RE_rayobject_align( r );
534
return r->api->cost( r );
501
rayface_from_vlak(&nface, face->ob, face->face);
503
DO_MINMAX(nface.v1, min, max);
504
DO_MINMAX(nface.v2, min, max);
505
DO_MINMAX(nface.v3, min, max);
506
if (RE_rayface_isQuad(&nface)) DO_MINMAX(nface.v4, min, max);
508
else if (RE_rayobject_isRayAPI(r))
510
r = RE_rayobject_align(r);
511
r->api->bb(r, min, max);
539
519
void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max)
541
if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r))
521
if (RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r))
545
else if(RE_rayobject_isRayAPI(r))
525
else if (RE_rayobject_isRayAPI(r))
547
r = RE_rayobject_align( r );
548
return r->api->hint_bb( r, hint, min, max );
527
r = RE_rayobject_align(r);
528
return r->api->hint_bb(r, hint, min, max);
534
/* RayObjectControl */
553
536
int RE_rayobjectcontrol_test_break(RayObjectControl *control)
555
if(control->test_break)
556
return control->test_break( control->data );
565
static int RE_rayobject_empty_intersect(RayObject *o, Isect *is)
570
static void RE_rayobject_empty_free(RayObject *o)
574
static void RE_rayobject_empty_bb(RayObject *o, float *min, float *max)
579
static float RE_rayobject_empty_cost(RayObject *o)
584
static void RE_rayobject_empty_hint_bb(RayObject *o, RayHint *hint, float *min, float *max)
587
static RayObjectAPI empty_api =
589
RE_rayobject_empty_intersect,
590
NULL, //static void RE_rayobject_instance_add(RayObject *o, RayObject *ob);
591
NULL, //static void RE_rayobject_instance_done(RayObject *o);
592
RE_rayobject_empty_free,
593
RE_rayobject_empty_bb,
594
RE_rayobject_empty_cost,
595
RE_rayobject_empty_hint_bb
598
static RayObject empty_raytree = { &empty_api, {0, 0} };
600
RayObject *RE_rayobject_empty_create()
602
return RE_rayobject_unalignRayAPI( &empty_raytree );
538
if (control->test_break)
539
return control->test_break(control->data);
544
void RE_rayobject_set_control(RayObject *r, void *data, RE_rayobjectcontrol_test_break_callback test_break)
546
if (RE_rayobject_isRayAPI(r))
548
r = RE_rayobject_align(r);
549
r->control.data = data;
550
r->control.test_break = test_break;