1 /*
2     Copyright (c) 2005-2021 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 /*
18     The original source for this example is
19     Copyright (c) 1994-2008 John E. Stone
20     All rights reserved.
21 
22     Redistribution and use in source and binary forms, with or without
23     modification, are permitted provided that the following conditions
24     are met:
25     1. Redistributions of source code must retain the above copyright
26        notice, this list of conditions and the following disclaimer.
27     2. Redistributions in binary form must reproduce the above copyright
28        notice, this list of conditions and the following disclaimer in the
29        documentation and/or other materials provided with the distribution.
30     3. The name of the author may not be used to endorse or promote products
31        derived from this software without specific prior written permission.
32 
33     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34     OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36     ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43     SUCH DAMAGE.
44 */
45 
46 /*
47  * api.cpp - This file contains all of the API calls that are defined for
48  *         external driver code to use.
49  */
50 
51 #include "machine.hpp"
52 #include "types.hpp"
53 #include "api.hpp"
54 #include "macros.hpp"
55 #include "vector.hpp"
56 
57 #define MyVNorm(a) VNorm((vector *)a)
58 
rt_polycylinder(void * tex,vector * points,int numpts,apiflt rad)59 void rt_polycylinder(void *tex, vector *points, int numpts, apiflt rad) {
60     vector a;
61     int i;
62 
63     if ((points == nullptr) || (numpts == 0)) {
64         return;
65     }
66 
67     if (numpts > 0) {
68         rt_sphere(tex, points[0], rad);
69 
70         if (numpts > 1) {
71             for (i = 1; i < numpts; i++) {
72                 a.x = points[i].x - points[i - 1].x;
73                 a.y = points[i].y - points[i - 1].y;
74                 a.z = points[i].z - points[i - 1].z;
75 
76                 rt_fcylinder(tex, points[i - 1], a, rad);
77                 rt_sphere(tex, points[i], rad);
78             }
79         }
80     }
81 }
82 
rt_heightfield(void * tex,vector ctr,int m,int n,apiflt * field,apiflt wx,apiflt wy)83 void rt_heightfield(void *tex, vector ctr, int m, int n, apiflt *field, apiflt wx, apiflt wy) {
84     int xx, yy;
85     vector v0, v1, v2;
86     apiflt xoff, yoff, zoff;
87 
88     xoff = ctr.x - (wx / 2.0);
89     yoff = ctr.z - (wy / 2.0);
90     zoff = ctr.y;
91 
92     for (yy = 0; yy < (n - 1); yy++) {
93         for (xx = 0; xx < (m - 1); xx++) {
94             v0.x = wx * (xx) / (m * 1.0) + xoff;
95             v0.y = field[(yy)*m + (xx)] + zoff;
96             v0.z = wy * (yy) / (n * 1.0) + yoff;
97 
98             v1.x = wx * (xx + 1) / (m * 1.0) + xoff;
99             v1.y = field[(yy)*m + (xx + 1)] + zoff;
100             v1.z = wy * (yy) / (n * 1.0) + yoff;
101 
102             v2.x = wx * (xx + 1) / (m * 1.0) + xoff;
103             v2.y = field[(yy + 1) * m + (xx + 1)] + zoff;
104             v2.z = wy * (yy + 1) / (n * 1.0) + yoff;
105 
106             rt_tri(tex, v1, v0, v2);
107 
108             v0.x = wx * (xx) / (m * 1.0) + xoff;
109             v0.y = field[(yy)*m + (xx)] + zoff;
110             v0.z = wy * (yy) / (n * 1.0) + yoff;
111 
112             v1.x = wx * (xx) / (m * 1.0) + xoff;
113             v1.y = field[(yy + 1) * m + (xx)] + zoff;
114             v1.z = wy * (yy + 1) / (n * 1.0) + yoff;
115 
116             v2.x = wx * (xx + 1) / (m * 1.0) + xoff;
117             v2.y = field[(yy + 1) * m + (xx + 1)] + zoff;
118             v2.z = wy * (yy + 1) / (n * 1.0) + yoff;
119 
120             rt_tri(tex, v0, v1, v2);
121         }
122     }
123 } /* end of heightfield */
124 
125 static void
rt_sheightfield(void * tex,vector ctr,int m,int n,apiflt * field,apiflt wx,apiflt wy)126 rt_sheightfield(void *tex, vector ctr, int m, int n, apiflt *field, apiflt wx, apiflt wy) {
127     vector *vertices;
128     vector *normals;
129     vector offset;
130     apiflt xinc, yinc;
131     int x, y, addr;
132 
133     vertices = (vector *)malloc(m * n * sizeof(vector));
134     normals = (vector *)malloc(m * n * sizeof(vector));
135 
136     offset.x = ctr.x - (wx / 2.0);
137     offset.y = ctr.z - (wy / 2.0);
138     offset.z = ctr.y;
139 
140     xinc = wx / ((apiflt)m);
141     yinc = wy / ((apiflt)n);
142 
143     /* build vertex list */
144     for (y = 0; y < n; y++) {
145         for (x = 0; x < m; x++) {
146             addr = y * m + x;
147             vertices[addr] =
148                 rt_vector(x * xinc + offset.x, field[addr] + offset.z, y * yinc + offset.y);
149         }
150     }
151 
152     /* build normals from vertex list */
153     for (x = 1; x < m; x++) {
154         normals[x] = normals[(n - 1) * m + x] = rt_vector(0.0, 1.0, 0.0);
155     }
156     for (y = 1; y < n; y++) {
157         normals[y * m] = normals[y * m + (m - 1)] = rt_vector(0.0, 1.0, 0.0);
158     }
159     for (y = 1; y < (n - 1); y++) {
160         for (x = 1; x < (m - 1); x++) {
161             addr = y * m + x;
162 
163             normals[addr] = rt_vector(-(field[addr + 1] - field[addr - 1]) / (2.0 * xinc),
164                                       1.0,
165                                       -(field[addr + m] - field[addr - m]) / (2.0 * yinc));
166 
167             MyVNorm(&normals[addr]);
168         }
169     }
170 
171     /* generate actual triangles */
172     for (y = 0; y < (n - 1); y++) {
173         for (x = 0; x < (m - 1); x++) {
174             addr = y * m + x;
175 
176             rt_stri(tex,
177                     vertices[addr],
178                     vertices[addr + 1 + m],
179                     vertices[addr + 1],
180                     normals[addr],
181                     normals[addr + 1 + m],
182                     normals[addr + 1]);
183             rt_stri(tex,
184                     vertices[addr],
185                     vertices[addr + m],
186                     vertices[addr + 1 + m],
187                     normals[addr],
188                     normals[addr + m],
189                     normals[addr + 1 + m]);
190         }
191     }
192 
193     free(normals);
194     free(vertices);
195 } /* end of smoothed heightfield */
196 
adjust(apiflt * base,int xres,int yres,apiflt wx,apiflt wy,int xa,int ya,int x,int y,int xb,int yb)197 static void adjust(apiflt *base,
198                    int xres,
199                    int yres,
200                    apiflt wx,
201                    apiflt wy,
202                    int xa,
203                    int ya,
204                    int x,
205                    int y,
206                    int xb,
207                    int yb) {
208     apiflt d, v;
209 
210     if (base[x + (xres * y)] == 0.0) {
211         d = (abs(xa - xb) / (xres * 1.0)) * wx + (abs(ya - yb) / (yres * 1.0)) * wy;
212 
213         v = (base[xa + (xres * ya)] + base[xb + (xres * yb)]) / 2.0 +
214             (((((rand() % 1000) - 500.0) / 500.0) * d) / 8.0);
215 
216         if (v < 0.0)
217             v = 0.0;
218         if (v > (xres + yres))
219             v = (xres + yres);
220         base[x + (xres * y)] = v;
221     }
222 }
223 
224 static void
subdivide(apiflt * base,int xres,int yres,apiflt wx,apiflt wy,int x1,int y1,int x2,int y2)225 subdivide(apiflt *base, int xres, int yres, apiflt wx, apiflt wy, int x1, int y1, int x2, int y2) {
226     long x, y;
227 
228     if (((x2 - x1) < 2) && ((y2 - y1) < 2)) {
229         return;
230     }
231 
232     x = (x1 + x2) / 2;
233     y = (y1 + y2) / 2;
234 
235     adjust(base, xres, yres, wx, wy, x1, y1, x, y1, x2, y1);
236     adjust(base, xres, yres, wx, wy, x2, y1, x2, y, x2, y2);
237     adjust(base, xres, yres, wx, wy, x1, y2, x, y2, x2, y2);
238     adjust(base, xres, yres, wx, wy, x1, y1, x1, y, x1, y2);
239 
240     if (base[x + xres * y] == 0.0) {
241         base[x + (xres * y)] = (base[x1 + xres * y1] + base[x2 + xres * y1] + base[x2 + xres * y2] +
242                                 base[x1 + xres * y2]) /
243                                4.0;
244     }
245 
246     subdivide(base, xres, yres, wx, wy, x1, y1, x, y);
247     subdivide(base, xres, yres, wx, wy, x, y1, x2, y);
248     subdivide(base, xres, yres, wx, wy, x, y, x2, y2);
249     subdivide(base, xres, yres, wx, wy, x1, y, x, y2);
250 }
251 
rt_landscape(void * tex,int m,int n,vector ctr,apiflt wx,apiflt wy)252 void rt_landscape(void *tex, int m, int n, vector ctr, apiflt wx, apiflt wy) {
253     int totalsize, x, y;
254     apiflt *field;
255 
256     totalsize = m * n;
257 
258     srand(totalsize);
259 
260     field = (apiflt *)malloc(totalsize * sizeof(apiflt));
261 
262     for (y = 0; y < n; y++) {
263         for (x = 0; x < m; x++) {
264             field[x + y * m] = 0.0;
265         }
266     }
267 
268     field[0 + 0] = 1.0 + (rand() % 100) / 100.0;
269     field[m - 1] = 1.0 + (rand() % 100) / 100.0;
270     field[0 + m * (n - 1)] = 1.0 + (rand() % 100) / 100.0;
271     field[m - 1 + m * (n - 1)] = 1.0 + (rand() % 100) / 100.0;
272 
273     subdivide(field, m, n, wx, wy, 0, 0, m - 1, n - 1);
274 
275     rt_sheightfield(tex, ctr, m, n, field, wx, wy);
276 
277     free(field);
278 }
279