1d86ed7fbStbbdev /*
2*c21e688aSSergey Zheltov     Copyright (c) 2005-2022 Intel Corporation
3d86ed7fbStbbdev 
4d86ed7fbStbbdev     Licensed under the Apache License, Version 2.0 (the "License");
5d86ed7fbStbbdev     you may not use this file except in compliance with the License.
6d86ed7fbStbbdev     You may obtain a copy of the License at
7d86ed7fbStbbdev 
8d86ed7fbStbbdev         http://www.apache.org/licenses/LICENSE-2.0
9d86ed7fbStbbdev 
10d86ed7fbStbbdev     Unless required by applicable law or agreed to in writing, software
11d86ed7fbStbbdev     distributed under the License is distributed on an "AS IS" BASIS,
12d86ed7fbStbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d86ed7fbStbbdev     See the License for the specific language governing permissions and
14d86ed7fbStbbdev     limitations under the License.
15d86ed7fbStbbdev */
16d86ed7fbStbbdev 
17d86ed7fbStbbdev /*
18d86ed7fbStbbdev     The original source for this example is
19d86ed7fbStbbdev     Copyright (c) 1994-2008 John E. Stone
20d86ed7fbStbbdev     All rights reserved.
21d86ed7fbStbbdev 
22d86ed7fbStbbdev     Redistribution and use in source and binary forms, with or without
23d86ed7fbStbbdev     modification, are permitted provided that the following conditions
24d86ed7fbStbbdev     are met:
25d86ed7fbStbbdev     1. Redistributions of source code must retain the above copyright
26d86ed7fbStbbdev        notice, this list of conditions and the following disclaimer.
27d86ed7fbStbbdev     2. Redistributions in binary form must reproduce the above copyright
28d86ed7fbStbbdev        notice, this list of conditions and the following disclaimer in the
29d86ed7fbStbbdev        documentation and/or other materials provided with the distribution.
30d86ed7fbStbbdev     3. The name of the author may not be used to endorse or promote products
31d86ed7fbStbbdev        derived from this software without specific prior written permission.
32d86ed7fbStbbdev 
33d86ed7fbStbbdev     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
34d86ed7fbStbbdev     OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35d86ed7fbStbbdev     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36d86ed7fbStbbdev     ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
37d86ed7fbStbbdev     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38d86ed7fbStbbdev     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39d86ed7fbStbbdev     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40d86ed7fbStbbdev     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41d86ed7fbStbbdev     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42d86ed7fbStbbdev     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43d86ed7fbStbbdev     SUCH DAMAGE.
44d86ed7fbStbbdev */
45d86ed7fbStbbdev 
46d86ed7fbStbbdev #include <cstdio>
47d86ed7fbStbbdev #include <cstdlib>
48d86ed7fbStbbdev #include <cstring>
49d86ed7fbStbbdev 
50d86ed7fbStbbdev #define VIDEO_WINMAIN_ARGS
51d86ed7fbStbbdev #include "types.hpp"
52d86ed7fbStbbdev #include "api.hpp" /* The ray tracing library API */
53d86ed7fbStbbdev #include "parse.hpp" /* Support for my own file format */
54d86ed7fbStbbdev #include "ui.hpp"
55d86ed7fbStbbdev #include "util.hpp"
56d86ed7fbStbbdev #include "tachyon_video.hpp"
57d86ed7fbStbbdev #include "common/utility/utility.hpp"
58d86ed7fbStbbdev 
59d86ed7fbStbbdev #if WIN8UI_EXAMPLE
60d86ed7fbStbbdev #include "oneapi/tbb.h"
61d86ed7fbStbbdev volatile long global_startTime = 0;
62d86ed7fbStbbdev volatile long global_elapsedTime = 0;
63d86ed7fbStbbdev volatile bool global_isCancelled = false;
64d86ed7fbStbbdev volatile int global_number_of_threads;
65d86ed7fbStbbdev #endif
66d86ed7fbStbbdev 
67d86ed7fbStbbdev SceneHandle global_scene;
68d86ed7fbStbbdev int global_xsize; /* size of graphic image rendered in window (from hres, vres) */
69d86ed7fbStbbdev int global_ysize;
70d86ed7fbStbbdev int global_xwinsize; /* size of window (may be larger than above) */
71d86ed7fbStbbdev int global_ywinsize;
72d86ed7fbStbbdev char *global_window_title;
73d86ed7fbStbbdev bool global_usegraphics;
74d86ed7fbStbbdev 
75d86ed7fbStbbdev bool silent_mode = false; /* silent mode */
76d86ed7fbStbbdev 
7757f524caSIlya Isaev class tachyon_video *video = nullptr;
78d86ed7fbStbbdev 
79d86ed7fbStbbdev typedef struct {
80d86ed7fbStbbdev     int foundfilename; /* was a model file name found in the args? */
81d86ed7fbStbbdev     char filename[1024]; /* model file to render */
82d86ed7fbStbbdev     int useoutfilename; /* command line override of output filename */
83d86ed7fbStbbdev     char outfilename[1024]; /* name of output image file */
84d86ed7fbStbbdev     int verbosemode; /* verbose flags */
85d86ed7fbStbbdev     int antialiasing; /* antialiasing setting */
86d86ed7fbStbbdev     int displaymode; /* display mode */
87d86ed7fbStbbdev     int boundmode; /* bounding mode */
88d86ed7fbStbbdev     int boundthresh; /* bounding threshold */
89d86ed7fbStbbdev     int usecamfile; /* use camera file */
90d86ed7fbStbbdev     char camfilename[1024]; /* camera filename */
91d86ed7fbStbbdev } argoptions;
92d86ed7fbStbbdev 
initoptions(argoptions * opt)93d86ed7fbStbbdev void initoptions(argoptions *opt) {
94d86ed7fbStbbdev     memset(opt, 0, sizeof(argoptions));
95d86ed7fbStbbdev     opt->foundfilename = -1;
96d86ed7fbStbbdev     opt->useoutfilename = -1;
97d86ed7fbStbbdev     opt->verbosemode = -1;
98d86ed7fbStbbdev     opt->antialiasing = -1;
99d86ed7fbStbbdev     opt->displaymode = -1;
100d86ed7fbStbbdev     opt->boundmode = -1;
101d86ed7fbStbbdev     opt->boundthresh = -1;
102d86ed7fbStbbdev     opt->usecamfile = -1;
103d86ed7fbStbbdev }
104d86ed7fbStbbdev 
105d86ed7fbStbbdev #if WIN8UI_EXAMPLE
CreateScene()106d86ed7fbStbbdev int CreateScene() {
107d86ed7fbStbbdev     char *filename = "Assets/balls.dat";
108d86ed7fbStbbdev 
109d86ed7fbStbbdev     global_scene = rt_newscene();
110d86ed7fbStbbdev     rt_initialize();
111d86ed7fbStbbdev 
112d86ed7fbStbbdev     if (readmodel(filename, global_scene) != 0) {
113d86ed7fbStbbdev         rt_finalize();
114d86ed7fbStbbdev         return -1;
115d86ed7fbStbbdev     }
116d86ed7fbStbbdev 
117d86ed7fbStbbdev     // need these early for create_graphics_window() so grab these here...
118d86ed7fbStbbdev     scenedef *scene = (scenedef *)global_scene;
119d86ed7fbStbbdev 
120d86ed7fbStbbdev     // scene->hres and scene->vres should be equal to screen resolution
121d86ed7fbStbbdev     scene->hres = global_xwinsize = global_xsize;
122d86ed7fbStbbdev     scene->vres = global_ywinsize = global_ysize;
123d86ed7fbStbbdev 
124d86ed7fbStbbdev     return 0;
125d86ed7fbStbbdev }
126d86ed7fbStbbdev 
example_main(void *)127d86ed7fbStbbdev unsigned int __stdcall example_main(void *) {
128d86ed7fbStbbdev     if (CreateScene() != 0)
129d86ed7fbStbbdev         std::exit(-1);
130d86ed7fbStbbdev 
131d86ed7fbStbbdev     tachyon_video tachyon;
132d86ed7fbStbbdev     tachyon.threaded = true;
133d86ed7fbStbbdev     tachyon.init_console();
134d86ed7fbStbbdev 
135d86ed7fbStbbdev     // always using window even if(!global_usegraphics)
136d86ed7fbStbbdev     global_usegraphics = tachyon.init_window(global_xwinsize, global_ywinsize);
137d86ed7fbStbbdev     if (!tachyon.running)
138d86ed7fbStbbdev         std::exit(-1);
139d86ed7fbStbbdev 
140d86ed7fbStbbdev     video = &tachyon;
141d86ed7fbStbbdev 
142d86ed7fbStbbdev     for (;;) {
143d86ed7fbStbbdev         global_elapsedTime = 0;
144d86ed7fbStbbdev         global_startTime = (long)time(nullptr);
145d86ed7fbStbbdev         global_isCancelled = false;
146d86ed7fbStbbdev         if (video)
147d86ed7fbStbbdev             video->running = true;
148d86ed7fbStbbdev         oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
149d86ed7fbStbbdev                                       global_number_of_threads);
150d86ed7fbStbbdev         memset(g_pImg, 0, sizeof(unsigned int) * global_xsize * global_ysize);
151d86ed7fbStbbdev         tachyon.main_loop();
152d86ed7fbStbbdev         global_elapsedTime = (long)(time(nullptr) - global_startTime);
153d86ed7fbStbbdev         video->running = false;
154d86ed7fbStbbdev         //The timer to restart drawing then it is complete.
155d86ed7fbStbbdev         int timer = 50;
156d86ed7fbStbbdev         while ((!global_isCancelled && (timer--) > 0)) {
157d86ed7fbStbbdev             rt_sleep(100);
158d86ed7fbStbbdev         }
159d86ed7fbStbbdev     }
160d86ed7fbStbbdev     return nullptr;
161d86ed7fbStbbdev }
162d86ed7fbStbbdev 
163d86ed7fbStbbdev #elif __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
164d86ed7fbStbbdev 
165d86ed7fbStbbdev #include "oneapi/tbb.h"
166d86ed7fbStbbdev #include "CoreFoundation/CoreFoundation.hpp"
167d86ed7fbStbbdev extern "C" void get_screen_resolution(int *x, int *y);
168d86ed7fbStbbdev 
CreateScene()169d86ed7fbStbbdev int CreateScene() {
170d86ed7fbStbbdev     CFURLRef balls_dat_url =
171d86ed7fbStbbdev         CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("balls"), CFSTR("dat"), nullptr);
172d86ed7fbStbbdev     char filename[1024];
173d86ed7fbStbbdev     CFURLGetFileSystemRepresentation(
174d86ed7fbStbbdev         balls_dat_url, true, (UInt8 *)filename, (CFIndex)sizeof(filename));
175d86ed7fbStbbdev     CFRelease(balls_dat_url);
176d86ed7fbStbbdev 
177d86ed7fbStbbdev     global_scene = rt_newscene();
178d86ed7fbStbbdev     rt_initialize();
179d86ed7fbStbbdev 
180d86ed7fbStbbdev     if (readmodel(filename, global_scene) != 0) {
181d86ed7fbStbbdev         rt_finalize();
182d86ed7fbStbbdev         return -1;
183d86ed7fbStbbdev     }
184d86ed7fbStbbdev 
185d86ed7fbStbbdev     // need these early for create_graphics_window() so grab these here...
186d86ed7fbStbbdev     scenedef *scene = (scenedef *)global_scene;
187d86ed7fbStbbdev 
188d86ed7fbStbbdev     get_screen_resolution(&global_xsize, &global_ysize);
189d86ed7fbStbbdev 
190d86ed7fbStbbdev     // scene->hres and scene->vres should be equal to screen resolution
191d86ed7fbStbbdev     scene->hres = global_xwinsize = global_xsize;
192d86ed7fbStbbdev     scene->vres = global_ywinsize = global_ysize;
193d86ed7fbStbbdev     return 0;
194d86ed7fbStbbdev }
195d86ed7fbStbbdev 
main(int argc,char * argv[])196d86ed7fbStbbdev int main(int argc, char *argv[]) {
197d86ed7fbStbbdev     if (CreateScene() != 0)
198d86ed7fbStbbdev         return -1;
199d86ed7fbStbbdev 
200d86ed7fbStbbdev     tachyon_video tachyon;
201d86ed7fbStbbdev     tachyon.threaded = true;
202d86ed7fbStbbdev     tachyon.init_console();
203d86ed7fbStbbdev 
204d86ed7fbStbbdev     global_usegraphics = tachyon.init_window(global_xwinsize, global_ywinsize);
205d86ed7fbStbbdev     if (!tachyon.running)
206d86ed7fbStbbdev         return -1;
207d86ed7fbStbbdev 
208d86ed7fbStbbdev     //TODO: add a demo loop.
209d86ed7fbStbbdev     video = &tachyon;
210d86ed7fbStbbdev     if (video)
211d86ed7fbStbbdev         video->running = true;
212d86ed7fbStbbdev     memset(g_pImg, 0, sizeof(unsigned int) * global_xsize * global_ysize);
213d86ed7fbStbbdev     tachyon.main_loop();
214d86ed7fbStbbdev     video->running = false;
215d86ed7fbStbbdev     return 0;
216d86ed7fbStbbdev }
217d86ed7fbStbbdev 
218d86ed7fbStbbdev #else
219d86ed7fbStbbdev 
window_title_string(int argc,const char * argv[])220d86ed7fbStbbdev static char *window_title_string(int argc, const char *argv[]) {
221d86ed7fbStbbdev     int i;
222d86ed7fbStbbdev     char *name;
223d86ed7fbStbbdev 
224d86ed7fbStbbdev     name = (char *)malloc(8192);
225d86ed7fbStbbdev     char *title = getenv("TITLE");
226d86ed7fbStbbdev     if (title)
227d86ed7fbStbbdev         strcpy(name, title);
228d86ed7fbStbbdev     else {
229d86ed7fbStbbdev         if (strrchr(argv[0], '\\'))
230d86ed7fbStbbdev             strcpy(name, strrchr(argv[0], '\\') + 1);
231d86ed7fbStbbdev         else if (strrchr(argv[0], '/'))
232d86ed7fbStbbdev             strcpy(name, strrchr(argv[0], '/') + 1);
233d86ed7fbStbbdev         else
234d86ed7fbStbbdev             strcpy(name, *argv[0] ? argv[0] : "Tachyon");
235d86ed7fbStbbdev     }
236d86ed7fbStbbdev     for (i = 1; i < argc; i++) {
237d86ed7fbStbbdev         strcat(name, " ");
238d86ed7fbStbbdev         strcat(name, argv[i]);
239d86ed7fbStbbdev     }
240d86ed7fbStbbdev #ifdef _DEBUG
241d86ed7fbStbbdev     strcat(name, " (DEBUG BUILD)");
242d86ed7fbStbbdev #endif
243d86ed7fbStbbdev     return name;
244d86ed7fbStbbdev }
245d86ed7fbStbbdev 
useoptions(argoptions * opt,SceneHandle scene)246d86ed7fbStbbdev int useoptions(argoptions *opt, SceneHandle scene) {
247d86ed7fbStbbdev     if (opt->useoutfilename == 1) {
248d86ed7fbStbbdev         rt_outputfile(scene, opt->outfilename);
249d86ed7fbStbbdev     }
250d86ed7fbStbbdev 
251d86ed7fbStbbdev     if (opt->verbosemode == 1) {
252d86ed7fbStbbdev         rt_verbose(scene, 1);
253d86ed7fbStbbdev     }
254d86ed7fbStbbdev 
255d86ed7fbStbbdev     if (opt->antialiasing != -1) {
256d86ed7fbStbbdev         /* need new api code for this */
257d86ed7fbStbbdev     }
258d86ed7fbStbbdev 
259d86ed7fbStbbdev     if (opt->displaymode != -1) {
260d86ed7fbStbbdev         rt_displaymode(scene, opt->displaymode);
261d86ed7fbStbbdev     }
262d86ed7fbStbbdev 
263d86ed7fbStbbdev     if (opt->boundmode != -1) {
264d86ed7fbStbbdev         rt_boundmode(scene, opt->boundmode);
265d86ed7fbStbbdev     }
266d86ed7fbStbbdev 
267d86ed7fbStbbdev     if (opt->boundthresh != -1) {
268d86ed7fbStbbdev         rt_boundthresh(scene, opt->boundthresh);
269d86ed7fbStbbdev     }
270d86ed7fbStbbdev 
271d86ed7fbStbbdev     return 0;
272d86ed7fbStbbdev }
273d86ed7fbStbbdev 
ParseCommandLine(int argc,const char * argv[])274d86ed7fbStbbdev argoptions ParseCommandLine(int argc, const char *argv[]) {
275d86ed7fbStbbdev     argoptions opt;
276d86ed7fbStbbdev 
277d86ed7fbStbbdev     initoptions(&opt);
278d86ed7fbStbbdev 
279d86ed7fbStbbdev     bool nobounding = false;
280d86ed7fbStbbdev     bool nodisp = false;
281d86ed7fbStbbdev 
282d86ed7fbStbbdev     std::string filename;
283d86ed7fbStbbdev 
284d86ed7fbStbbdev     utility::parse_cli_arguments(
285d86ed7fbStbbdev         argc,
286d86ed7fbStbbdev         argv,
287d86ed7fbStbbdev         utility::cli_argument_pack()
288d86ed7fbStbbdev             .positional_arg(filename, "dataset", "Model file")
289d86ed7fbStbbdev             .positional_arg(opt.boundthresh, "boundthresh", "bounding threshold value")
290d86ed7fbStbbdev             .arg(nodisp, "no-display-updating", "disable run-time display updating")
291d86ed7fbStbbdev             .arg(nobounding, "no-bounding", "disable bounding technique")
292d86ed7fbStbbdev             .arg(silent_mode, "silent", "no output except elapsed time"));
293d86ed7fbStbbdev 
294d86ed7fbStbbdev     strcpy(opt.filename, filename.c_str());
295d86ed7fbStbbdev 
296d86ed7fbStbbdev     opt.displaymode = nodisp ? RT_DISPLAY_DISABLED : RT_DISPLAY_ENABLED;
297d86ed7fbStbbdev     opt.boundmode = nobounding ? RT_BOUNDING_DISABLED : RT_BOUNDING_ENABLED;
298d86ed7fbStbbdev 
299d86ed7fbStbbdev     return opt;
300d86ed7fbStbbdev }
301d86ed7fbStbbdev 
CreateScene(argoptions & opt)302d86ed7fbStbbdev int CreateScene(argoptions &opt) {
303d86ed7fbStbbdev     char *filename;
304d86ed7fbStbbdev 
305d86ed7fbStbbdev     global_scene = rt_newscene();
306d86ed7fbStbbdev     rt_initialize();
307d86ed7fbStbbdev 
308d86ed7fbStbbdev     /* process command line overrides */
309d86ed7fbStbbdev     useoptions(&opt, global_scene);
310d86ed7fbStbbdev 
311d86ed7fbStbbdev #ifdef DEFAULT_MODELFILE
312d86ed7fbStbbdev #if _WIN32 || _WIN64
313d86ed7fbStbbdev #define _GLUE_FILENAME(x) "..\\dat\\" #x
314d86ed7fbStbbdev #else
315d86ed7fbStbbdev #define _GLUE_FILENAME(x) #x
316d86ed7fbStbbdev #endif
317d86ed7fbStbbdev #define GLUE_FILENAME(x) _GLUE_FILENAME(x)
318d86ed7fbStbbdev     if (opt.foundfilename == -1)
319d86ed7fbStbbdev         filename = GLUE_FILENAME(DEFAULT_MODELFILE);
320d86ed7fbStbbdev     else
321d86ed7fbStbbdev #endif //DEFAULT_MODELFILE
322d86ed7fbStbbdev         filename = opt.filename;
323d86ed7fbStbbdev 
324d86ed7fbStbbdev     if (readmodel(filename, global_scene) != 0) {
325d86ed7fbStbbdev         fprintf(stderr, "Parser returned a non-zero error code reading %s\n", filename);
326d86ed7fbStbbdev         fprintf(stderr, "Aborting Render...\n");
327d86ed7fbStbbdev         rt_finalize();
328d86ed7fbStbbdev         return -1;
329d86ed7fbStbbdev     }
330d86ed7fbStbbdev 
331d86ed7fbStbbdev     // need these early for create_graphics_window() so grab these here...
332d86ed7fbStbbdev     scenedef *scene = (scenedef *)global_scene;
333d86ed7fbStbbdev     global_xsize = scene->hres;
334d86ed7fbStbbdev     global_ysize = scene->vres;
335d86ed7fbStbbdev     global_xwinsize = global_xsize;
336d86ed7fbStbbdev     global_ywinsize =
337d86ed7fbStbbdev         global_ysize; // add some here to leave extra blank space on bottom for status etc.
338d86ed7fbStbbdev 
339d86ed7fbStbbdev     return 0;
340d86ed7fbStbbdev }
341d86ed7fbStbbdev 
main(int argc,char * argv[])342d86ed7fbStbbdev int main(int argc, char *argv[]) {
343d86ed7fbStbbdev     timer mainStartTime = gettimer();
344d86ed7fbStbbdev 
345d86ed7fbStbbdev     global_window_title = window_title_string(argc, (const char **)argv);
346d86ed7fbStbbdev 
347d86ed7fbStbbdev     argoptions opt = ParseCommandLine(argc, (const char **)argv);
348d86ed7fbStbbdev 
349d86ed7fbStbbdev     if (CreateScene(opt) != 0)
350d86ed7fbStbbdev         return -1;
351d86ed7fbStbbdev 
352d86ed7fbStbbdev     tachyon_video tachyon;
353d86ed7fbStbbdev     tachyon.threaded = true;
354d86ed7fbStbbdev     tachyon.init_console();
355d86ed7fbStbbdev 
356d86ed7fbStbbdev     tachyon.title = global_window_title;
357d86ed7fbStbbdev     // always using window even if(!global_usegraphics)
358d86ed7fbStbbdev     global_usegraphics = tachyon.init_window(global_xwinsize, global_ywinsize);
359d86ed7fbStbbdev     if (!tachyon.running)
360d86ed7fbStbbdev         return -1;
361d86ed7fbStbbdev 
362d86ed7fbStbbdev     video = &tachyon;
363d86ed7fbStbbdev     tachyon.main_loop();
364d86ed7fbStbbdev 
365d86ed7fbStbbdev     utility::report_elapsed_time(timertime(mainStartTime, gettimer()));
366d86ed7fbStbbdev     return 0;
367d86ed7fbStbbdev }
368d86ed7fbStbbdev #endif
369