Fix for a crash which happened when a document couldn't be opened.
[AROS-Contrib.git] / fish / surf / poly.c
blobec6ee03014bde941d7053162f3d3c9b3402c5ba1
1 #include <proto/mathtrans.h>
2 #include "mytypes.h"
3 #include "scrnio.h"
4 #include "bezpt.h"
5 #include "revolve.h"
6 #include "control.h"
7 #include "poly.h"
8 #include "readilbm.h"
9 #include "menuexp.h"
11 bool SpecOn = false; /* specular lighting enable - default off */
13 float Ambience = DefAmbience;
14 float PtIntensity = (float)DefIntensity;
15 float Kd = DefKd,
16 Ks = DefKs;
18 Pt3 LightSrc = {
19 DefLightSrcX,
20 DefLightSrcY,
21 DefLightSrcZ
24 extern struct Library * MathTransBase;
26 static
27 Rhomboid *polylist = null,
28 *nextpoly;
30 MapRhomboid *mpolylist = null,
31 *mnextpoly;
34 void OutErr(char *);
35 void ClrWindow(bool);
36 void DrawRhomShade(Rhomboid *);
37 void DrawRhomFrame(ScrnPair *);
38 void DrawRhomMap(MapRhomboid *);
39 bool InitMapping();
41 static bool shadeflag;
43 long CalcMaxPolyNum() {
44 return( GetNumSegs() * BezMesh * RevMesh );
47 static
48 bool PrepPoly()
50 if( polylist ) free( (char *)polylist );
51 polylist = (Rhomboid *)malloc( CalcMaxPolyNum() * sizeof(Rhomboid));
52 if( !polylist ) {
53 OutErr("PrepPoly: not enough memory");
54 return( true );
56 nextpoly = polylist;
57 return(false); /* success = 0 */
61 static bool
62 PrepMPoly()
64 if( mpolylist ) free( (char *)mpolylist );
65 mpolylist = (MapRhomboid *)
66 malloc( CalcMaxPolyNum() * sizeof(MapRhomboid));
67 if( !mpolylist ) {
68 OutErr("PrepPoly: not enough memory");
69 return( true );
71 mnextpoly = mpolylist;
72 return(false); /* success = 0 */
77 * Multiply a vector by scalar quantity
79 void ScaleVec( fact, src, dst )
80 float fact;
81 Pt3 *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
89 * if possible
91 void Unitize( vec )
92 Pt3 *vec;
94 float len;
96 len = vec->x*vec->x + vec->y*vec->y + vec->z*vec->z;
97 len = sqrt( len );
98 if( len != 0.0 ) {
99 vec->x /= len;
100 vec->y /= len;
101 vec->z /= len;
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)
128 PtGen *vxlist[];
129 register Pt3 *normal;
131 int i, k, m;
132 Pt3 *j[3];
133 Pt3 v1, v2;
135 for( i = 0; i < RhomVxNum; i++ ) {
136 for( k = 0, m = 3; m--; k++ ) {
137 if( k == i ) {
138 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 ) {
147 continue;
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;
156 Unitize(normal);
157 return( false );
159 return(true);
164 * Euclidean dot product.
165 * I wonder what the minkowski dot product would look like
167 float DotProd( v1, v2 )
168 Pt3 *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;
186 Pt3 normal;
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
193 if( shadeflag ) {
194 Pt3 lvec;
195 Pt3 center;
196 float ptintens;
197 float ldotn; /* light vector dot normal */
199 * if cant compute normal, then junk polygon
201 if( CalcNormal( list, &normal )) {
202 return(false);
205 curpoly->intensity = Ambience;
206 center.x = ( list[0]->d3.x
207 + list[1]->d3.x
208 + list[2]->d3.x
209 + list[3]->d3.x)/4.0;
210 center.y = ( list[0]->d3.y
211 + list[1]->d3.y
212 + list[2]->d3.y
213 + list[3]->d3.y)/4.0;
214 center.z = ( list[0]->d3.z
215 + list[1]->d3.z
216 + list[2]->d3.z
217 + list[3]->d3.z)/4.0;
219 curpoly->depth = center.z;
221 CalcVector( &center, &LightSrc, &lvec );
222 Unitize( &lvec );
223 ldotn = DotProd( &lvec, &normal );
224 if( ldotn < 0 ) {
225 ptintens = PtIntensity * Kd * -ldotn;
226 curpoly->intensity += ptintens;
229 * calculate specular component
231 if( SpecOn && ldotn < 0 ) {
232 float Kspec, Is;
233 Pt3 rvec; /* lvec reflected through poly */
235 ScaleVec( 2*ldotn, &normal, &rvec );
236 CalcVector(&lvec, &rvec, &rvec );
237 Unitize( &center );
238 Kspec = DotProd( &rvec, &center);
240 if( Kspec <= 0.0 ) {
241 Is = Ks * Kspec * Kspec* PtIntensity;
242 curpoly->intensity += Is;
246 if( curpoly->intensity > 1.0 ) {
247 curpoly->intensity = 1.0;
250 else {
252 * calculate depth of polygon
253 * for now, try an average of the vertex depths
255 curpoly->depth =( list[0]->d3.z
256 + list[1]->d3.z
257 + list[2]->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;
268 return(true);
271 * passable procedure for creating polygons without mapping
273 static
274 void AcceptPoly(p0, p1, p2, p3)
275 PtGen *p0, *p1, *p2, *p3;
277 if( CreatePoly(nextpoly, p0, p1, p2,p3)) {
278 nextpoly++;
282 static
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;
289 mnextpoly++;
298 * compare the depth of two polygons for SortPoly
300 static int CmpDepth( a, b )
301 Rhomboid *a, *b;
303 if( a->depth < b->depth ) return(-1);
304 else if( a->depth > b->depth ) return(1);
305 else return(0);
308 static int CmpMDepth( a, b )
309 MapRhomboid *a, *b;
311 if( a->rhom.depth < b->rhom.depth ) return(-1);
312 else if( a->rhom.depth > b->rhom.depth ) return(1);
313 else return(0);
320 void RevNoShade() {
321 Rhomboid *i;
322 if( GetNumSegs() < 1 ) {
323 return;
326 ClrAbort();
327 shadeflag = false;
328 if( PrepPoly() ) return;
329 if( Revolve(AcceptPoly) ) return;
330 CurMode = NOTACTIVE;
332 qsort( (char *)polylist, nextpoly - polylist,
333 sizeof(Rhomboid), CmpDepth);
335 ClrWindow(false);
337 for( i = polylist; i< nextpoly; i++ ) {
338 if( AbortDraw ) return;
339 DrawRhomFrame( i->pt );
346 void RevShade() {
347 register Rhomboid *i;
349 if( !AllocDither()) return; /* not enough memory */
350 if( GetNumSegs() < 1 ) {
351 return;
353 CurMode = NOTACTIVE;
354 ClrAbort();
355 shadeflag = true;
356 if( PrepPoly() || Revolve(AcceptPoly) ) {
357 return;
359 qsort( (char *)polylist, nextpoly-polylist,
360 sizeof(Rhomboid), CmpDepth);
362 ClrWindow(false);
364 for( i = polylist; i< nextpoly; i++ ) {
365 if( AbortDraw ) return;
366 DrawRhomShade( i );
372 void RevMap() {
373 register MapRhomboid *i;
375 ClrAbort();
376 if( GetNumSegs() < 1 ) {
377 return;
379 if( InitMapping() ) {
380 return;
382 CurMode = NOTACTIVE;
383 shadeflag = true;
386 if( PrepMPoly() || Revolve(AcceptMPoly) ) {
387 return;
389 qsort( (char *)mpolylist, mnextpoly-mpolylist,
390 sizeof(MapRhomboid), CmpMDepth);
391 ClrWindow(false);
393 for( i = mpolylist; i< mnextpoly; i++ ) {
394 if( AbortDraw ) return;
395 DrawRhomMap(i);