*Added support to "BB hints" (which works like a BB version of LCTS - longest common...
[blender-staging.git] / source / blender / render / intern / include / rayobject.h
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): AndrĂ© Pinto.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29 #ifndef RE_RAYOBJECT_H
30 #define RE_RAYOBJECT_H
31
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35
36 #include "RE_raytrace.h"
37 #include <float.h>
38
39
40 /* RayObject
41         
42         A ray object is everything where we can cast rays like:
43                 * a face/triangle
44                 * an octree
45                 * a bvh tree
46                 * an octree of bvh's
47                 * a bvh of bvh's
48         
49                 
50         All types of RayObjects can be created by implementing the
51         callbacks of the RayObject.
52
53         Due to high computing time evolved with casting on faces
54         there is a special type of RayObject (named RayFace)
55         which won't use callbacks like other generic nodes.
56         
57         In order to allow a mixture of RayFace+RayObjects,
58         all RayObjects must be 4byte aligned, allowing us to use the
59         2 least significant bits (with the mask 0x02) to define the
60         type of RayObject.
61         
62         This leads to 4 possible types of RayObject, but at the moment
63         only 2 are used:
64
65          addr&2  - type of object
66                 0               Self (reserved for each structure)
67                 1       RayFace
68                 2               RayObject (generic with API callbacks)
69                 3               unused
70
71         0 means it's reserved and has it own meaning inside each ray acceleration structure
72         (this way each structure can use the allign offset to determine if a node represents a
73          RayObject primitive, which can be used to save memory)
74
75         You actually don't need to care about this if you are only using the API
76         described on RE_raytrace.h
77  */
78  
79 typedef struct RayFace
80 {
81         float *v1, *v2, *v3, *v4;
82         
83         void *ob;
84         void *face;
85         
86 } RayFace;
87
88 struct RayObject
89 {
90         struct RayObjectAPI *api;
91         
92 };
93
94
95 typedef int  (*RE_rayobject_raycast_callback)(RayObject *, Isect *);
96 typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject);
97 typedef void (*RE_rayobject_done_callback)(RayObject *);
98 typedef void (*RE_rayobject_free_callback)(RayObject *);
99 typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float *min, float *max);
100 typedef float (*RE_rayobject_cost_callback)(RayObject *);
101 typedef void (*RE_rayobject_hint_bb_callback)(RayObject *, RayHint *, float *, float *);
102
103 typedef struct RayObjectAPI
104 {
105         RE_rayobject_raycast_callback   raycast;
106         RE_rayobject_add_callback               add;
107         RE_rayobject_done_callback              done;
108         RE_rayobject_free_callback              free;
109         RE_rayobject_merge_bb_callback  bb;
110         RE_rayobject_cost_callback              cost;
111         RE_rayobject_hint_bb_callback   hint_bb;
112         
113 } RayObjectAPI;
114
115 #define RayObject_align(o)                              ((RayObject*)(((intptr_t)o)&(~3)))
116 #define RayObject_unalignRayFace(o)             ((RayObject*)(((intptr_t)o)|1))
117 #define RayObject_unalignRayAPI(o)              ((RayObject*)(((intptr_t)o)|2))
118
119 #define RayObject_isAligned(o)  ((((intptr_t)o)&3) == 0)
120 #define RayObject_isRayFace(o)  ((((intptr_t)o)&3) == 1)
121 #define RayObject_isRayAPI(o)   ((((intptr_t)o)&3) == 2)
122
123 /*
124  * Extend min/max coords so that the rayobject is inside them
125  */
126 void RE_rayobject_merge_bb(RayObject *ob, float *min, float *max);
127
128 /*
129  * This function differs from RE_rayobject_raycast
130  * RE_rayobject_intersect does NOT perform last-hit optimization
131  * So this is probably a function to call inside raytrace structures
132  */
133 int RE_rayobject_intersect(RayObject *r, Isect *i);
134
135 /*
136  * Returns distance ray must travel to hit the given bounding box
137  * BB should be in format [2][3]
138  */
139 float RE_rayobject_bb_intersect(const Isect *i, const float *bb);
140
141 /*
142  * Returns the expected cost of raycast on this node, primitives have a cost of 1
143  */
144 float RE_rayobject_cost(RayObject *r);
145
146
147 #define ISECT_EPSILON ((float)FLT_EPSILON)
148
149
150
151 #if !defined(_WIN32)
152
153 #include <sys/time.h>
154 #include <time.h>
155 #include <stdio.h>
156
157 #define BENCH(a,name)   \
158         do {                    \
159                 double _t1, _t2;                                \
160                 struct timeval _tstart, _tend;  \
161                 clock_t _clock_init = clock();  \
162                 gettimeofday ( &_tstart, NULL); \
163                 (a);                                                    \
164                 gettimeofday ( &_tend, NULL);   \
165                 _t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 );    \
166                 _t2 = ( double )   _tend.tv_sec + ( double )   _tend.tv_usec/ ( 1000*1000 );    \
167                 printf("BENCH:%s: %fs (real) %fs (cpu)\n", #name, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\
168         } while(0)
169 #else
170
171 #define BENCH(a)        (a)
172
173 #endif
174
175
176
177 #ifdef __cplusplus
178 }
179 #endif
180
181
182 #endif