Tachyon (current)  Current Main Branch
apigeom.c
Go to the documentation of this file.
1 /*
2  * apigeom.c - This file contains all of the API calls that are defined for
3  * external driver code to use.
4  *
5  * (C) Copyright 1994-2022 John E. Stone
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * $Id: apigeom.c,v 1.16 2022/03/13 23:46:29 johns Exp $
9  *
10  */
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <math.h>
16 #include "tachyon.h"
17 
18 void VNorm(apivector *); /* hack proto, should fix later */
19 
20 void rt_polycylinder(SceneHandle scene, void * tex, apivector * points, int numpts, flt rad) {
21  apivector a;
22  int i;
23 
24  if ((points == NULL) || (numpts == 0)) {
25  return;
26  }
27 
28  if (numpts > 0) {
29  rt_sphere(scene, tex, points[0], rad);
30 
31  if (numpts > 1) {
32  for (i=1; i<numpts; i++) {
33  a.x = points[i].x - points[i-1].x;
34  a.y = points[i].y - points[i-1].y;
35  a.z = points[i].z - points[i-1].z;
36 
37  rt_fcylinder(scene, tex, points[i-1], a, rad);
38  rt_sphere(scene, tex, points[i], rad);
39  }
40  }
41  }
42 }
43 
44 void rt_polycylinder3fv(SceneHandle scene, void * tex,
45  const float *points, int numpts, float rad) {
46  float a[3];
47  int i;
48 
49  if ((points == NULL) || (numpts == 0)) {
50  return;
51  }
52 
53  if (numpts > 0) {
54  rt_sphere3fv(scene, tex, points, rad);
55 
56  if (numpts > 1) {
57  for (i=1; i<numpts; i++) {
58  int addr = i*3;
59  a[0] = points[addr ] - points[addr - 3];
60  a[1] = points[addr + 1] - points[addr - 2];
61  a[2] = points[addr + 2] - points[addr - 1];
62 
63  rt_fcylinder3fv(scene, tex, &points[addr-3], a, rad);
64  rt_sphere3fv(scene, tex, &points[addr], rad);
65  }
66  }
67  }
68 }
69 
70 void rt_heightfield(SceneHandle scene, void * tex, apivector ctr, int m, int n,
71  flt * field, flt wx, flt wy) {
72  int xx,yy;
73  apivector v0, v1, v2;
74  flt xoff, yoff, zoff;
75 
76  xoff=ctr.x - (wx / 2.0);
77  yoff=ctr.z - (wy / 2.0);
78  zoff=ctr.y;
79 
80  for (yy=0; yy<(n-1); yy++) {
81  for (xx=0; xx<(m-1); xx++) {
82  v0.x=wx*(xx )/(m*1.0) + xoff;
83  v0.y=field[(yy )*m + (xx )] + zoff;
84  v0.z=wy*(yy )/(n*1.0) + yoff;
85 
86  v1.x=wx*(xx + 1)/(m*1.0) + xoff;
87  v1.y=field[(yy )*m + (xx + 1)] + zoff;
88  v1.z=wy*(yy )/(n*1.0) + yoff;
89 
90  v2.x=wx*(xx + 1)/(m*1.0) + xoff;
91  v2.y=field[(yy + 1)*m + (xx + 1)] + zoff;
92  v2.z=wy*(yy + 1)/(n*1.0) + yoff;
93 
94  rt_tri(scene, tex, v1, v0, v2);
95 
96  v0.x=wx*(xx )/(m*1.0) + xoff;
97  v0.y=field[(yy )*m + (xx )] + zoff;
98  v0.z=wy*(yy )/(n*1.0) + yoff;
99 
100  v1.x=wx*(xx )/(m*1.0) + xoff;
101  v1.y=field[(yy + 1)*m + (xx )] + zoff;
102  v1.z=wy*(yy + 1)/(n*1.0) + yoff;
103 
104  v2.x=wx*(xx + 1)/(m*1.0) + xoff;
105  v2.y=field[(yy + 1)*m + (xx + 1)] + zoff;
106  v2.z=wy*(yy + 1)/(n*1.0) + yoff;
107 
108  rt_tri(scene, tex, v0, v1, v2);
109  }
110  }
111 } /* end of heightfield */
112 
113 
114 static void rt_sheightfield(SceneHandle scene, void * tex, apivector ctr, int m, int n,
115  flt * field, flt wx, flt wy) {
116  apivector * vertices;
117  apivector * normals;
118  apivector offset;
119  flt xinc, yinc;
120  int x, y, addr;
121 
122  vertices = (apivector *) malloc(m*n*sizeof(apivector));
123  normals = (apivector *) malloc(m*n*sizeof(apivector));
124 
125  offset.x = ctr.x - (wx / 2.0);
126  offset.y = ctr.z - (wy / 2.0);
127  offset.z = ctr.y;
128 
129  xinc = wx / ((flt) m-1);
130  yinc = wy / ((flt) n-1);
131 
132  /* build vertex list */
133  for (y=0; y<n; y++) {
134  for (x=0; x<m; x++) {
135  addr = y*m + x;
136  vertices[addr] = rt_vector(
137  x * xinc + offset.x,
138  field[addr] + offset.z,
139  y * yinc + offset.y);
140  }
141  }
142 
143  /* build normals from vertex list */
144  for (x=1; x<m; x++) {
145  normals[x] = normals[(n - 1)*m + x] = rt_vector(0.0, 1.0, 0.0);
146  }
147  for (y=1; y<n; y++) {
148  normals[y*m] = normals[y*m + (m-1)] = rt_vector(0.0, 1.0, 0.0);
149  }
150  for (y=1; y<(n-1); y++) {
151  for (x=1; x<(m-1); x++) {
152  addr = y*m + x;
153 
154  normals[addr] = rt_vector(
155  -(field[addr + 1] - field[addr - 1]) / (2.0 * xinc),
156  1.0,
157  -(field[addr + m] - field[addr - m]) / (2.0 * yinc));
158 
159  VNorm(&normals[addr]);
160  }
161  }
162 
163  /* generate actual triangles */
164  for (y=0; y<(n-1); y++) {
165  for (x=0; x<(m-1); x++) {
166  addr = y*m + x;
167 
168  rt_stri(scene, tex, vertices[addr], vertices[addr + 1 + m], vertices[addr + 1],
169  normals[addr], normals[addr + 1 + m], normals[addr + 1]);
170  rt_stri(scene, tex, vertices[addr], vertices[addr + m], vertices[addr + 1 + m],
171  normals[addr], normals[addr + m], normals[addr + 1 + m]);
172  }
173  }
174 
175  free(normals);
176  free(vertices);
177 } /* end of smoothed heightfield */
178 
179 
180 static void adjust(flt *base, int xres, int yres, flt wx, flt wy,
181  int xa, int ya, int x, int y, int xb, int yb,
182  unsigned int *rndval) {
183  flt d, v, len;
184 
185  len = SQRT(wx * wx + wy * wy);
186 
187  if (base[x + (xres*y)]==0.0) {
188  d=(abs(xa - xb) / (xres * 1.0))*wx + (abs(ya - yb) / (yres * 1.0))*wy;
189 
190  v= (base[xa + (xres*ya)] + base[xb + (xres*yb)]) / 2.0 +
191  ((((rt_rand(rndval) * RT_RAND_MAX_INV) - 0.5)*d) / 4.0) * (len / 16.0);
192 
193  if (v < 0.0) v=0.0;
194  if (v > (xres + yres)) v=(xres + yres);
195  base[x + (xres * y)]=v;
196  }
197 }
198 
199 static void subdivide(flt *base, int xres, int yres, flt wx, flt wy,
200  int x1, int y1, int x2, int y2, unsigned int *rndval) {
201  int x, y;
202 
203  if (((x2 - x1) < 2) && ((y2 - y1) < 2)) { return; }
204 
205  x=(x1 + x2) / 2;
206  y=(y1 + y2) / 2;
207 
208  adjust(base, xres, yres, wx, wy, x1, y1, x, y1, x2, y1, rndval);
209  adjust(base, xres, yres, wx, wy, x2, y1, x2, y, x2, y2, rndval);
210  adjust(base, xres, yres, wx, wy, x1, y2, x, y2, x2, y2, rndval);
211  adjust(base, xres, yres, wx, wy, x1, y1, x1, y, x1, y2, rndval);
212 
213 
214  if (base[x + xres*y]==0.0) {
215  base[x + (xres * y)]=(base[x1 + xres*y1] + base[x2 + xres*y1] +
216  base[x2 + xres*y2] + base[x1 + xres*y2] )/4.0;
217  }
218 
219  subdivide(base, xres, yres, wx, wy, x1, y1 ,x ,y, rndval);
220  subdivide(base, xres, yres, wx, wy, x, y1, x2, y, rndval);
221  subdivide(base, xres, yres, wx, wy, x, y, x2, y2, rndval);
222  subdivide(base, xres, yres, wx, wy, x1, y, x, y2, rndval);
223 }
224 
225 void rt_landscape(SceneHandle scene, void * tex, int m, int n,
226  apivector ctr, flt wx, flt wy) {
227  int totalsize, x, y;
228  flt * field;
229  unsigned int rndval; /* random number.. */
230 
231  totalsize=m*n;
232  rndval = totalsize;
233 
234  field=(flt *) malloc(totalsize*sizeof(flt));
235 
236  for (y=0; y<n; y++) {
237  for (x=0; x<m; x++) {
238  field[x + y*m]=0.0;
239  }
240  }
241 
242  field[0 + 0 ] = rt_rand(&rndval) * RT_RAND_MAX_INV;
243  field[m - 1 ] = rt_rand(&rndval) * RT_RAND_MAX_INV;
244  field[0 + m*(n - 1)] = rt_rand(&rndval) * RT_RAND_MAX_INV;
245  field[m - 1 + m*(n - 1)] = rt_rand(&rndval) * RT_RAND_MAX_INV;
246 
247  subdivide(field, m, n, wx, wy, 0, 0, m-1, n-1, &rndval);
248 
249  rt_sheightfield(scene, tex, ctr, m, n, field, wx, wy);
250 
251  free(field);
252 }
253 
unsigned int rt_rand(unsigned int *idum)
Definition: util.c:324
#define RT_RAND_MAX_INV
Definition: util.h:72
static void rt_sheightfield(SceneHandle scene, void *tex, apivector ctr, int m, int n, flt *field, flt wx, flt wy)
Definition: apigeom.c:114
void rt_landscape(SceneHandle scene, void *tex, int m, int n, apivector ctr, flt wx, flt wy)
Define an auto-generated height field.
Definition: apigeom.c:225
static void subdivide(flt *base, int xres, int yres, flt wx, flt wy, int x1, int y1, int x2, int y2, unsigned int *rndval)
Definition: apigeom.c:199
static void adjust(flt *base, int xres, int yres, flt wx, flt wy, int xa, int ya, int x, int y, int xb, int yb, unsigned int *rndval)
Definition: apigeom.c:180
void VNorm(apivector *)
void rt_heightfield(SceneHandle scene, void *tex, apivector ctr, int m, int n, flt *field, flt wx, flt wy)
Define an axis-aligned height field.
Definition: apigeom.c:70
void rt_sphere(SceneHandle scene, void *tex, apivector ctr, flt rad)
Define a sphere with associated texture, center, and radius.
Definition: api.c:1212
void rt_sphere3fv(SceneHandle scene, void *tex, const float *ctr, float rad)
Define a sphere with associated texture, center, and radius.
Definition: api.c:1216
double flt
generic floating point number, using double
Definition: tachyon.h:47
void rt_tri(SceneHandle voidscene, void *tex, apivector v0, apivector v1, apivector v2)
Define a flat-shaded triangle.
Definition: api.c:1224
flt x
X coordinate or direction component.
Definition: tachyon.h:54
flt y
Y coordinate or direction component.
Definition: tachyon.h:55
void rt_fcylinder(SceneHandle scene, void *tex, apivector ctr, apivector axis, flt rad)
Define a finite-length cylinder.
Definition: api.c:1173
void * SceneHandle
Definition: tachyon.h:51
#define SQRT(x)
Definition: util.h:31
void rt_stri(SceneHandle voidscene, void *tex, apivector v0, apivector v1, apivector v2, apivector n0, apivector n1, apivector n2)
Define a smooth-shaded triangle using interpolated vertex normals.
Definition: api.c:1252
apivector rt_vector(flt x, flt y, flt z)
Helper function to make vectors.
Definition: api.c:159
void rt_fcylinder3fv(SceneHandle scene, void *tex, const float *ctr, const float *axis, float rad)
Define a finite-length cylinder.
Definition: api.c:1177
void rt_polycylinder(SceneHandle scene, void *tex, apivector *points, int numpts, flt rad)
Define a sequence of connected cylinders.
Definition: apigeom.c:20
Tachyon public API function prototypes and declarations used to drive the ray tracing engine...
void rt_polycylinder3fv(SceneHandle scene, void *tex, const float *points, int numpts, float rad)
Define a sequence of connected cylinders.
Definition: apigeom.c:44
flt z
Z coordinate or direction component.
Definition: tachyon.h:56