2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2009 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): André Pinto.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/render/intern/raytrace/rayobject.cpp
35 #include "MEM_guardedalloc.h"
38 #include "BLI_utildefines.h"
40 #include "DNA_material_types.h"
42 #include "rayintersection.h"
43 #include "rayobject.h"
44 #include "raycounter.h"
45 #include "render_types.h"
46 #include "renderdatabase.h"
50 * note we force always inline here, because compiler refuses to otherwise
51 * because function is too long. Since this is code that is called billions
52 * of times we really do want to inline. */
54 MALWAYS_INLINE RayObject *rayface_from_coords(RayFace *rayface, void *ob, void *face,
55 float *v1, float *v2, float *v3, float *v4)
60 copy_v3_v3(rayface->v1, v1);
61 copy_v3_v3(rayface->v2, v2);
62 copy_v3_v3(rayface->v3, v3);
65 copy_v3_v3(rayface->v4, v4);
72 return RE_rayobject_unalignRayFace(rayface);
75 MALWAYS_INLINE void rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr)
77 rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : NULL);
79 if (obi->transform_primitives) {
80 mul_m4_v3(obi->mat, rayface->v1);
81 mul_m4_v3(obi->mat, rayface->v2);
82 mul_m4_v3(obi->mat, rayface->v3);
84 if (RE_rayface_isQuad(rayface))
85 mul_m4_v3(obi->mat, rayface->v4);
89 RayObject *RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr)
91 return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : NULL);
94 RayObject *RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4)
96 return rayface_from_coords(rayface, ob, face, v1, v2, v3, v4);
101 RayObject *RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr)
106 return RE_rayobject_unalignVlakPrimitive(face);
109 /* Checks for ignoring faces or materials */
111 MALWAYS_INLINE int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr)
113 /* for baking selected to active non-traceable materials might still
114 * be in the raytree */
115 if (!(vlr->flag & R_TRACEBLE))
118 /* I know... cpu cycle waste, might do smarter once */
119 if (is->mode == RE_RAY_MIRROR)
120 return !(vlr->mat->mode & MA_ONLYCAST);
122 return (is->lay & obi->lay);
125 MALWAYS_INLINE int vlr_check_intersect_solid(Isect *UNUSED(is), ObjectInstanceRen *UNUSED(obi), VlakRen *vlr)
127 /* solid material types only */
128 if (vlr->mat->material_type == MA_TYPE_SURFACE)
134 MALWAYS_INLINE int vlr_check_bake(Isect *is, ObjectInstanceRen *obi, VlakRen *UNUSED(vlr))
136 return (obi->obr->ob != is->userdata) && (obi->obr->ob->flag & SELECT);
139 /* Ray Triangle/Quad Intersection */
141 MALWAYS_INLINE int isec_tri_quad(float start[3], float dir[3], RayFace *face, float uv[2], float *lambda)
143 float co1[3], co2[3], co3[3], co4[3];
144 float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1, l;
147 quad = RE_rayface_isQuad(face);
149 copy_v3_v3(co1, face->v1);
150 copy_v3_v3(co2, face->v2);
151 copy_v3_v3(co3, face->v3);
155 /* intersect triangle */
156 sub_v3_v3v3(t0, co3, co2);
157 sub_v3_v3v3(t1, co3, co1);
159 cross_v3_v3v3(x, r, t1);
160 divdet = dot_v3v3(t0, x);
162 sub_v3_v3v3(m, start, co3);
163 det1 = dot_v3v3(m, x);
165 if (divdet != 0.0f) {
166 divdet = 1.0f / divdet;
169 if (v < RE_RAYTRACE_EPSILON && v > -(1.0f + RE_RAYTRACE_EPSILON)) {
172 cross_v3_v3v3(cros, m, t0);
173 u = divdet * dot_v3v3(cros, r);
175 if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f + RE_RAYTRACE_EPSILON)) {
176 l = divdet * dot_v3v3(cros, t1);
178 /* check if intersection is within ray length */
179 if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
189 /* intersect second triangle in quad */
191 copy_v3_v3(co4, face->v4);
192 sub_v3_v3v3(t0, co3, co4);
193 divdet = dot_v3v3(t0, x);
195 if (divdet != 0.0f) {
196 divdet = 1.0f / divdet;
199 if (v < RE_RAYTRACE_EPSILON && v > -(1.0f + RE_RAYTRACE_EPSILON)) {
202 cross_v3_v3v3(cros, m, t0);
203 u = divdet * dot_v3v3(cros, r);
205 if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f + RE_RAYTRACE_EPSILON)) {
206 l = divdet * dot_v3v3(cros, t1);
208 if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
210 uv[1] = -(1.0f + v + u);
222 /* Simpler yes/no Ray Triangle/Quad Intersection */
224 MALWAYS_INLINE int isec_tri_quad_neighbour(float start[3], float dir[3], RayFace *face)
226 float co1[3], co2[3], co3[3], co4[3];
227 float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1;
230 quad = RE_rayface_isQuad(face);
232 copy_v3_v3(co1, face->v1);
233 copy_v3_v3(co2, face->v2);
234 copy_v3_v3(co3, face->v3);
236 negate_v3_v3(r, dir); /* note, different than above function */
238 /* intersect triangle */
239 sub_v3_v3v3(t0, co3, co2);
240 sub_v3_v3v3(t1, co3, co1);
242 cross_v3_v3v3(x, r, t1);
243 divdet = dot_v3v3(t0, x);
245 sub_v3_v3v3(m, start, co3);
246 det1 = dot_v3v3(m, x);
248 if (divdet != 0.0f) {
249 divdet = 1.0f / divdet;
252 if (v < RE_RAYTRACE_EPSILON && v > -(1.0f + RE_RAYTRACE_EPSILON)) {
255 cross_v3_v3v3(cros, m, t0);
256 u = divdet * dot_v3v3(cros, r);
258 if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f + RE_RAYTRACE_EPSILON))
263 /* intersect second triangle in quad */
265 copy_v3_v3(co4, face->v4);
266 sub_v3_v3v3(t0, co3, co4);
267 divdet = dot_v3v3(t0, x);
269 if (divdet != 0.0f) {
270 divdet = 1.0f / divdet;
273 if (v < RE_RAYTRACE_EPSILON && v > -(1.0f + RE_RAYTRACE_EPSILON)) {
276 cross_v3_v3v3(cros, m, t0);
277 u = divdet * dot_v3v3(cros, r);
279 if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f + RE_RAYTRACE_EPSILON))
288 /* RayFace intersection with checks and neighbor verifaction included,
289 * Isect is modified if the face is hit. */
291 MALWAYS_INLINE int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is)
296 /* avoid self-intersection */
297 if (is->orig.ob == face->ob && is->orig.face == face->face)
300 /* check if we should intersect this face */
301 if (is->check == RE_CHECK_VLR_RENDER) {
302 if (vlr_check_intersect(is, (ObjectInstanceRen *)face->ob, (VlakRen *)face->face) == 0)
305 else if (is->check == RE_CHECK_VLR_NON_SOLID_MATERIAL) {
306 if (vlr_check_intersect(is, (ObjectInstanceRen *)face->ob, (VlakRen *)face->face) == 0)
308 if (vlr_check_intersect_solid(is, (ObjectInstanceRen *)face->ob, (VlakRen *)face->face) == 0)
311 else if (is->check == RE_CHECK_VLR_BAKE) {
312 if (vlr_check_bake(is, (ObjectInstanceRen *)face->ob, (VlakRen *)face->face) == 0)
317 RE_RC_COUNT(is->raycounter->faces.test);
320 ok = isec_tri_quad(is->start, is->dir, face, uv, &dist);
324 /* when a shadow ray leaves a face, it can be little outside the edges
325 * of it, causing intersection to be detected in its neighbor face */
326 if (is->skip & RE_SKIP_VLR_NEIGHBOUR) {
327 if (dist < 0.1f && is->orig.ob == face->ob) {
328 VlakRen *a = (VlakRen *)is->orig.face;
329 VlakRen *b = (VlakRen *)face->face;
330 ObjectRen *obr = ((ObjectInstanceRen *)face->ob)->obr;
333 int *org_idx_a, *org_idx_b;
335 bool is_neighbor = false;
337 /* "same" vertex means either the actual same VertRen, or the same 'final org index', if available
338 * (autosmooth only, currently). */
339 for (i = 0, va = &a->v1; !is_neighbor && i < 4 && *va; ++i, ++va) {
340 org_idx_a = RE_vertren_get_origindex(obr, *va, false);
341 for (j = 0, vb = &b->v1; !is_neighbor && j < 4 && *vb; ++j, ++vb) {
345 else if (org_idx_a) {
346 org_idx_b = RE_vertren_get_origindex(obr, *vb, 0);
347 if (org_idx_b && *org_idx_a == *org_idx_b) {
354 /* So there's a shared edge or vertex, let's intersect ray with self, if that's true
355 * we can safely return 1, otherwise we assume the intersection is invalid, 0 */
357 /* create RayFace from original face, transformed if necessary */
359 ObjectInstanceRen *ob = (ObjectInstanceRen *)is->orig.ob;
360 rayface_from_vlak(&origface, ob, (VlakRen *)is->orig.face);
362 if (!isec_tri_quad_neighbour(is->start, is->dir, &origface)) {
369 RE_RC_COUNT(is->raycounter->faces.hit);
371 is->isect = ok; // which half of the quad
373 is->u = uv[0]; is->v = uv[1];
375 is->hit.ob = face->ob;
376 is->hit.face = face->face;
377 #ifdef RT_USE_LAST_HIT
378 is->last_hit = hit_obj;
388 int RE_rayobject_raycast(RayObject *r, Isect *isec)
392 RE_RC_COUNT(isec->raycounter->raycast.test);
394 /* setup vars used on raycast */
395 for (i = 0; i < 3; i++) {
396 isec->idot_axis[i] = 1.0f / isec->dir[i];
398 isec->bv_index[2 * i] = isec->idot_axis[i] < 0.0f ? 1 : 0;
399 isec->bv_index[2 * i + 1] = 1 - isec->bv_index[2 * i];
401 isec->bv_index[2 * i] = i + 3 * isec->bv_index[2 * i];
402 isec->bv_index[2 * i + 1] = i + 3 * isec->bv_index[2 * i + 1];
405 #ifdef RT_USE_LAST_HIT
406 /* last hit heuristic */
407 if (isec->mode == RE_RAY_SHADOW && isec->last_hit) {
408 RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.test);
410 if (RE_rayobject_intersect(isec->last_hit, isec)) {
411 RE_RC_COUNT(isec->raycounter->raycast.hit);
412 RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.hit);
422 if (RE_rayobject_intersect(r, isec)) {
423 RE_RC_COUNT(isec->raycounter->raycast.hit);
426 isec->hint = isec->hit_hint;
434 int RE_rayobject_intersect(RayObject *r, Isect *i)
436 if (RE_rayobject_isRayFace(r)) {
437 return intersect_rayface(r, (RayFace *) RE_rayobject_align(r), i);
439 else if (RE_rayobject_isVlakPrimitive(r)) {
440 //TODO optimize (useless copy to RayFace to avoid duplicate code)
441 VlakPrimitive *face = (VlakPrimitive *) RE_rayobject_align(r);
443 rayface_from_vlak(&nface, face->ob, face->face);
445 return intersect_rayface(r, &nface, i);
447 else if (RE_rayobject_isRayAPI(r)) {
448 r = RE_rayobject_align(r);
449 return r->api->raycast(r, i);
459 void RE_rayobject_add(RayObject *r, RayObject *o)
461 r = RE_rayobject_align(r);
462 return r->api->add(r, o);
465 void RE_rayobject_done(RayObject *r)
467 r = RE_rayobject_align(r);
471 void RE_rayobject_free(RayObject *r)
473 r = RE_rayobject_align(r);
477 float RE_rayobject_cost(RayObject *r)
479 if (RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) {
482 else if (RE_rayobject_isRayAPI(r)) {
483 r = RE_rayobject_align(r);
484 return r->api->cost(r);
494 void RE_rayobject_merge_bb(RayObject *r, float min[3], float max[3])
496 if (RE_rayobject_isRayFace(r)) {
497 RayFace *face = (RayFace *) RE_rayobject_align(r);
499 DO_MINMAX(face->v1, min, max);
500 DO_MINMAX(face->v2, min, max);
501 DO_MINMAX(face->v3, min, max);
502 if (RE_rayface_isQuad(face)) DO_MINMAX(face->v4, min, max);
504 else if (RE_rayobject_isVlakPrimitive(r)) {
505 VlakPrimitive *face = (VlakPrimitive *) RE_rayobject_align(r);
507 rayface_from_vlak(&nface, face->ob, face->face);
509 DO_MINMAX(nface.v1, min, max);
510 DO_MINMAX(nface.v2, min, max);
511 DO_MINMAX(nface.v3, min, max);
512 if (RE_rayface_isQuad(&nface)) DO_MINMAX(nface.v4, min, max);
514 else if (RE_rayobject_isRayAPI(r)) {
515 r = RE_rayobject_align(r);
516 r->api->bb(r, min, max);
524 void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max)
526 if (RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) {
529 else if (RE_rayobject_isRayAPI(r)) {
530 r = RE_rayobject_align(r);
531 return r->api->hint_bb(r, hint, min, max);
537 /* RayObjectControl */
539 int RE_rayobjectcontrol_test_break(RayObjectControl *control)
541 if (control->test_break)
542 return control->test_break(control->data);
547 void RE_rayobject_set_control(RayObject *r, void *data, RE_rayobjectcontrol_test_break_callback test_break)
549 if (RE_rayobject_isRayAPI(r)) {
550 r = RE_rayobject_align(r);
551 r->control.data = data;
552 r->control.test_break = test_break;