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