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