1 /*
2     Copyright (c) 2005-2020 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 #include <cstdio>
47 #include <cstdlib>
48 #include <cstring>
49 
50 #define VIDEO_WINMAIN_ARGS
51 #include "types.hpp"
52 #include "api.hpp" /* The ray tracing library API */
53 #include "parse.hpp" /* Support for my own file format */
54 #include "ui.hpp"
55 #include "util.hpp"
56 #include "tachyon_video.hpp"
57 #include "common/utility/utility.hpp"
58 
59 #if WIN8UI_EXAMPLE
60 #include "oneapi/tbb.h"
61 volatile long global_startTime = 0;
62 volatile long global_elapsedTime = 0;
63 volatile bool global_isCancelled = false;
64 volatile int global_number_of_threads;
65 #endif
66 
67 SceneHandle global_scene;
68 int global_xsize; /* size of graphic image rendered in window (from hres, vres) */
69 int global_ysize;
70 int global_xwinsize; /* size of window (may be larger than above) */
71 int global_ywinsize;
72 char *global_window_title;
73 bool global_usegraphics;
74 
75 bool silent_mode = false; /* silent mode */
76 
77 class tachyon_video *video = 0;
78 
79 typedef struct {
80     int foundfilename; /* was a model file name found in the args? */
81     char filename[1024]; /* model file to render */
82     int useoutfilename; /* command line override of output filename */
83     char outfilename[1024]; /* name of output image file */
84     int verbosemode; /* verbose flags */
85     int antialiasing; /* antialiasing setting */
86     int displaymode; /* display mode */
87     int boundmode; /* bounding mode */
88     int boundthresh; /* bounding threshold */
89     int usecamfile; /* use camera file */
90     char camfilename[1024]; /* camera filename */
91 } argoptions;
92 
93 void initoptions(argoptions *opt) {
94     memset(opt, 0, sizeof(argoptions));
95     opt->foundfilename = -1;
96     opt->useoutfilename = -1;
97     opt->verbosemode = -1;
98     opt->antialiasing = -1;
99     opt->displaymode = -1;
100     opt->boundmode = -1;
101     opt->boundthresh = -1;
102     opt->usecamfile = -1;
103 }
104 
105 #if WIN8UI_EXAMPLE
106 int CreateScene() {
107     char *filename = "Assets/balls.dat";
108 
109     global_scene = rt_newscene();
110     rt_initialize();
111 
112     if (readmodel(filename, global_scene) != 0) {
113         rt_finalize();
114         return -1;
115     }
116 
117     // need these early for create_graphics_window() so grab these here...
118     scenedef *scene = (scenedef *)global_scene;
119 
120     // scene->hres and scene->vres should be equal to screen resolution
121     scene->hres = global_xwinsize = global_xsize;
122     scene->vres = global_ywinsize = global_ysize;
123 
124     return 0;
125 }
126 
127 unsigned int __stdcall example_main(void *) {
128     if (CreateScene() != 0)
129         std::exit(-1);
130 
131     tachyon_video tachyon;
132     tachyon.threaded = true;
133     tachyon.init_console();
134 
135     // always using window even if(!global_usegraphics)
136     global_usegraphics = tachyon.init_window(global_xwinsize, global_ywinsize);
137     if (!tachyon.running)
138         std::exit(-1);
139 
140     video = &tachyon;
141 
142     for (;;) {
143         global_elapsedTime = 0;
144         global_startTime = (long)time(nullptr);
145         global_isCancelled = false;
146         if (video)
147             video->running = true;
148         oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
149                                       global_number_of_threads);
150         memset(g_pImg, 0, sizeof(unsigned int) * global_xsize * global_ysize);
151         tachyon.main_loop();
152         global_elapsedTime = (long)(time(nullptr) - global_startTime);
153         video->running = false;
154         //The timer to restart drawing then it is complete.
155         int timer = 50;
156         while ((!global_isCancelled && (timer--) > 0)) {
157             rt_sleep(100);
158         }
159     }
160     return nullptr;
161 }
162 
163 #elif __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
164 
165 #include "oneapi/tbb.h"
166 #include "CoreFoundation/CoreFoundation.hpp"
167 extern "C" void get_screen_resolution(int *x, int *y);
168 
169 int CreateScene() {
170     CFURLRef balls_dat_url =
171         CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("balls"), CFSTR("dat"), nullptr);
172     char filename[1024];
173     CFURLGetFileSystemRepresentation(
174         balls_dat_url, true, (UInt8 *)filename, (CFIndex)sizeof(filename));
175     CFRelease(balls_dat_url);
176 
177     global_scene = rt_newscene();
178     rt_initialize();
179 
180     if (readmodel(filename, global_scene) != 0) {
181         rt_finalize();
182         return -1;
183     }
184 
185     // need these early for create_graphics_window() so grab these here...
186     scenedef *scene = (scenedef *)global_scene;
187 
188     get_screen_resolution(&global_xsize, &global_ysize);
189 
190     // scene->hres and scene->vres should be equal to screen resolution
191     scene->hres = global_xwinsize = global_xsize;
192     scene->vres = global_ywinsize = global_ysize;
193     return 0;
194 }
195 
196 int main(int argc, char *argv[]) {
197     if (CreateScene() != 0)
198         return -1;
199 
200     tachyon_video tachyon;
201     tachyon.threaded = true;
202     tachyon.init_console();
203 
204     global_usegraphics = tachyon.init_window(global_xwinsize, global_ywinsize);
205     if (!tachyon.running)
206         return -1;
207 
208     //TODO: add a demo loop.
209     video = &tachyon;
210     if (video)
211         video->running = true;
212     memset(g_pImg, 0, sizeof(unsigned int) * global_xsize * global_ysize);
213     tachyon.main_loop();
214     video->running = false;
215     return 0;
216 }
217 
218 #else
219 
220 static char *window_title_string(int argc, const char *argv[]) {
221     int i;
222     char *name;
223 
224     name = (char *)malloc(8192);
225     char *title = getenv("TITLE");
226     if (title)
227         strcpy(name, title);
228     else {
229         if (strrchr(argv[0], '\\'))
230             strcpy(name, strrchr(argv[0], '\\') + 1);
231         else if (strrchr(argv[0], '/'))
232             strcpy(name, strrchr(argv[0], '/') + 1);
233         else
234             strcpy(name, *argv[0] ? argv[0] : "Tachyon");
235     }
236     for (i = 1; i < argc; i++) {
237         strcat(name, " ");
238         strcat(name, argv[i]);
239     }
240 #ifdef _DEBUG
241     strcat(name, " (DEBUG BUILD)");
242 #endif
243     return name;
244 }
245 
246 int useoptions(argoptions *opt, SceneHandle scene) {
247     if (opt->useoutfilename == 1) {
248         rt_outputfile(scene, opt->outfilename);
249     }
250 
251     if (opt->verbosemode == 1) {
252         rt_verbose(scene, 1);
253     }
254 
255     if (opt->antialiasing != -1) {
256         /* need new api code for this */
257     }
258 
259     if (opt->displaymode != -1) {
260         rt_displaymode(scene, opt->displaymode);
261     }
262 
263     if (opt->boundmode != -1) {
264         rt_boundmode(scene, opt->boundmode);
265     }
266 
267     if (opt->boundthresh != -1) {
268         rt_boundthresh(scene, opt->boundthresh);
269     }
270 
271     return 0;
272 }
273 
274 argoptions ParseCommandLine(int argc, const char *argv[]) {
275     argoptions opt;
276 
277     initoptions(&opt);
278 
279     bool nobounding = false;
280     bool nodisp = false;
281 
282     std::string filename;
283 
284     utility::parse_cli_arguments(
285         argc,
286         argv,
287         utility::cli_argument_pack()
288             .positional_arg(filename, "dataset", "Model file")
289             .positional_arg(opt.boundthresh, "boundthresh", "bounding threshold value")
290             .arg(nodisp, "no-display-updating", "disable run-time display updating")
291             .arg(nobounding, "no-bounding", "disable bounding technique")
292             .arg(silent_mode, "silent", "no output except elapsed time"));
293 
294     strcpy(opt.filename, filename.c_str());
295 
296     opt.displaymode = nodisp ? RT_DISPLAY_DISABLED : RT_DISPLAY_ENABLED;
297     opt.boundmode = nobounding ? RT_BOUNDING_DISABLED : RT_BOUNDING_ENABLED;
298 
299     return opt;
300 }
301 
302 int CreateScene(argoptions &opt) {
303     char *filename;
304 
305     global_scene = rt_newscene();
306     rt_initialize();
307 
308     /* process command line overrides */
309     useoptions(&opt, global_scene);
310 
311 #ifdef DEFAULT_MODELFILE
312 #if _WIN32 || _WIN64
313 #define _GLUE_FILENAME(x) "..\\dat\\" #x
314 #else
315 #define _GLUE_FILENAME(x) #x
316 #endif
317 #define GLUE_FILENAME(x) _GLUE_FILENAME(x)
318     if (opt.foundfilename == -1)
319         filename = GLUE_FILENAME(DEFAULT_MODELFILE);
320     else
321 #endif //DEFAULT_MODELFILE
322         filename = opt.filename;
323 
324     if (readmodel(filename, global_scene) != 0) {
325         fprintf(stderr, "Parser returned a non-zero error code reading %s\n", filename);
326         fprintf(stderr, "Aborting Render...\n");
327         rt_finalize();
328         return -1;
329     }
330 
331     // need these early for create_graphics_window() so grab these here...
332     scenedef *scene = (scenedef *)global_scene;
333     global_xsize = scene->hres;
334     global_ysize = scene->vres;
335     global_xwinsize = global_xsize;
336     global_ywinsize =
337         global_ysize; // add some here to leave extra blank space on bottom for status etc.
338 
339     return 0;
340 }
341 
342 int main(int argc, char *argv[]) {
343     timer mainStartTime = gettimer();
344 
345     global_window_title = window_title_string(argc, (const char **)argv);
346 
347     argoptions opt = ParseCommandLine(argc, (const char **)argv);
348 
349     if (CreateScene(opt) != 0)
350         return -1;
351 
352     tachyon_video tachyon;
353     tachyon.threaded = true;
354     tachyon.init_console();
355 
356     tachyon.title = global_window_title;
357     // always using window even if(!global_usegraphics)
358     global_usegraphics = tachyon.init_window(global_xwinsize, global_ywinsize);
359     if (!tachyon.running)
360         return -1;
361 
362     video = &tachyon;
363     tachyon.main_loop();
364 
365     utility::report_elapsed_time(timertime(mainStartTime, gettimer()));
366     return 0;
367 }
368 #endif
369