1 #include <proto/mathtrans.h>
11 bool SpecOn
= false; /* specular lighting enable - default off */
13 float Ambience
= DefAmbience
;
14 float PtIntensity
= (float)DefIntensity
;
24 extern struct Library
* MathTransBase
;
27 Rhomboid
*polylist
= null
,
30 MapRhomboid
*mpolylist
= null
,
36 void DrawRhomShade(Rhomboid
*);
37 void DrawRhomFrame(ScrnPair
*);
38 void DrawRhomMap(MapRhomboid
*);
41 static bool shadeflag
;
43 long CalcMaxPolyNum() {
44 return( GetNumSegs() * BezMesh
* RevMesh
);
50 if( polylist
) free( (char *)polylist
);
51 polylist
= (Rhomboid
*)malloc( CalcMaxPolyNum() * sizeof(Rhomboid
));
53 OutErr("PrepPoly: not enough memory");
57 return(false); /* success = 0 */
64 if( mpolylist
) free( (char *)mpolylist
);
65 mpolylist
= (MapRhomboid
*)
66 malloc( CalcMaxPolyNum() * sizeof(MapRhomboid
));
68 OutErr("PrepPoly: not enough memory");
71 mnextpoly
= mpolylist
;
72 return(false); /* success = 0 */
77 * Multiply a vector by scalar quantity
79 void ScaleVec( fact
, src
, dst
)
83 dst
->x
= src
->x
* fact
;
84 dst
->y
= src
->y
* fact
;
85 dst
->z
= src
->z
* fact
;
88 * convert a vector to a unitized vector
96 len
= vec
->x
*vec
->x
+ vec
->y
*vec
->y
+ vec
->z
*vec
->z
;
106 * calculate a vector from two points
108 void CalcVector( src1
, src2
, dest
)
109 Pt3
*src1
, *src2
, *dest
;
111 dest
->x
= src1
->x
- src2
->x
;
112 dest
->y
= src1
->y
- src2
->y
;
113 dest
->z
= src1
->z
- src2
->z
;
120 * calculate a normal from a list of polygons. This routine does the
121 * logical trick of trying to exclude each point in turn if the
122 * normal can not be calculated, or something of the sort.
123 * a value of true is returned if a normal with a nonzero z component
124 * could not be calculated
127 bool CalcNormal( vxlist
, normal
)
129 register Pt3
*normal
;
135 for( i
= 0; i
< RhomVxNum
; i
++ ) {
136 for( k
= 0, m
= 3; m
--; k
++ ) {
140 j
[m
] = &vxlist
[k
]->d3
;
142 CalcVector( j
[1], j
[0], &v1
);
143 CalcVector( j
[2], j
[1], &v2
);
145 normal
->z
= v1
.x
*v2
.y
- v1
.y
*v2
.x
;
146 if( normal
->z
== 0 ) {
149 normal
->x
= v1
.y
*v2
.z
- v1
.z
*v2
.y
;
150 normal
->y
= v1
.z
*v2
.x
- v1
.x
*v2
.z
;
151 if( normal
->z
< 0 ) {
152 normal
->x
= -normal
->x
;
153 normal
->y
= -normal
->y
;
154 normal
->z
= -normal
->z
;
164 * Euclidean dot product.
165 * I wonder what the minkowski dot product would look like
167 float DotProd( v1
, v2
)
170 return( v1
->x
*v2
->x
+ v1
->y
*v2
->y
+ v1
->z
*v2
->z
);
178 * define a polygon as a set of four points
179 * returns true if polygon created
181 static bool CreatePoly(curpoly
, p0
, p1
, p2
, p3
)
182 register Rhomboid
*curpoly
;
183 PtGen
*p0
, *p1
, *p2
, *p3
;
187 PtGen
*list
[RhomVxNum
];
189 list
[0] = p0
; list
[1] = p1
; list
[2] = p2
; list
[3] = p3
;
191 * compute stuff needed only if producing shaded image
197 float ldotn
; /* light vector dot normal */
199 * if cant compute normal, then junk polygon
201 if( CalcNormal( list
, &normal
)) {
205 curpoly
->intensity
= Ambience
;
206 center
.x
= ( list
[0]->d3
.x
209 + list
[3]->d3
.x
)/4.0;
210 center
.y
= ( list
[0]->d3
.y
213 + list
[3]->d3
.y
)/4.0;
214 center
.z
= ( list
[0]->d3
.z
217 + list
[3]->d3
.z
)/4.0;
219 curpoly
->depth
= center
.z
;
221 CalcVector( ¢er
, &LightSrc
, &lvec
);
223 ldotn
= DotProd( &lvec
, &normal
);
225 ptintens
= PtIntensity
* Kd
* -ldotn
;
226 curpoly
->intensity
+= ptintens
;
229 * calculate specular component
231 if( SpecOn
&& ldotn
< 0 ) {
233 Pt3 rvec
; /* lvec reflected through poly */
235 ScaleVec( 2*ldotn
, &normal
, &rvec
);
236 CalcVector(&lvec
, &rvec
, &rvec
);
238 Kspec
= DotProd( &rvec
, ¢er
);
241 Is
= Ks
* Kspec
* Kspec
* PtIntensity
;
242 curpoly
->intensity
+= Is
;
246 if( curpoly
->intensity
> 1.0 ) {
247 curpoly
->intensity
= 1.0;
252 * calculate depth of polygon
253 * for now, try an average of the vertex depths
255 curpoly
->depth
=( list
[0]->d3
.z
258 + list
[3]->d3
.z
)/4.0;
261 * store index to screen coordinates
263 curpoly
->pt
[0] = p0
->d2
;
264 curpoly
->pt
[1] = p1
->d2
;
265 curpoly
->pt
[2] = p2
->d2
;
266 curpoly
->pt
[3] = p3
->d2
;
271 * passable procedure for creating polygons without mapping
274 void AcceptPoly(p0
, p1
, p2
, p3
)
275 PtGen
*p0
, *p1
, *p2
, *p3
;
277 if( CreatePoly(nextpoly
, p0
, p1
, p2
,p3
)) {
283 void AcceptMPoly( p0
, p1
, p2
, p3
)
284 PtGen
*p0
, *p1
, *p2
, *p3
;
286 if( CreatePoly(&mnextpoly
->rhom
, p0
, p1
, p2
,p3
)) {
287 mnextpoly
->bezindex
= RevImageB
;
288 mnextpoly
->revindex
= RevImageR
;
298 * compare the depth of two polygons for SortPoly
300 static int CmpDepth( a
, b
)
303 if( a
->depth
< b
->depth
) return(-1);
304 else if( a
->depth
> b
->depth
) return(1);
308 static int CmpMDepth( a
, b
)
311 if( a
->rhom
.depth
< b
->rhom
.depth
) return(-1);
312 else if( a
->rhom
.depth
> b
->rhom
.depth
) return(1);
322 if( GetNumSegs() < 1 ) {
328 if( PrepPoly() ) return;
329 if( Revolve(AcceptPoly
) ) return;
332 qsort( (char *)polylist
, nextpoly
- polylist
,
333 sizeof(Rhomboid
), CmpDepth
);
337 for( i
= polylist
; i
< nextpoly
; i
++ ) {
338 if( AbortDraw
) return;
339 DrawRhomFrame( i
->pt
);
347 register Rhomboid
*i
;
349 if( !AllocDither()) return; /* not enough memory */
350 if( GetNumSegs() < 1 ) {
356 if( PrepPoly() || Revolve(AcceptPoly
) ) {
359 qsort( (char *)polylist
, nextpoly
-polylist
,
360 sizeof(Rhomboid
), CmpDepth
);
364 for( i
= polylist
; i
< nextpoly
; i
++ ) {
365 if( AbortDraw
) return;
373 register MapRhomboid
*i
;
376 if( GetNumSegs() < 1 ) {
379 if( InitMapping() ) {
386 if( PrepMPoly() || Revolve(AcceptMPoly
) ) {
389 qsort( (char *)mpolylist
, mnextpoly
-mpolylist
,
390 sizeof(MapRhomboid
), CmpMDepth
);
393 for( i
= mpolylist
; i
< mnextpoly
; i
++ ) {
394 if( AbortDraw
) return;