1 /*
2  * apigeom.c - This file contains all of the API calls that are defined for
3  *         external driver code to use.
4  *
5  *  $Id: apigeom.c,v 1.8 2001/12/06 07:01:59 johns Exp $
6  */
7 
8 #include "machine.h"
9 #include "tachyon.h"
10 
11 void VNorm(apivector *); /* hack proto, should fix later */
12 
rt_polycylinder(SceneHandle scene,void * tex,apivector * points,int numpts,apiflt rad)13 void rt_polycylinder(SceneHandle scene, void * tex, apivector * points, int numpts, apiflt rad) {
14   apivector a;
15   int i;
16 
17   if ((points == NULL) || (numpts == 0)) {
18     return;
19   }
20 
21   if (numpts > 0) {
22     rt_sphere(scene, tex, points[0], rad);
23 
24     if (numpts > 1) {
25       for (i=1; i<numpts; i++) {
26         a.x = points[i].x - points[i-1].x;
27         a.y = points[i].y - points[i-1].y;
28         a.z = points[i].z - points[i-1].z;
29 
30         rt_fcylinder(scene, tex, points[i-1], a, rad);
31         rt_sphere(scene, tex, points[i], rad);
32       }
33     }
34   }
35 }
36 
rt_heightfield(SceneHandle scene,void * tex,apivector ctr,int m,int n,apiflt * field,apiflt wx,apiflt wy)37 void rt_heightfield(SceneHandle scene, void * tex, apivector ctr, int m, int n,
38                     apiflt * field, apiflt wx, apiflt wy) {
39   int xx,yy;
40   apivector v0, v1, v2;
41   apiflt xoff, yoff, zoff;
42 
43   xoff=ctr.x - (wx / 2.0);
44   yoff=ctr.z - (wy / 2.0);
45   zoff=ctr.y;
46 
47   for (yy=0; yy<(n-1); yy++) {
48     for (xx=0; xx<(m-1); xx++) {
49       v0.x=wx*(xx    )/(m*1.0) + xoff;
50       v0.y=field[(yy    )*m + (xx    )] + zoff;
51       v0.z=wy*(yy    )/(n*1.0) + yoff;
52 
53       v1.x=wx*(xx + 1)/(m*1.0) + xoff;
54       v1.y=field[(yy    )*m + (xx + 1)] + zoff;
55       v1.z=wy*(yy    )/(n*1.0) + yoff;
56 
57       v2.x=wx*(xx + 1)/(m*1.0) + xoff;
58       v2.y=field[(yy + 1)*m + (xx + 1)] + zoff;
59       v2.z=wy*(yy + 1)/(n*1.0) + yoff;
60 
61       rt_tri(scene, tex, v1, v0, v2);
62 
63       v0.x=wx*(xx    )/(m*1.0) + xoff;
64       v0.y=field[(yy    )*m + (xx    )] + zoff;
65       v0.z=wy*(yy    )/(n*1.0) + yoff;
66 
67       v1.x=wx*(xx    )/(m*1.0) + xoff;
68       v1.y=field[(yy + 1)*m + (xx    )] + zoff;
69       v1.z=wy*(yy + 1)/(n*1.0) + yoff;
70 
71       v2.x=wx*(xx + 1)/(m*1.0) + xoff;
72       v2.y=field[(yy + 1)*m + (xx + 1)] + zoff;
73       v2.z=wy*(yy + 1)/(n*1.0) + yoff;
74 
75       rt_tri(scene, tex, v0, v1, v2);
76     }
77   }
78 } /* end of heightfield */
79 
80 
rt_sheightfield(SceneHandle scene,void * tex,apivector ctr,int m,int n,apiflt * field,apiflt wx,apiflt wy)81 static void rt_sheightfield(SceneHandle scene, void * tex, apivector ctr, int m, int n,
82                     apiflt * field, apiflt wx, apiflt wy) {
83   apivector * vertices;
84   apivector * normals;
85   apivector offset;
86   apiflt xinc, yinc;
87   int x, y, addr;
88 
89   vertices = (apivector *) malloc(m*n*sizeof(apivector));
90   normals = (apivector *) malloc(m*n*sizeof(apivector));
91 
92   offset.x = ctr.x - (wx / 2.0);
93   offset.y = ctr.z - (wy / 2.0);
94   offset.z = ctr.y;
95 
96   xinc = wx / ((apiflt) m-1);
97   yinc = wy / ((apiflt) n-1);
98 
99   /* build vertex list */
100   for (y=0; y<n; y++) {
101     for (x=0; x<m; x++) {
102       addr = y*m + x;
103       vertices[addr] = rt_vector(
104         x * xinc + offset.x,
105         field[addr] + offset.z,
106         y * yinc + offset.y);
107     }
108   }
109 
110   /* build normals from vertex list */
111   for (x=1; x<m; x++) {
112     normals[x] = normals[(n - 1)*m + x] = rt_vector(0.0, 1.0, 0.0);
113   }
114   for (y=1; y<n; y++) {
115     normals[y*m] = normals[y*m + (m-1)] = rt_vector(0.0, 1.0, 0.0);
116   }
117   for (y=1; y<(n-1); y++) {
118     for (x=1; x<(m-1); x++) {
119       addr = y*m + x;
120 
121       normals[addr] = rt_vector(
122         -(field[addr + 1] - field[addr - 1]) / (2.0 * xinc),
123         1.0,
124         -(field[addr + m] - field[addr - m]) / (2.0 * yinc));
125 
126       VNorm(&normals[addr]);
127     }
128   }
129 
130   /* generate actual triangles */
131   for (y=0; y<(n-1); y++) {
132     for (x=0; x<(m-1); x++) {
133       addr = y*m + x;
134 
135       rt_stri(scene, tex, vertices[addr], vertices[addr + 1 + m], vertices[addr + 1],
136                    normals[addr], normals[addr + 1 + m], normals[addr + 1]);
137       rt_stri(scene, tex, vertices[addr], vertices[addr + m], vertices[addr + 1 + m],
138                    normals[addr], normals[addr + m], normals[addr + 1 + m]);
139     }
140   }
141 
142   free(normals);
143   free(vertices);
144 } /* end of smoothed heightfield */
145 
146 
adjust(apiflt * base,int xres,int yres,apiflt wx,apiflt wy,int xa,int ya,int x,int y,int xb,int yb,unsigned int * rndval)147 static void adjust(apiflt *base, int xres, int yres, apiflt wx, apiflt wy,
148                    int xa, int ya, int x, int y, int xb, int yb,
149                    unsigned int *rndval) {
150   apiflt d, v, len;
151 
152   len = sqrt(wx * wx + wy * wy);
153 
154   if (base[x + (xres*y)]==0.0) {
155     d=(abs(xa - xb) / (xres * 1.0))*wx + (abs(ya - yb) / (yres * 1.0))*wy;
156 
157     v= (base[xa + (xres*ya)] + base[xb + (xres*yb)]) / 2.0 +
158        ((((rt_rand(rndval) / RT_RAND_MAX) - 0.5)*d) / 4.0) * (len / 16.0);
159 
160     if (v < 0.0) v=0.0;
161     if (v > (xres + yres)) v=(xres + yres);
162     base[x + (xres * y)]=v;
163  }
164 }
165 
subdivide(apiflt * base,int xres,int yres,apiflt wx,apiflt wy,int x1,int y1,int x2,int y2,unsigned int * rndval)166 static void subdivide(apiflt *base, int xres, int yres, apiflt wx, apiflt wy,
167                       int x1, int y1, int x2, int y2, unsigned int *rndval) {
168   int x, y;
169 
170   if (((x2 - x1) < 2) && ((y2 - y1) < 2)) { return; }
171 
172   x=(x1 + x2) / 2;
173   y=(y1 + y2) / 2;
174 
175   adjust(base, xres, yres, wx, wy, x1, y1, x, y1, x2, y1, rndval);
176   adjust(base, xres, yres, wx, wy, x2, y1, x2, y, x2, y2, rndval);
177   adjust(base, xres, yres, wx, wy, x1, y2, x, y2, x2, y2, rndval);
178   adjust(base, xres, yres, wx, wy, x1, y1, x1, y, x1, y2, rndval);
179 
180 
181   if (base[x + xres*y]==0.0) {
182     base[x + (xres * y)]=(base[x1 + xres*y1] + base[x2 + xres*y1] +
183                           base[x2 + xres*y2] + base[x1 + xres*y2]   )/4.0;
184   }
185 
186   subdivide(base, xres, yres, wx, wy, x1, y1 ,x ,y, rndval);
187   subdivide(base, xres, yres, wx, wy, x, y1, x2, y, rndval);
188   subdivide(base, xres, yres, wx, wy, x, y, x2, y2, rndval);
189   subdivide(base, xres, yres, wx, wy, x1, y, x, y2, rndval);
190 }
191 
rt_landscape(SceneHandle scene,void * tex,int m,int n,apivector ctr,apiflt wx,apiflt wy)192 void rt_landscape(SceneHandle scene, void * tex, int m, int n,
193               	apivector ctr, apiflt wx, apiflt wy) {
194   int totalsize, x, y;
195   apiflt * field;
196   unsigned int rndval; /* random number.. */
197 
198   totalsize=m*n;
199   rndval = totalsize;
200 
201   field=(apiflt *) malloc(totalsize*sizeof(apiflt));
202 
203   for (y=0; y<n; y++) {
204     for (x=0; x<m; x++) {
205        field[x + y*m]=0.0;
206     }
207   }
208 
209   field[0 + 0            ] = rt_rand(&rndval) / RT_RAND_MAX;
210   field[m - 1            ] = rt_rand(&rndval) / RT_RAND_MAX;
211   field[0     + m*(n - 1)] = rt_rand(&rndval) / RT_RAND_MAX;
212   field[m - 1 + m*(n - 1)] = rt_rand(&rndval) / RT_RAND_MAX;
213 
214   subdivide(field, m, n, wx, wy, 0, 0, m-1, n-1, &rndval);
215 
216   rt_sheightfield(scene, tex, ctr, m, n, field, wx, wy);
217 
218   free(field);
219 }
220 
221