1 //////////////////////////////////////////////////////////////////////
2 //
3 //                             Pixie
4 //
5 // Copyright � 1999 - 2003, Okan Arikan
6 //
7 // Contact: okan@cs.utexas.edu
8 //
9 //	This library is free software; you can redistribute it and/or
10 //	modify it under the terms of the GNU Lesser General Public
11 //	License as published by the Free Software Foundation; either
12 //	version 2.1 of the License, or (at your option) any later version.
13 //
14 //	This library is distributed in the hope that it will be useful,
15 //	but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //	Lesser General Public License for more details.
18 //
19 //	You should have received a copy of the GNU Lesser General Public
20 //	License along with this library; if not, write to the Free Software
21 //	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 ///////////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////////
25 //
26 //  File				:	reyes.h
27 //  Classes				:	CReyes
28 //  Description			:	The rasterizer class
29 //
30 ////////////////////////////////////////////////////////////////////////
31 #ifndef REYES_H
32 #define REYES_H
33 
34 #include "common/global.h"
35 #include "shading.h"
36 #include "object.h"
37 #include "renderer.h"
38 #include "ri_config.h"
39 
40 // Note:
41 // The low bits are spliced with the zfilter mode and used to dispatch in stochastic hider
42 // high bits are used in the primitive rasterization code to modify behavior
43 
44 const	unsigned int	RASTER_MOVING			=	1 << 0;		// The primitive is moving
45 const	unsigned int	RASTER_TRANSPARENT		=	1 << 1;		// The primitive is transparent
46 const	unsigned int	RASTER_POINT			=	1 << 2;		// The primitive is a point
47 const	unsigned int	RASTER_UNSHADED			=	1 << 3;		// The primitive has not been shaded (only displaced)
48 const	unsigned int	RASTER_FOCALBLUR		=	1 << 4;		// The primitive has focalblur
49 const	unsigned int	RASTER_EXTRASAMPLES		=	1 << 5;		// The primitive has extra samples to compute
50 const	unsigned int	RASTER_MATTE			=	1 << 6;		// The primitive is a matte
51 const	unsigned int	RASTER_LOD				=	1 << 7;		// The primitive has LOD
52 const	unsigned int	RASTER_UNDERCULL		=	1 << 8;		// The primitive requires underculling
53 const	unsigned int	RASTER_XTREME			=	1 << 9;		// The primitive has extreme motion blur/depth of field
54 const	unsigned int	RASTER_GLOBAL_MASK		=	(1 << 10) - 1;// This mask is used to block the lower fields
55 
56 const	unsigned int	RASTER_HIGHBITS_SHIFT	=	10;			// The shift needed to put bits in the higher fields
57 const	unsigned int	RASTER_DEPTHFILT_MASK	=	1;
58 
59 const	unsigned int	RASTER_DRAW_FRONT		=	1 << 10;	// Draw the front of the primitive
60 const	unsigned int	RASTER_DRAW_BACK		=	1 << 11;	// Draw the back of the primitive
61 const	unsigned int	RASTER_SHADE_HIDDEN		=	1 << 12;	// Shade the primitive even if occluded
62 const	unsigned int	RASTER_SHADE_BACKFACE	=	1 << 13;	// Shade the primitive even if backfacing
63 
64 
65 ///////////////////////////////////////////////////////////////////////
66 // Class				:	CReyes
67 // Description			:	This class is implementes a REYES like scan
68 //							line renderer
69 // Comments				:
70 class	CReyes : public CShadingContext {
71 protected:
72 
73 	///////////////////////////////////////////////////////////////////////
74 	// Class				:	CRasterPatch
75 	// Description			:	Holds an object associated with a bucket
76 	// Comments				:	The same instance of this class may be associated with multiple buckets in multiple threads
77 	class	CRasterObject {
78 	public:
79 			CObject				*object;				// The object
80 			CRasterObject		**next;					// The next object (one for each thread)
81 			int					refCount;				// The number of threads working on this object
82 			int					diced;					// TRUE if this object has already been diced
83 			int					grid;					// TRUE if this is a grid
84 			int					cached;					// TRUE if this is a cached object
85 
86 			int					xbound[2],ybound[2];	// The bound of the object on the screen, in samples
87 			float				zmin;					// The minimum z coordinate of the object (used for occlusion culling)
88 			TMutex				mutex;					// To secure the object
89 
90 	};
91 
92 	///////////////////////////////////////////////////////////////////////
93 	// Class				:	CRasterGrid
94 	// Description			:	This class encapsulates a shading grid
95 	//							line renderer
96 	// Comments				:
97 	class	CRasterGrid : public CRasterObject {
98 	public:
99 			float				*vertices;				// Array of vertices
100 			int					*bounds;				// The bound of the primitive (4 numbers per primitive)
101 			float				*sizes;					// The size of the primitive (only makes sense for points)
102 			EShadingDim			dim;					// Dimensionality (0,1 or 2)
103 			float				umin,umax,vmin,vmax;	// The parametric range
104 			int					udiv,vdiv;				// The number of division
105 			int					numVertices;			// The number of vertices
106 			int					flags;					// The primitive flags
107 	};
108 
109 
110 	///////////////////////////////////////////////////////////////////////
111 	// Class				:	CPqueue
112 	// Description			:	Priority queue specifically written for CRasterObject
113 	// Comments				:	I could have used the template in containers.h, but this one allows me to defer objects directly
114 	class CPqueue  {
115 	public:
116 								CPqueue(int ss=100)	{
117 									stepSize	=	ss;
118 									maxItems	=	stepSize;
119 									numItems	=	1;
120 									allItems	=	new CRasterObject*[maxItems];
121 								}
122 
~CPqueue()123 								~CPqueue()	{
124 									delete [] allItems;
125 								}
126 
insert(CRasterObject * cObject)127 					void		insert(CRasterObject *cObject) {
128 									int i,j;
129 
130 									// Expand the buffer
131 									if (numItems >= maxItems) {
132 										CRasterObject	**newItems;
133 										maxItems		+=	stepSize;
134 										newItems		=	new CRasterObject*[maxItems+1];
135 										memcpy(newItems,allItems,numItems*sizeof(CRasterObject*));
136 										delete [] allItems;
137 										allItems		=	newItems;
138 										stepSize		*=	2;
139 									}
140 
141 									// Insert the item
142 									i	= numItems++;
143 									j	= i >> 1;
144 									while ((i > 1) && (cObject->zmin < allItems[j]->zmin)) {
145 										allItems[i]	=	allItems[j];
146 										i			=	j;
147 										j			=	i >> 1;
148 
149 									}
150 
151 									allItems[i]		=	cObject;
152 								}
153 
get(TMutex & mutex)154 				CRasterObject	*get(TMutex &mutex) {
155 									int				i = 1, j;
156 									CRasterObject	*lItem,*cItem;
157 
158 									osLock(mutex);
159 
160 									if (numItems <= 1) {
161 										cItem	=	NULL;
162 									} else {
163 										cItem	=	allItems[1];
164 
165 										numItems--;
166 										lItem	=	allItems[numItems];
167 
168 										while (i <= numItems / 2) {
169 											j = 2 * i;
170 											if (j >= numItems) break;
171 
172 											if ((j < (numItems-1)) && (allItems[j]->zmin > allItems[j+1]->zmin))
173 												j++;
174 
175 											if (allItems[j]->zmin > lItem->zmin)
176 												break;
177 
178 											allItems[i]	=	allItems[j];
179 											i			=	j;
180 										}
181 										allItems[i]				=	lItem;
182 									}
183 
184 									if (cItem != NULL) osUnlock(mutex);
185 
186 									return cItem;
187 								}
188 
189 		CRasterObject			**allItems;					// Array of the heap
190 		int						numItems,maxItems,stepSize;	// Misc junk
191 	};
192 
193 
194 	///////////////////////////////////////////////////////////////////////
195 	// Class				:	CBucket
196 	// Description			:	Holds a bucket
197 	// Comments				:
198 	class	CBucket {
199 	public:
200 								CBucket();
201 								~CBucket();
202 
203 			CRasterObject		*objects;				// The list of objects waiting to be rendered
204 			CPqueue				*queue;					// If this is not null, we're currently rendering this bucket
205 	};
206 
207 
208 public:
209 
210 								CReyes(int thread);
211 								~CReyes();
212 
213 								// This function is called to to render
214 	void						renderingLoop();
215 
216 								// The following functions must be overriden by the child rasterizer
217 	virtual	void				rasterBegin(int,int,int,int,int)			=	0;
218 	virtual	void				rasterDrawPrimitives(CRasterGrid *)			=	0;
219 	virtual	void				rasterEnd(float *,int)						=	0;
220 
221 								// The following can be called from the "dice" function to insert an object into the scene
222 	void						drawObject(CObject *);									// Draw an object
223 	void						drawGrid(CSurface *,int,int,float,float,float,float);	// Draw a grid
224 	void						drawPoints(CSurface *,int);								// Draw points (RiPoints)
225 
226 								// Some stats
227 	int							numGridsRendered;
228 	int							numQuadsRendered;
229 	int							numGridsShaded;
230 	int							numGridsCreated;
231 	int							numVerticesCreated;
232 protected:
233 	float						maxDepth;										// The maximum opaque depth in the current bucket
234 
235 	static	int					extraPrimitiveFlags;							// These are the extra primitive flags
236 	static	int					numVertexSamples;								// The number of samples per pixel
237 
238 	void						shadeGrid(CRasterGrid *,int);					// Called by the child to force the shading of a grid
239 
probeArea(int * xbound,int * ybound,int bw,int bh,int bl,int bt,float zmin)240 	virtual int					probeArea(int *xbound,int *ybound, int bw, int bh, int bl, int bt, float zmin) {
241 									return TRUE;
242 								}
243 
244 private:
245 	void						copyPoints(int,float **,float *,int);			// Data movement (copy P only)
246 	void						copySamples(int,float **,float *,int);			// Data movement (copy the color + opacity + extra samples)
247 
248 	void						insertObject(CRasterObject *object);			// Add an object into the system
249 	void						insertGrid(CRasterGrid *,int);					// Insert a grid into the correct bucket
250 
251 	CRasterObject				*newObject(CObject *);							// Create a new object
252 	CRasterGrid					*newGrid(CSurface *,int,int,int);				// Create a new grid
253 	void						deleteObject(CRasterObject *);					// Delete an object (the object can also be a grid)
254 
255 	void						render();										// Render the current bucket
256 	void						skip();											// Skip the current bucket
257 
258 	CBucket						***buckets;										// All buckets
259 	TMutex						bucketMutex;									// Controls the accesses to the buckets
260 
261 	int							bucketPixelLeft;								// Left of the current bucket in pixels
262 	int							bucketPixelTop;									// Top of the current bucket in pixels
263 	int							bucketPixelWidth;								// Width of the current bucket in pixels
264 	int							bucketPixelHeight;								// Height of the current bucket in pixels
265 	int							tbucketLeft;									// Left of the current bucket in samples
266 	int							tbucketTop;										// Right of the current bucket in samples
267 	int							tbucketRight;
268 	int							tbucketBottom;
269 
270 
271 				///////////////////////////////////////////////////////////////////////
272 				// Class				:	CReyes
273 				// Method				:	distance2samples
274 				// Description			:	Project distances into the sample space
275 				// Return Value			:
276 				// Comments				:	(inline for speed)
distance2samples(int n,float * dist,float * P)277 				inline void		distance2samples(int n,float *dist,float *P) {
278 									if(CRenderer::projection == OPTIONS_PROJECTION_PERSPECTIVE) {
279 										for (;n>0;n--,P+=3,dist++) {
280 											*dist		=	CRenderer::dSampledx*CRenderer::imagePlane*dist[0]/P[COMP_Z];
281 										}
282 									} else {
283 										for (;n>0;n--,P+=3,dist++) {
284 											*dist		=	CRenderer::dSampledx*dist[0];
285 										}
286 									}
287 								}
288 
289 				///////////////////////////////////////////////////////////////////////
290 				// Class				:	CReyes
291 				// Method				:	camera2samples
292 				// Description			:	Project from camera space into the sample space
293 				// Return Value			:
294 				// Comments				:	(inline for speed)
camera2samples(int n,float * P)295 				inline void		camera2samples(int n,float *P) {
296 									if(CRenderer::projection == OPTIONS_PROJECTION_PERSPECTIVE) {
297 										for (;n>0;n--,P+=3) {
298 											P[COMP_X]	=	(CRenderer::imagePlane*P[COMP_X]/P[COMP_Z] - CRenderer::pixelLeft)*CRenderer::dSampledx;
299 											P[COMP_Y]	=	(CRenderer::imagePlane*P[COMP_Y]/P[COMP_Z] - CRenderer::pixelTop)*CRenderer::dSampledy;
300 										}
301 									} else {
302 										for (;n>0;n--,P+=3) {
303 											P[COMP_X]	=	(P[COMP_X] - CRenderer::pixelLeft)*CRenderer::dSampledx;
304 											P[COMP_Y]	=	(P[COMP_Y] - CRenderer::pixelTop)*CRenderer::dSampledy;
305 										}
306 									}
307 								}
308 
309 				///////////////////////////////////////////////////////////////////////
310 				// Class				:	CReyes
311 				// Method				:	camera2samples
312 				// Description			:	Project from camera space into the sample space
313 				// Return Value			:
314 				// Comments				:	(inline for speed)
camera2samples(float * P)315 				inline void		camera2samples(float *P) {
316 									if(CRenderer::projection == OPTIONS_PROJECTION_PERSPECTIVE) {
317 										P[COMP_X]	=	CRenderer::imagePlane*P[COMP_X]/P[COMP_Z];
318 										P[COMP_Y]	=	CRenderer::imagePlane*P[COMP_Y]/P[COMP_Z];
319 									}
320 
321 									P[COMP_X]	=	(P[COMP_X] - CRenderer::pixelLeft)*CRenderer::dSampledx;
322 									P[COMP_Y]	=	(P[COMP_Y] - CRenderer::pixelTop)*CRenderer::dSampledy;
323 								}
324 
325 };
326 
327 #endif
328 
329