Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

open-axiom repository from github

24005 views
1
/*
2
Copyright (C) 1991-2002, The Numerical ALgorithms Group Ltd.
3
All rights reserved.
4
Copyright (C) 2007-2010, Gabriel Dos Reis.
5
All rights reserved.
6
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are
9
met:
10
11
- Redistributions of source code must retain the above copyright
12
notice, this list of conditions and the following disclaimer.
13
14
- Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the following disclaimer in
16
the documentation and/or other materials provided with the
17
distribution.
18
19
- Neither the name of The Numerical ALgorithms Group Ltd. nor the
20
names of its contributors may be used to endorse or promote products
21
derived from this software without specific prior written permission.
22
23
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
27
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
*/
35
36
#define _SMOOTHSHADE_C
37
#include "openaxiom-c-macros.h"
38
39
#include <string.h>
40
#include <math.h>
41
#include <stdlib.h>
42
43
#include "header.h"
44
#include "draw.h"
45
#include "volume.h"
46
#include "mode.h" /* for #define components */
47
48
#include "spadcolors.h"
49
#include "Gfun.H1"
50
#include "util.H1"
51
#include "XSpadFill.h"
52
#include "all_3d.H1"
53
54
#define SAFE_VALUE 892347
55
56
57
58
59
60
61
char
62
get_cBuffer_axes(int ix)
63
{
64
if( ix >=0 && ix <ARRAY_WIDTH) return (cBuffer[ix].axes);
65
return ('0');
66
}
67
68
void
69
put_cBuffer_axes(int ix,char val)
70
{
71
if( ix >=0 && ix <ARRAY_WIDTH) cBuffer[ix].axes = val;
72
}
73
74
int
75
get_cBuffer_indx(int ix)
76
{
77
if( ix >=0 && ix <ARRAY_WIDTH) return (cBuffer[ix].indx);
78
return (-1);
79
}
80
81
void
82
put_cBuffer_indx(int ix,int val)
83
{
84
if( ix >=0 && ix <ARRAY_WIDTH) cBuffer[ix].indx = val;
85
}
86
87
void
88
put_zBuffer(int ix,float val)
89
{
90
if (ix >=0 && ix <ARRAY_WIDTH) zBuffer[ix] = val;
91
}
92
93
float
94
get_zBuffer(int ix)
95
{
96
return (zBuffer[ix]);
97
}
98
99
void
100
put_imageX(int ix,char val)
101
{
102
if (ix <=0 && ix <vwInfo.width) imageX->data[ix] = val;
103
}
104
105
106
107
108
/***************************
109
* void drawPhongSpan() *
110
* *
111
* This routine sets the *
112
* buffer values for each *
113
* span of pixels which *
114
* intersect the current *
115
* scanline. *
116
***************************/
117
void
118
drawPhongSpan(triple pt,float N[3],int dFlag)
119
{
120
int xpixel,hue,shade;
121
float colorindx, col;
122
triple hs;
123
124
125
/* negative values of xleft and xright have been pushed to machine0 */
126
127
xpixel = (int)xleft;
128
129
130
while (xpixel <= (int)xright) {
131
/* if z is closer to viewer than value in zBuffer continue */
132
if ( (zC < get_zBuffer(xpixel)) ) {
133
/* get the intensity for current point */
134
col = phong(pt,N);
135
put_cBuffer_axes(xpixel,'0');
136
put_zBuffer(xpixel,zC);
137
/* if mono (bw dsply) do black and white semi-random dithering */
138
if (mono || (dFlag == PSoption) || viewport->monoOn) {
139
if (get_random() < 100.0*exp((double)-1.3*(pi_sq*(col-.2)*(col-.2)))) {
140
put_cBuffer_indx(xpixel,black);
141
} else {
142
put_cBuffer_indx(xpixel,white);
143
}
144
} else {
145
/* glossy shading for one hue else dithered for many hues */
146
if (viewport->hueOffset == viewport->hueTop && !smoothError) {
147
colorindx = (float)(smoothConst+1) * col;
148
if (colorindx > (smoothConst+1)) colorindx = smoothConst+1;
149
put_cBuffer_indx(xpixel,XPixelColor((int)colorindx-1));
150
} else { /* probabalistic multi-hued dithering */
151
hs = norm_dist();
152
hue = (int)(intersectColor[0]+hs.x/20.0);
153
/* cannot dither out of color map range */
154
if (viewport->hueOffset < viewport->hueTop) {
155
if (hue < viewport->hueOffset)
156
hue = viewport->hueOffset;
157
else {
158
if (hue > viewport->hueTop)
159
hue = viewport->hueTop;
160
}
161
} else {
162
if (hue < viewport->hueTop)
163
hue = viewport->hueTop;
164
else {
165
if (hue > viewport->hueOffset)
166
hue = viewport->hueOffset;
167
}
168
}
169
col += hs.y/6.0; /* perturb intensity */
170
if (col > 1.0) put_cBuffer_indx(xpixel,white);
171
else {
172
if (col < 0.0) put_cBuffer_indx(xpixel,black);
173
else {
174
shade = (int)(col * 4.0);
175
put_cBuffer_indx(xpixel,XSolidColor(hue,shade));
176
}
177
}
178
}
179
}
180
} /* zC < zBuffer */
181
zC += dzdx;
182
if (viewport->hueOffset != viewport->hueTop || smoothError ||
183
viewport->monoOn)
184
intersectColor[0] += dcolor;
185
N[0] += dnorm.x; N[1] += dnorm.y; N[2] += dnorm.z;
186
pt.x += dpt.x; pt.y += dpt.y; pt.z += dpt.z;
187
xpixel++;
188
} /* while each pixel */
189
190
}
191
192
193
/***************************
194
* void scanPhong() *
195
* *
196
* This routine takes all *
197
* polygons that intersect *
198
* with the current scan- *
199
* line and calculates the *
200
* intersecting x and z *
201
* points as well as the *
202
* color at each point. *
203
* Interpolation is done *
204
* according to Phong. *
205
***************************/
206
207
void
208
scanPhong(int dFlag)
209
{
210
viewTriple *p1, *p2;
211
polyList *polygon;
212
poly *p;
213
int i,num,xtemp,numttt;
214
int *anIndex, *start, *end;
215
float x1,x2,y1,y2,z2,zright,wx1,wx2,wy1,wy2,wz1,wz2;
216
float intersectionx[2], intersectionz[2];
217
float c1,c2,colortemp,ztemp,dY,diffy,diffx,n1[3],n2[3],NV[3];
218
triple ntemp, intersectPt[2], ptemp, pt, intersectN[2];
219
220
/* polygon list intersecting the current scanline, will be modified to
221
edge list structure */
222
polygon = scanList[scanline];
223
while (polygon != NIL(polyList) && polygon->polyIndx != NIL(poly) ) {
224
/* for each polygon in the list */
225
p = polygon->polyIndx;
226
/* don't include clipped polygons */
227
if ( ! ( p->partialClipPz ||
228
p->totalClipPz ||
229
(viewData.clipStuff && (p->partialClip || p->totalClip ) ) ) ) {
230
num = 0; /* 0 & 1, for the 2 edges of polygon that intersect scanline */
231
numttt =0;
232
233
if ((scanline >= (int)p->pymin) && (scanline <= (int)p->pymax)) {
234
/* which edges of the polygon intersect the scanline */
235
for (i=0, anIndex=p->indexPtr; i<p->numpts; i++) {
236
start = anIndex + i;
237
p1 = refPt3D(viewData,*(start));
238
x1 = p1->px; y1 = p1->py; zC = p1->pz; c1 = p1->sc;
239
/* if (x1 < machine0){ x1 = machine0; } */
240
wx1 = p1->wx; wy1 = p1->wy; wz1 = p1->wz;
241
n1[0] = p1->norm[0]; n1[1] = p1->norm[1]; n1[2] = p1->norm[2];
242
end = (i != (p->numpts - 1)) ? anIndex + (i + 1) : anIndex;
243
p2 = refPt3D(viewData,*(end));
244
x2 = p2->px; y2 = p2->py; z2 = p2->pz; c2 = p2->sc;
245
/* if (x2 < machine0){ x2 = machine0; } */
246
wx2 = p2->wx; wy2 = p2->wy; wz2 = p2->wz;
247
n2[0] = p2->norm[0]; n2[1] = p2->norm[1]; n2[2] = p2->norm[2];
248
/* find beginning and end for intersecting edge */
249
if ((scanline < y1 && scanline >= y2) ||
250
(scanline >= y1 && scanline < y2)) {
251
dY = (float)scanline - y1;
252
diffy = y2 - y1;
253
if (absolute(diffy) < 0.01) diffy = 1.0;
254
intersectionx[num] = x1 + ((x2-x1)/diffy) * dY;
255
intersectionz[num] = zC + ((z2-zC)/diffy) * dY;
256
if (viewport->hueOffset != viewport->hueTop || smoothError ||
257
viewport->monoOn)
258
intersectColor[num] = c1 + ((c2 - c1)/diffy) * dY;
259
intersectN[num].x = n1[0] + ((n2[0] - n1[0])/diffy)*dY;
260
intersectN[num].y = n1[1] + ((n2[1] - n1[1])/diffy)*dY;
261
intersectN[num].z = n1[2] + ((n2[2] - n1[2])/diffy)*dY;
262
intersectPt[num].x = wx1 + ((wx2 - wx1)/diffy)*dY;
263
intersectPt[num].y = wy1 + ((wy2 - wy1)/diffy)*dY;
264
intersectPt[num].z = wz1 + ((wz2 - wz1)/diffy)*dY;
265
num = 1-num;
266
numttt++;
267
} /* if edge intersects scanline */
268
} /* for each edge */
269
if (numttt>=2) { /* if numttt 0 or 1 something has gone wrong */
270
xleft = intersectionx[0]; xright = intersectionx[1];
271
zC = intersectionz[0]; zright = intersectionz[1];
272
/* edges are drawn from left to right, so switch if necessary */
273
if (xright < xleft) {
274
xtemp = xright; xright = xleft; xleft = xtemp;
275
ztemp = zright; zright = zC; zC = ztemp;
276
if (viewport->hueOffset != viewport->hueTop || smoothError ||
277
viewport->monoOn) {
278
colortemp = intersectColor[1];
279
intersectColor[1] = intersectColor[0];
280
intersectColor[0] = colortemp;
281
}
282
ntemp = intersectN[1]; intersectN[1] = intersectN[0];
283
intersectN[0] = ntemp;
284
ptemp = intersectPt[1];
285
intersectPt[1] = intersectPt[0];
286
intersectPt[0] = ptemp;
287
}
288
diffx = xright - xleft;
289
if (absolute(diffx) > .01) {
290
if (viewport->hueOffset != viewport->hueTop || smoothError ||
291
viewport->monoOn)
292
dcolor = (intersectColor[1] - intersectColor[0]) / diffx;
293
dnorm.x = (intersectN[1].x - intersectN[0].x) / diffx;
294
dnorm.y = (intersectN[1].y - intersectN[0].y) / diffx;
295
dnorm.z = (intersectN[1].z - intersectN[0].z) / diffx;
296
dpt.x = (intersectPt[1].x - intersectPt[0].x) / diffx;
297
dpt.y = (intersectPt[1].y - intersectPt[0].y) / diffx;
298
dpt.z = (intersectPt[1].z - intersectPt[0].z) / diffx;
299
dzdx = (zright - zC) / diffx;
300
} else {
301
if (viewport->hueOffset != viewport->hueTop || smoothError ||
302
viewport->monoOn)
303
dcolor = intersectColor[1];
304
dnorm.x = 0.0; dnorm.y = 0.0; dnorm.z = 0.0;
305
dpt.x = 0.0; dpt.y = 0.0; dpt.z = 0.0;
306
dzdx = 0.0;
307
}
308
NV[0] = intersectN[0].x;
309
NV[1] = intersectN[0].y;
310
NV[2] = intersectN[0].z;
311
pt.x = intersectPt[0].x;
312
pt.y = intersectPt[0].y;
313
pt.z = intersectPt[0].z;
314
drawPhongSpan(pt,NV,dFlag);
315
} /* numttt guard */
316
} /* if scanline intersect */
317
} /* clipped */
318
polygon = polygon->next;
319
} /* while still polygons */
320
321
}
322
323
/********************************************
324
* boxTObuffer() writes the projection of *
325
* the x,y bounding box to the z-buffer. *
326
********************************************/
327
328
void
329
boxTObuffer(void)
330
{
331
int xpix,i,j,k,count,decision;
332
int xA,xB,yA,yB;
333
float x,xend,y,yend,diffy,dX,dY,dXY,intersectionx;
334
335
for (i=0;i<6;i++) {
336
if (box[i].inside) {
337
for (j=0; j<3; j++) {
338
quadMesh[j].x = box[i].pointsPtr[j]->px;
339
quadMesh[j].y = box[i].pointsPtr[j]->py;
340
}
341
342
intersectionx = 0.0;
343
for (k=0; k<2; k++) {
344
xA = quadMesh[k].x; yA = quadMesh[k].y;
345
xB = quadMesh[k+1].x; yB = quadMesh[k+1].y;
346
347
/*
348
if (xA > graphWindowAttrib.width+1) xA = graphWindowAttrib.width+1;
349
if (xB > graphWindowAttrib.width+1) xB = graphWindowAttrib.width+1;
350
if (yA > graphWindowAttrib.height) yA = graphWindowAttrib.height;
351
if (yB > graphWindowAttrib.height) yB = graphWindowAttrib.height;
352
if (xA < 0) xA = 0; if (xB < 0) xB = 0;
353
if (yA < 0) yA = 0; if (yB < 0) yB = 0;
354
*/
355
x = xA; xend = xB; y = yA; yend = yB;
356
diffy = (float)scanline - y;
357
dX = xend - x; dY = yend - y;
358
if (absolute(dY) > machine0) {
359
dXY = dX/dY;
360
} else {
361
dXY = dX;
362
}
363
364
if (dXY < 0.0) dXY = -dXY;
365
366
if ((scanline == (int)y) && (absolute(dY) <= 1.0)) {
367
if (x <= xend) {
368
for (xpix = (int)x; xpix <= (int)xend; xpix++) {
369
put_cBuffer_axes(xpix,'b');
370
}
371
} else {
372
for (xpix = (int)x; xpix >= (int)xend; xpix--) {
373
put_cBuffer_axes(xpix,'b');
374
}
375
}
376
} else {
377
if (xend < x)
378
decision = (scanline < y && scanline >= yend) ||
379
(scanline > y && scanline <= yend);
380
else
381
decision = (scanline <= y && scanline > yend) ||
382
(scanline >= y && scanline < yend);
383
if (decision) {
384
intersectionx = x + dX/dY * diffy;
385
for (count = (int)intersectionx;
386
count <= (int)intersectionx + (int)dXY; count++) {
387
put_cBuffer_axes(count,'b');
388
}
389
}
390
}
391
}
392
393
}
394
}
395
396
}
397
398
/********************************************
399
* clipboxTObuffer() writes the projection *
400
* of the x,y,z clipping region box to the *
401
* z-buffer. *
402
********************************************/
403
404
void
405
clipboxTObuffer(void)
406
{
407
int xpix,i,j,k,count,decision;
408
int xA,xB,yA,yB;
409
float x,xend,y,yend,diffy,dX,dY,dXY,intersectionx;
410
411
for (i=0;i<6;i++) {
412
if (clipBox[i].inside) {
413
for (j=0; j<3; j++) {
414
quadMesh[j].x = clipBox[i].pointsPtr[j]->px;
415
quadMesh[j].y = clipBox[i].pointsPtr[j]->py;
416
}
417
418
intersectionx = 0.0;
419
for (k=0; k<2; k++) {
420
xA = quadMesh[k].x; yA = quadMesh[k].y;
421
xB = quadMesh[k+1].x; yB = quadMesh[k+1].y;
422
/*
423
424
if (xA > graphWindowAttrib.width+1) xA = graphWindowAttrib.width+1;
425
if (xB > graphWindowAttrib.width+1) xB = graphWindowAttrib.width+1;
426
if (yA > graphWindowAttrib.height) yA = graphWindowAttrib.height;
427
if (yB > graphWindowAttrib.height) yB = graphWindowAttrib.height;
428
if (xA < 0) xA = 0; if (xB < 0) xB = 0;
429
if (yA < 0) yA = 0; if (yB < 0) yB = 0;
430
*/
431
x = xA; xend = xB; y = yA; yend = yB;
432
diffy = (float)scanline - y;
433
dX = xend - x; dY = yend - y;
434
if (absolute(dY) > machine0) {
435
dXY = dX/dY;
436
} else {
437
dXY = dX;
438
}
439
if (dXY < 0.0) dXY = -dXY;
440
441
if ((scanline == (int)y) && (absolute(dY) <= 1.0)) {
442
if (x <= xend) {
443
for (xpix = (int)x; xpix <= (int)xend; xpix++) {
444
put_cBuffer_axes(xpix,'c');
445
}
446
} else {
447
for (xpix = (int)x; xpix >= (int)xend; xpix--) {
448
put_cBuffer_axes(xpix,'c');
449
}
450
}
451
} else {
452
if (xend < x)
453
decision = (scanline < y && scanline >= yend) ||
454
(scanline > y && scanline <= yend);
455
else
456
decision = (scanline <= y && scanline > yend) ||
457
(scanline >= y && scanline < yend);
458
if (decision) {
459
intersectionx = x + dX/dY * diffy;
460
for (count = (int)intersectionx;
461
count <= (int)intersectionx + (int)dXY; count++) {
462
put_cBuffer_axes(count,'c');
463
}
464
}
465
}
466
}
467
468
}
469
}
470
471
}
472
473
474
475
/********************************************
476
* axesTObuffer() writes the projection of *
477
* the x,y,z axes to the z-buffer. *
478
********************************************/
479
480
void
481
axesTObuffer(void)
482
{
483
int xpix,i,count,decision;
484
int xA,xB,yA,yB;
485
float x,xend,y,yend,diffy,dX,dY,dXY,intersectionx;
486
float zA,zB,z,zend;
487
float dZ,dZX,dZY,intersectionz;
488
489
intersectionz = 0.0; intersectionx = 0.0;
490
for (i=0; i<3; i++) {
491
xA = axesXY[i][0]; yA = axesXY[i][1]; zA = axesZ[i][0];
492
xB = axesXY[i][2]; yB = axesXY[i][3]; zB = axesZ[i][1];
493
/*
494
if (xA > graphWindowAttrib.width+1) xA = graphWindowAttrib.width+1;
495
if (xB > graphWindowAttrib.width+1) xB = graphWindowAttrib.width+1;
496
if (yA > graphWindowAttrib.height) yA = graphWindowAttrib.height;
497
if (yB > graphWindowAttrib.height) yB = graphWindowAttrib.height;
498
if (xA < 0) xA = 0; if (xB < 0) xB = 0;
499
if (yA < 0) yA = 0; if (yB < 0) yB = 0;
500
*/
501
x = xA; xend = xB; y = yA; yend = yB; z = zA; zend = zB;
502
diffy = (float)scanline - y;
503
dX = xend - x; dY = yend - y; dZ = zend - z;
504
dZY = dZ/dY;
505
dXY = dX/dY;
506
if (dXY < 0.0) dXY = -dXY;
507
dZX = dZ/dX;
508
509
if ((scanline == (int)y) && (absolute(dY) <= 1.0)) {
510
if (x <= xend) {
511
for (xpix = (int)x; xpix <= (int)xend; xpix++) {
512
put_cBuffer_axes(xpix,'a');
513
put_zBuffer(xpix,z + dZY * diffy);
514
} /* for x */
515
} else {
516
for (xpix = (int)x; xpix >= (int)xend; xpix--) {
517
put_cBuffer_axes(xpix,'a');
518
put_zBuffer(xpix,z + dZY * diffy);
519
} /* for x */
520
}
521
} else {
522
if (xend < x)
523
decision = (scanline < y && scanline >= yend) ||
524
(scanline > y && scanline <= yend);
525
else
526
decision = (scanline <= y && scanline > yend) ||
527
(scanline >= y && scanline < yend);
528
if (decision) {
529
intersectionx = x + dX/dY * diffy;
530
intersectionz = z + dZY * diffy;
531
for (count = (int)intersectionx;
532
count <= (int)intersectionx + (int)dXY; count++) {
533
put_cBuffer_axes(count,'a');
534
put_zBuffer(count,intersectionz);
535
intersectionz += dZX;
536
}
537
} /* if edge intersects scanline */
538
}
539
} /* for each axes */
540
541
}
542
543
/********************************************
544
* scanLines() scanline z-buffer algorithm *
545
* initialize z-buffer and color buffer for *
546
* all scanlines. *
547
********************************************/
548
549
void
550
scanLines(int dFlag)
551
{
552
unsigned long pixColor;
553
int i;
554
char tempA;
555
556
if (dFlag == Xoption) {
557
if (viewmap_valid) {
558
XFreePixmap(dsply,viewmap);
559
viewmap_valid=0;
560
}
561
viewmap = XCreatePixmap(/* display */ dsply,
562
/* drawable */ viewport->viewWindow,
563
/* width */ vwInfo.width,
564
/* height */ vwInfo.height,
565
/* depth */ DefaultDepth(dsply,scrn));
566
viewmap_valid =1;
567
GSetForeground(trashGC,(float)backgroundColor,dFlag);
568
XFillRectangle(dsply,viewmap,trashGC,0,0,vwInfo.width,vwInfo.height);
569
XFillRectangle(dsply,viewport->viewWindow,trashGC,0,0,
570
vwInfo.width,vwInfo.height);
571
} else {
572
GSetForeground(GC9991,
573
1.0-(float)((int)(psShadeMax-0.3*psShadeMax)-1)*psShadeMul,dFlag);
574
quadMesh[0].x = 0; quadMesh[0].y = 0;
575
quadMesh[1].x = graphWindowAttrib.width+2;
576
quadMesh[1].y = 0;
577
quadMesh[2].x = graphWindowAttrib.width+2;
578
quadMesh[2].y = graphWindowAttrib.height;
579
quadMesh[3].x = 0;
580
quadMesh[3].y = graphWindowAttrib.height;
581
quadMesh[4].x = 0; quadMesh[4].y = 0;
582
PSFillPolygon(GC9991, quadMesh, 5);
583
}
584
585
if (graphWindowAttrib.height >= physicalHeight)
586
graphWindowAttrib.height = physicalHeight - 1;
587
if (graphWindowAttrib.width >= physicalWidth)
588
graphWindowAttrib.width = physicalWidth - 1;
589
if (dFlag == Xoption)
590
strcpy(control->message," Display Scanlines ");
591
else
592
strcpy(control->message," Writing Output ");
593
writeControlMessage();
594
595
scanline = graphWindowAttrib.height-1;
596
597
imageX = XCreateImage(/* display */ dsply,
598
/* visual */ DefaultVisual(dsply,scrn),
599
/* depth */ DefaultDepth(dsply,scrn),
600
/* format */ ZPixmap,
601
/* offset */ 0,
602
/* data */ 0,
603
/* width */ vwInfo.width,
604
/* height */ 1,
605
/* bitmap_pad */ 32,
606
/* bytes_per_line */ 0);
607
imageX->data = (char *)malloc(imageX->bytes_per_line);
608
609
610
while (scanline >= 0 && keepDrawingViewport()) {
611
/* initialize buffer values for scanline */
612
pixColor = backgroundColor;
613
for (i=0; i < (int)graphWindowAttrib.width; i++) {
614
put_zBuffer(i,10000.0);
615
put_cBuffer_indx(i,-1);
616
put_cBuffer_axes(i,'0');
617
if (mono || viewport->monoOn)
618
if ((scanline % 2) == 0)
619
if ((i % 2) == 0) {
620
if (i>=0 && i<vwInfo.width) XPutPixel(imageX,i,0,backgroundColor);
621
}
622
else {
623
if (i>=0 && i<vwInfo.width) XPutPixel(imageX,i,0,foregroundColor);
624
}
625
else
626
if ((i % 2) == 0) {
627
if (i>=0 && i<vwInfo.width) XPutPixel(imageX,i,0,foregroundColor);
628
}
629
else {
630
if (i>=0 && i<vwInfo.width) XPutPixel(imageX,i,0,backgroundColor);
631
}
632
else {
633
if (i>=0 && i<vwInfo.width) XPutPixel(imageX,i,0,backgroundColor);
634
}
635
}
636
637
/* writes the axes info to the buffers */
638
if (viewData.box) boxTObuffer();
639
if (viewData.clipbox) clipboxTObuffer();
640
if (viewport->axesOn) axesTObuffer();
641
642
/* fill buffers for current scanline */
643
scanPhong(dFlag);
644
645
for (i=0; i < (int)graphWindowAttrib.width; i++) {
646
/* include bounding region info */
647
if (viewData.box) {
648
if (get_cBuffer_axes(i) == 'b') {
649
if (dFlag==Xoption) {
650
if (mono || (viewport->monoOn)) pixColor = foregroundColor;
651
else pixColor = boxInline;
652
if (i >=0 && i<vwInfo.width) XPutPixel(imageX,i,0,pixColor);
653
} else {
654
GSetForeground(GC9991, psBlack, dFlag );
655
GDrawPoint(viewport->viewWindow, GC9991, i,scanline,dFlag);
656
}
657
}
658
}
659
/* include clipping box info */
660
if (viewData.clipbox) {
661
if (get_cBuffer_axes(i)== 'c') {
662
if (dFlag==Xoption) {
663
if (mono || (viewport->monoOn)) pixColor = foregroundColor;
664
else pixColor = clipBoxInline;
665
if (i >=0 && i<vwInfo.width) XPutPixel(imageX,i,0,pixColor);
666
} else {
667
GSetForeground(GC9991, psBlack, dFlag );
668
GDrawPoint(viewport->viewWindow, GC9991, i,scanline,dFlag);
669
}
670
}
671
}
672
/* include axes info */
673
if (viewport->axesOn) {
674
if (get_cBuffer_axes(i) == 'a') {
675
if (dFlag == Xoption) {
676
if (mono || (viewport->monoOn)) pixColor = foregroundColor;
677
else pixColor = monoColor(axesColor);
678
if (i >=0 && i<vwInfo.width) XPutPixel(imageX,i,0,pixColor);
679
} else {
680
GSetForeground(GC9991,psBlack,dFlag);
681
GDrawPoint(viewport->viewWindow, GC9991, i,scanline,dFlag);
682
}
683
} /* if buffer slot is an axes point */
684
tempA = get_cBuffer_axes(i);
685
} else tempA = '0'; /* else axes not on */
686
687
if (get_cBuffer_indx(i) >= 0 && (tempA == '0')) {
688
if (dFlag == Xoption) {
689
GSetForeground(trashGC,(float)get_cBuffer_indx(i),dFlag);
690
pixColor = get_cBuffer_indx(i);
691
if (i >=0 && i<vwInfo.width) XPutPixel(imageX,i,0,pixColor);
692
}
693
else {
694
GSetForeground(GC9991,(float)get_cBuffer_indx(i),dFlag);
695
GDrawPoint(viewport->viewWindow, GC9991, i,scanline,dFlag);
696
}
697
}
698
} /* for each pixel in scanline */
699
700
if (dFlag == Xoption) {
701
XPutImage(dsply,viewport->viewWindow,trashGC,imageX,0,0,0,
702
scanline,vwInfo.width,1);
703
XPutImage(dsply,viewmap,trashGC,imageX,0,0,0,
704
scanline,vwInfo.width,1);
705
}
706
707
scanline--;
708
709
} /* while each scanline */
710
XDestroyImage(imageX);
711
712
}
713
714
/*************************************
715
* void freePolyList(); *
716
* *
717
* frees up the global scanList l-l *
718
*************************************/
719
720
void
721
freePolyList (void)
722
{
723
polyList *P, *nextP;
724
int i;
725
726
for (i = 0; (i < ARRAY_HEIGHT); i++) {
727
P = scanList[i];
728
while((P != NIL(polyList))) {
729
nextP = P->next;
730
free(P);
731
P = nextP;
732
}
733
}
734
735
} /* freePolyList() */
736
737
738
/********************************************
739
* showAxesLabels() writes the axes labels *
740
* onto the viewmap of a graph. *
741
********************************************/
742
743
void
744
showAxesLabels(int dFlag)
745
{
746
int xcoord2,ycoord2;
747
748
if (dFlag == Xoption)
749
if (mono || (viewport->monoOn))
750
GSetForeground(globGC,(float)foregroundColor,dFlag);
751
else
752
GSetForeground(globGC,(float)monoColor(labelColor),dFlag);
753
else GSetForeground(GC9991,psBlack,dFlag);
754
755
/* axes label for X */
756
if ((int)axesZ[0][0] >= (int)axesZ[0][2]) {
757
if (axesXY[0][2] < axesXY[0][0]) xcoord2 = axesXY[0][2]-5;
758
else xcoord2 = axesXY[0][2] + 5;
759
if (axesXY[0][3] < axesXY[0][1]) ycoord2 = axesXY[0][3]-5;
760
else ycoord2 = axesXY[0][3] + 5;
761
if (!viewport->yzOn) {
762
if (dFlag == Xoption)
763
GDrawString(globGC,viewmap,xcoord2,ycoord2,"X",1,dFlag);
764
else
765
GDrawString(GC9991,viewport->viewWindow,xcoord2,ycoord2,"X",1,dFlag);
766
}
767
}
768
769
/* axes label for Y */
770
if ((int)axesZ[1][0] >= (int)axesZ[1][1]) {
771
if (axesXY[1][2] < axesXY[1][0]) xcoord2 = axesXY[1][2]-5;
772
else xcoord2 = axesXY[1][2] + 5;
773
if (axesXY[1][3] < axesXY[1][1]) ycoord2 = axesXY[1][3]-5;
774
else ycoord2 = axesXY[1][3] + 5;
775
if (!viewport->xzOn) {
776
if (dFlag == Xoption)
777
GDrawString(globGC,viewmap,xcoord2,ycoord2,"Y",1,dFlag);
778
else
779
GDrawString(GC9991,viewport->viewWindow,xcoord2,ycoord2,"Y",1,dFlag);
780
}
781
}
782
783
/* axes label for Z */
784
if ((int)axesZ[2][0] >= (int)axesZ[2][1]) {
785
if (axesXY[2][2] < axesXY[2][0]) xcoord2 = axesXY[2][2]-5;
786
else xcoord2 = axesXY[2][2] + 5;
787
if (axesXY[2][3] < axesXY[2][1]) ycoord2 = axesXY[2][3]-5;
788
else ycoord2 = axesXY[2][3] + 5;
789
if (!viewport->xyOn) {
790
if (dFlag == Xoption)
791
GDrawString(globGC,viewmap,xcoord2,ycoord2,"Z",1,dFlag);
792
else
793
GDrawString(GC9991,viewport->viewWindow,xcoord2,ycoord2,"Z",1,dFlag);
794
}
795
}
796
}
797
798
799
800
/********************************************
801
* changeColorMap() modifies the color map *
802
* for moving in and out of smooth shading. *
803
********************************************/
804
805
void
806
changeColorMap(void)
807
{
808
int okay, i, hue, *index;
809
poly *cp;
810
viewTriple *pt;
811
812
strcpy(control->message," Make New Color Map ");
813
writeControlMessage();
814
if ((viewport->hueOffset == viewport->hueTop) &&
815
!mono && !viewport->monoOn) {
816
817
/* colormap is not an even distribution across spectrum */
818
/* see spadcolors.c code to understand why this is done */
819
820
if (viewport->hueTop < 11) smoothHue = viewport->hueTop * 6;
821
else
822
if (viewport->hueTop > 10 && viewport->hueTop < 16) {
823
smoothHue = viewport->hueTop*20 - 140;
824
}
825
else {
826
smoothHue = viewport->hueTop*12 - 12;
827
}
828
829
if (redoColor) {
830
/* reallocate colormap for new hue */
831
redoColor = no;
832
if (pixelSetFlag) {
833
FreePixels(dsply,colorMap,smoothConst+1);
834
}
835
okay = makeNewColorMap(dsply,colorMap,smoothHue);
836
if (okay) {
837
pixelSetFlag = yes;
838
smoothError = no; }
839
else {
840
pixelSetFlag = no;
841
smoothError = yes; }
842
} /* if redoColor */
843
} else {
844
redoDither = no;
845
if (pixelSetFlag && !mono) {
846
FreePixels(dsply,colorMap,smoothConst);
847
pixelSetFlag = no;
848
redoColor = no;
849
multiColorFlag = yes;
850
}
851
if (!mono && !viewport->monoOn) {
852
cp = quickList;
853
while (cp != NIL(poly) && keepDrawingViewport()) {
854
for (i = 0, index = cp->indexPtr;
855
i < cp->numpts; i++, index++) {
856
pt = refPt3D(viewData,*(index));
857
/* get hue for each point if multi-dithering is used */
858
if (absolute(cp->color) > 1.0)
859
hue = floor(absolute(cp->color));
860
else
861
hue = floor(absolute(cp->color) * viewport->numberOfHues) +
862
viewport->hueOffset;
863
pt->sc = (float)hue;
864
} /* for each point in polygon */
865
cp = cp->next;
866
}
867
} /* multi-color dither */
868
} /* else hueOffset != hueTop */
869
}
870
871
872
/***********************
873
* void drawPhong() *
874
* *
875
* A general routine *
876
* for displaying a *
877
* list of polygons *
878
* using a simple *
879
* scanline z-buffer *
880
* algorithm with *
881
* phong shading. *
882
***********************/
883
884
void
885
drawPhong(int dFlag)
886
{
887
888
poly *p, *head;
889
polyList *s;
890
int i,j,hue;
891
int *anIndex, redo;
892
viewTriple *aPoint, *polyPt;
893
894
redo = (recalc || redoSmooth);
895
if (redo || redoColor || redoDither) {
896
rotated = no; zoomed = no; translated = no;
897
switchedPerspective = no; changedEyeDistance = no;
898
redoSmooth = no; movingLight = no;
899
900
/* If only a color change don't recalculate polygon info. */
901
if (!redo) {
902
/* glossy shading if a single hue is indicated */
903
changeColorMap();
904
scanLines(dFlag);
905
/* if axes are on then show axes labels */
906
if (viewport->axesOn) showAxesLabels(dFlag);
907
908
/* show pixmap of image */
909
XCopyArea(dsply,viewmap,viewport->viewWindow,trashGC,0,0,
910
vwInfo.width,vwInfo.height,0,0);
911
} else {
912
if (keepDrawingViewport()) {
913
if (!firstTime && !(scanline > 0)) {
914
strcpy(control->message," Freeing Polygons ");
915
writeControlMessage();
916
freeListOfPolygons(quickList);
917
freePointResevoir();
918
}
919
if (keepDrawingViewport()) {
920
strcpy(control->message," Collecting Polygons ");
921
writeControlMessage();
922
quickList = copyPolygons(viewData.polygons);
923
924
if (keepDrawingViewport()) {
925
strcpy(control->message," Projecting Polygons ");
926
writeControlMessage();
927
projectAllPolys(quickList);
928
if (keepDrawingViewport()) {
929
strcpy(control->message,
930
" Setting Polygon Extremes ");
931
writeControlMessage();
932
minMaxPolygons(quickList);
933
if (keepDrawingViewport()) {
934
strcpy(control->message,
935
" Sorting Polygons ");
936
writeControlMessage();
937
quickList = msort(quickList,0,viewData.numPolygons,
938
polyCompare);
939
calcEyePoint();
940
head = p = quickList;
941
942
/* glossy shading if a single hue is indicated */
943
changeColorMap();
944
945
for (i=0, aPoint=viewData.points;
946
i<viewData.numOfPoints; i++,aPoint++) {
947
aPoint->norm[0]= 0.0;
948
aPoint->norm[1]= 0.0;
949
aPoint->norm[2]= 0.0;
950
}
951
freePolyList();
952
for (i = 0; i < ARRAY_HEIGHT; i++)
953
scanList[i] = NIL(polyList);
954
/* for each polygon */
955
/* calculate average normal for each vertex */
956
strcpy(control->message,
957
" Build Polygon Lists ");
958
writeControlMessage();
959
p = head;
960
while ((p != NIL(poly)) && keepDrawingViewport()) {
961
962
for (j = 0, anIndex = p->indexPtr;
963
j < p->numpts; j++, anIndex++) {
964
polyPt = refPt3D(viewData,*(anIndex));
965
polyPt->norm[0] += p->N[0];
966
polyPt->norm[1] += p->N[1];
967
polyPt->norm[2] += p->N[2];
968
normalizeVector(polyPt->norm);
969
/* get hue for each point if multi-dithering is used */
970
if ((viewport->hueOffset != viewport->hueTop ||
971
smoothError) && !mono) {
972
if (absolute(p->color) > 1.0) {
973
hue = floor(absolute(p->color));
974
} else {
975
hue = floor(absolute(p->color) *
976
viewport->numberOfHues) +
977
viewport->hueOffset;
978
}
979
polyPt->sc = (float)hue;
980
} /* multi-color dither */
981
} /* for each point in polygon */
982
983
if ( ! ( p->partialClipPz ||
984
p->totalClipPz ||
985
(viewData.clipStuff && (p->partialClip || p->totalClip ) ) ) ) {
986
/* put polygon in each scanline list it intersects */
987
for (i=(int)p->pymin; i<= (int)p->pymax; i++) {
988
if ( (i>=0) && (i<ARRAY_HEIGHT ) ){
989
s = (polyList *)saymem("smoothShade.c",1,sizeof(polyList));
990
s->polyIndx = p;
991
s->next = scanList[i];
992
scanList[i] = s;
993
}
994
} /* put polygon in each scanline it intersects */
995
} /* if polygon not clipped */
996
p = p->next;
997
} /* while still polygons */
998
999
scanLines(dFlag);
1000
1001
/* if axes are on then show axes labels */
1002
if (viewport->axesOn) showAxesLabels(dFlag);
1003
1004
/* show pixmap of image */
1005
XCopyArea(dsply,viewmap,viewport->viewWindow,trashGC,0,0,
1006
vwInfo.width,vwInfo.height,0,0);
1007
/* freePolyList(scanList); */
1008
1009
} /* keepDrawingViewport() after setting extreme values */
1010
} /* keepDrawingViewport() after projecting all polygons */
1011
} /* keepDrawingViewport() after collecting polygons */
1012
} /* keepDrawingViewport() after freeing polygons */
1013
} /* keepDrawingViewport() after recalc */
1014
finishedList = !(scanline>0);
1015
if (firstTime) firstTime = no;
1016
} /* not only a color change */
1017
1018
} else { /* else just redisplay current pixmap of image */
1019
XCopyArea(dsply,viewmap,viewport->viewWindow,trashGC,0,0,
1020
vwInfo.width,vwInfo.height,0,0);
1021
}
1022
clearControlMessage();
1023
strcpy(control->message,viewport->title);
1024
writeControlMessage();
1025
1026
} /* drawPhong */
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038