Tachyon (current)  Current Main Branch
objloader.cpp
Go to the documentation of this file.
1 /*
2  * objloader.cpp - Parametric surface plotting example scene.
3  *
4  * (C) Copyright 2013-2022 John E. Stone
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * $Id: objloader.cpp,v 1.11 2022/04/19 02:54:21 johns Exp $
8  *
9  */
10 
20 //
21 // OBJ loader example
22 // John E. Stone, Mar 2022
23 //
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29 #include "ProfileHooks.h"
30 
31 #define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
32 // Optional requires C++11: TINYOBJLOADER_USE_MAPBOX_EARCUT robust trinagulation
33 //#define TINYOBJLOADER_USE_MAPBOX_EARCUT
34 #include "tiny_obj_loader.h"
35 
36 #define STB_IMAGE_WRITE_IMPLEMENTATION
37 #include "stb_image_write.h"
38 #define STB_IMAGE_IMPLEMENTATION
39 #include "stb_image.h"
40 
41 #include "TachyonOptiX.h"
42 
43 #if defined(TACHYON_USEPINNEDMEMORY)
44 #include <cuda_runtime.h>
45 #endif
46 
47 
48 #if 0
49 static int replacefileextension(char * s,
50  const char * oldextension,
51  const char * newextension) {
52  int sz, extsz;
53  sz = strlen(s);
54  extsz = strlen(oldextension);
55 
56  if (strlen(newextension) != strlen(oldextension))
57  return -1;
58 
59  if (extsz > sz)
60  return -1;
61 
62 // if (strupncmp(s + (sz - extsz), oldextension, extsz)) {
63  if (strncmp(s + (sz - extsz), oldextension, extsz)) {
64  return -1;
65  }
66 
67  strcpy(s + (sz - extsz), newextension);
68 
69  return 0;
70 }
71 
72 
73 static char * getmaterialfilename(const char* objfilename) {
74  char *mtlfilename = strdup(objfilename);
75  if (replacefileextension(mtlfilename, ".obj", ".mtl")) {
76  free(mtlfilename);
77  return NULL;
78  }
79 
80  return mtlfilename;
81 }
82 #endif
83 
84 
85 static char * getmaterialdir(const char* filename) {
86 #if defined(_MSC_VER)
87  char slash = '\\';
88 #else
89  char slash = '/';
90 #endif
91 
92  char *dirname = strdup(filename);
93  char *sep = strrchr(dirname, slash);
94  if (sep != NULL) {
95  *sep = '\0'; // terminate after last seperator
96  }
97 
98  return dirname;
99 }
100 
101 
102 static unsigned char * loadimage_rgba4u(const char *searchpath,
103  const char *filename,
104  int &xres, int &yres, int &chinfile) {
105  int newlen = strlen(searchpath) + strlen(filename) + 2;
106  char *fullpath = (char *) calloc(1, newlen);
107 
108  strcpy(fullpath, searchpath);
109  strcat(fullpath, "/");
110  strcat(fullpath, filename);
111 
112  int fplen = strlen(fullpath);
113  for (int i=0; i<fplen; i++) {
114  if (fullpath[i] == '\\')
115  fullpath[i] = '/';
116  }
117 
118 // printf("Load: %s\n", fullpath);
119  unsigned char *img = NULL;
120  chinfile=0;
121  img = stbi_load(fullpath, &xres, &yres, &chinfile, 4);
122 
123  return img;
124 }
125 
126 
127 void print_coords(float *coords, int numpts, int count) {
128  printf("Coordinate dump:\n");
129  if (count > numpts)
130  count = numpts;
131 
132  int i;
133  for (i=0; i<count; i++) {
134  int ind = i * 3;
135  printf("[%d]: %.3f %.3f %.3f\n",
136  i, coords[ind], coords[ind+1], coords[ind+2]);
137 
138  }
139  printf("...\n");
140  for (i=numpts-count; i<numpts; i++) {
141  int ind = i * 3;
142  printf("[%d]: %.3f %.3f %.3f\n",
143  i, coords[ind], coords[ind+1], coords[ind+2]);
144  }
145 }
146 
147 
148 int main(int argc, const char **argv) {
150 
151  // some sane defaults
152  int imgSize[2] = {3840, 2160 }; // W x H
153  const char *objfilename = NULL;
154  int ambientocclusion = 1;
155  int denoiser = 0;
156  int dof = 0;
157  int warmup = 0;
158 
159  printf("Tachyon OBJ scene viewer demo\n");
160 
161  //
162  // camera defaults
163  //
164 
165 #if 0
166  // XXX some default camera settings for the "San Miguel" test scene.
167  float campos[3] = { 22.0f, 14.0f, 10.0f};
168  float camV[3] = { 0.0f, 1.0f, 0.0f};
169  float camat[3] = { 10.0f, 0.0f, 0.0f};
170  float camzoom = 0.5f;
171  float aomaxdist = 15;
172 #else
173  // XXX some default camera settings for the "Sponza" test scene.
174  float campos[3] = { 800.0f, 400.0f, 0.0f};
175  float camV[3] = { 0.0f, 1.0f, 0.0f};
176  float camat[3] = { 0.0f, 400.0f, 0.0f};
177  float camzoom = 0.5f;
178  float aomaxdist = 700;
179 #endif
180 
181  //
182  // parse args
183  //
184  if (argc == 1) {
185  printf("Usage: %s objfilename.obj [optional flags]\n", argv[0]);
186  printf(" optional flags: -ao: add renderer-specific AO lighting\n");
187  printf(" -res XXXX YYYY: override default image res\n");
188  return -1;
189  }
190 
191  // parse surface type
192  if (argc > 1) {
193  objfilename = argv[1];
194  }
195 
196  // parse remaining optional parameter flags
197  if (argc > 2) {
198  for (int i=2; i<argc; i++) {
199  if (!strcmp("-ao", argv[i])) {
200  ambientocclusion = 1;
201  printf("Enabling renderer-specific AO lighting.\n");
202  continue;
203  }
204 
205  if (!strcmp("-camlookat", argv[i])) {
206  if ((argc - i) >= 3) {
207  camat[0] = atof(argv[++i]);
208  camat[1] = atof(argv[++i]);
209  camat[2] = atof(argv[++i]);
210  }
211  continue;
212  }
213 
214  if (!strcmp("-campos", argv[i])) {
215  if ((argc - i) >= 3) {
216  campos[0] = atof(argv[++i]);
217  campos[1] = atof(argv[++i]);
218  campos[2] = atof(argv[++i]);
219  }
220  continue;
221  }
222 
223  if (!strcmp("-camup", argv[i])) {
224  if ((argc - i) >= 3) {
225  camV[0] = atof(argv[++i]);
226  camV[1] = atof(argv[++i]);
227  camV[2] = atof(argv[++i]);
228  }
229  continue;
230  }
231 
232  if (!strcmp("-camzoom", argv[i])) {
233  if ((argc - i) >= 1) {
234  camzoom = atof(argv[++i]);
235  }
236  continue;
237  }
238 
239  if (!strcmp("-aomaxdist", argv[i])) {
240  if ((argc - i) >= 1) {
241  aomaxdist = atof(argv[++i]);
242  }
243  printf("** aomaxdist: %.2f\n", aomaxdist);
244  continue;
245  }
246 
247  if (!strcmp("-noao", argv[i])) {
248  ambientocclusion = 0;
249  printf("Disabling renderer-specific AO lighting.\n");
250  continue;
251  }
252 
253  if (!strcmp("-res", argv[i])) {
254  if ((argc - i) >= 2) {
255  imgSize[0] = atoi(argv[++i]);
256  imgSize[1] = atoi(argv[++i]);
257  printf("Image resolution set to: %d x %d\n", imgSize[0], imgSize[1]);
258  }
259  continue;
260  }
261 
262  if (!strcmp("-denoiser", argv[i])) {
263  denoiser = 1;
264  continue;
265  }
266 
267  if (!strcmp("-dof", argv[i])) {
268  dof = 1;
269  continue;
270  }
271 
272 #if 0
273  if (!strcmp("-pause", argv[i])) {
274  sleep(10);
275  }
276 #endif
277 
278  if (!strcmp("-warmup", argv[i])) {
279  warmup = 1;
280  printf("Enabling profiling warm-up pass and timing.\n");
281  continue;
282  }
283 
284  printf("Unrecognized flag: '%s'.\n", argv[i]);
285  }
286  }
287 
288  printf("All command line flags processed.\n");
289 
290 #if defined(TACHYON_USEPINNEDMEMORY)
291  printf("USING PINNED HOST MEMORY ALLOCATIONS\n");
292 #endif
293 
294  PROFILE_PUSH_RANGE("Loading OBJ", 0);
295 
296  std::string inputfile = objfilename;
297  tinyobj::ObjReaderConfig reader_config;
298  tinyobj::ObjReader reader;
299 
300  // get path to material files
301  char *materialdir = getmaterialdir(objfilename);
302  if (materialdir) {
303  printf("MTL directory: %s\n", materialdir);
304  reader_config.mtl_search_path = materialdir;
305  } else {
306  reader_config.mtl_search_path = "./";
307  }
308 
309 
310  if (!reader.ParseFromFile(inputfile, reader_config)) {
311  if (!reader.Error().empty()) {
312  printf("TinyObjReader Error: %s\n", reader.Error().c_str());
313  }
314  return -1;
315  }
316 
317  if (!reader.Warning().empty()) {
318  printf("TinyObjReader Warning: %s\n", reader.Warning().c_str());
319  }
320 
322 
323  auto& attrib = reader.GetAttrib();
324  auto& shapes = reader.GetShapes();
325  auto& materials = reader.GetMaterials();
326 
327  printf("OBJ materials: %ld\n", materials.size());
328 #if 0
329  for (size_t m = 0; m < materials.size(); m++) {
330  printf(" mat[%ld]: '%s'\n", m, materials[m].name.c_str());
331  }
332  printf("\n");
333 #endif
334 
335  printf("OBJ shapes: %ld\n", shapes.size());
336 #if 0
337  // Loop over shapes
338  for (size_t s = 0; s < shapes.size(); s++) {
339  printf(" shape[%ld]: %ld faces\n",
340  s, shapes[s].mesh.num_face_vertices.size());
341 
342 #if 0
343  // Loop over faces(polygon)
344  size_t index_offset = 0;
345  for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
346  size_t fv = size_t(shapes[s].mesh.num_face_vertices[f]);
347 
348  index_offset += fv;
349  }
350 #endif
351  }
352 #endif
353 
354 
355  PROFILE_PUSH_RANGE("Initialize Tachyon", 0);
356  printf("Initializing TachyonOptiX...");
357 
360  unsigned int devcount = TachyonOptiX::device_count();
361  unsigned int optixversion = TachyonOptiX::optix_version();
362 
363  printf("Found %u OptiX devices\n", devcount);
364  printf("OptiX version used for build: %d.%d.%d (%u)\n",
365  optixversion/10000,
366  (optixversion%10000)/100,
367  (optixversion%100),
368  optixversion);
369 
370  TachyonOptiX *rt = new TachyonOptiX();
371  printf("\n");
372 
374 
375 
376  PROFILE_PUSH_RANGE("Build Scene", 0);
377 
378  //
379  // Build scene
380  //
381 
382  // create and setup camera
384  rt->framebuffer_resize(imgSize[0], imgSize[1]);
385 // rt->set_verbose_mode(TachyonOptiX::RT_VERB_MIN);
386 // rt->set_verbose_mode(TachyonOptiX::RT_VERB_DEBUG);
387  float rtbgcolor[] = { 1.0, 1.0, 1.0 };
388  float rtbggradtopcolor[] = { 0.4, 0.6, 0.7 };
389  float rtbggradbotcolor[] = { 0.5, 0.1, 0.2 };
390 
391  rt->set_bg_color(rtbgcolor);
392  rt->set_bg_color_grad_top(rtbggradtopcolor);
393  rt->set_bg_color_grad_bot(rtbggradbotcolor);
394 
395  float bggradient[] = { 0.0f, 1.0f, 0.0f };
396  rt->set_bg_gradient(bggradient);
397  rt->set_bg_gradient_topval(1.0f);
398  rt->set_bg_gradient_botval(-1.0f);
399 
400 // rt->set_bg_mode(TachyonOptiX::RT_BACKGROUND_TEXTURE_SOLID);
402 // rt->set_bg_mode(TachyonOptiX::RT_BACKGROUND_TEXTURE_SKY_SPHERE);
403 
404  rt->set_aa_samples(512);
405  rt->shadows_enable(1);
406 
407  if (ambientocclusion) {
408  rt->set_ao_samples(1);
409  rt->set_ao_ambient(1.2);
410  rt->set_ao_direct(0.4);
411  rt->set_ao_maxdist(aomaxdist);
412  }
413 
414  float lightdir0[] = { 0.3f, 1.0f, 0.3f };
415  float lightcolor0[] = { 1.0f, 1.0f, 1.0f };
416  rt->add_directional_light(lightdir0, lightcolor0);
417 
418  // set camera params
420 // rt->set_camera_type(TachyonOptiX::RT_ORTHOGRAPHIC);
421 // rt->set_camera_type(TachyonOptiX::RT_EQUIRECTANGULAR);
422 // rt->set_camera_type(TachyonOptiX::RT_OCTOHEDRAL);
423 
424  rt->set_camera_pos(campos);
425 // rt->set_camera_ONB(camU, camV, camW);
426  rt->set_camera_lookat(camat, camV);
427  rt->set_camera_zoom(camzoom);
428 
429  if (denoiser)
430  rt->denoiser_enable(1);
431 
432  if (dof)
433  rt->camera_dof_enable(1);
434 
435  rt->set_camera_dof_fnumber(80.0f);
436  rt->set_camera_dof_focal_dist(500.0f);
437 
438  // set stereoscopic display parameters
439  rt->set_camera_stereo_eyesep(0.6f);
441 
442  // set depth cueing parameters
443  float start = 1.0f;
444  float end = 30.0f;
445  float density = 0.33f;
446 // rt->set_cue_mode(TachyonOptiX::RT_FOG_LINEAR, start, end, density);
447 // rt->set_cue_mode(TachyonOptiX::RT_FOG_EXP, start, end, density);
448 // rt->set_cue_mode(TachyonOptiX::RT_FOG_EXP2, start, end, density);
449  rt->set_cue_mode(TachyonOptiX::RT_FOG_NONE, start, end, density);
450 
451 
452  printf("Loading materials and texture images\n");
453  for (size_t m = 0; m < materials.size(); m++) {
454 #if 1
455  float ambient = 0.0f;
456 // (materials[m].ambient[0] +
457 // materials[m].ambient[1] +
458 // materials[m].ambient[2]) / 3.0f;
459 
460  float diffuse =
461  (materials[m].diffuse[0] +
462  materials[m].diffuse[1] +
463  materials[m].diffuse[2]) / 3.0f;
464 
465  float specular =
466  (materials[m].specular[0] +
467  materials[m].specular[1] +
468  materials[m].specular[2]) / 3.0f;
469 
470  float shininess =
471  materials[m].shininess;
472 
473  float reflectivity = 0.0f;
474 
475  float opacity =
476  materials[m].dissolve;
477 
478 // (materials[m].dissolve[0] +
479 // materials[m].dissolve[1] +
480 // materials[m].dissolve[2]) / 3.0f;
481 
482  float outline = 0.0f;
483  float outlinewidth = 0.0f;
484  int transmode = 0;
485 
486  // skipped material properties:
487  // materials[m].transmittance
488  // materials[m].emission
489  // materials[m].ior
490  // materials[m].illum
491  // materials[m].ambient_texname.c_str()
492  // materials[m].diffuse_texname.c_str()
493  // materials[m].specular_texname.c_str()
494  // materials[m].specular_highlight_texname.c_str()
495  //
496  // materials[m].bump_texname.c_str()
497  // materials[m].bump_texopt.bump_multiplier
498  // materials[m].alpha_texname.c_str()
499  // materials[m].displacement_texname.c_str()
500  //
501  // PBR extensions:
502  // materials[m].roughness
503  // materials[m].metallic
504  // materials[m].sheen
505  // materials[m].clearcoat_thickness
506  // materials[m].clearcoat?
507  // materials[m].anisotropy
508  // materials[m].anisotropy_rotation
509  // materials[m].emissive_texname.c_str()
510  // materials[m].roughness_texname.c_str()
511  // materials[m].metallic_texname.c_str()
512  // materials[m].sheen_texname.c-str()
513  // materials[m].normal_texname.c_str()
514  //
515  //
516  // // handle unrecognized/non-standard property names
517  // std::map<std::string, std::string>::const_iterator it(
518  // materials[i].unknown_parameter.begin());
519  // std::map<std::string, std::string>::const_iterator itEnd(
520  // materials[i].unknown_parameter.end());
521  //
522  // for (; it != itEnd; it++) {
523  // printf(" material.%s = %s\n", it->first.c_str(),it->second.c_str());
524  // }
525  //
526 #else
527  float ambient = 0.1f;
528  float diffuse = 0.7f;
529  float specular = 0.0f;
530  float shininess = 0.0f;
531  float reflectivity = 0.0f;
532  float opacity = 1.0f;
533  float outline = 0.0f;
534  float outlinewidth = 0.0f;
535  int transmode = 0;
536 #endif
537 
538 // printf("mat[%ld]: a:%.1f d:%.2f s:%.2f o:%.2f sh:%.2f\n",
539 // m, ambient, diffuse, specular, opacity, shininess);
540 
541  unsigned char *img = NULL;
542  int xres=0, yres=0, chinfile=0;
543  const char *texfilename = materials[m].diffuse_texname.c_str();
544  if ((texfilename != NULL) && (texfilename[0] != '\0')) {
545  printf("mat[%lu] '%s'\n", m, texfilename);
546  img = loadimage_rgba4u(materialdir, texfilename, xres, yres, chinfile);
547  if (img != NULL) {
548  printf(" %4d x %4d, %d channels\n", xres, yres, chinfile);
549  } else {
550  printf(" Failed to load image!\n");
551  }
552  }
553 
554  if (img != NULL) {
555  int texflags = (chinfile == 4) ? RT_TEX_ALPHA : RT_TEX_NONE;
556 
557  rt->add_tex2d_rgba4u(img, xres, yres, texflags | RT_COLORSPACE_sRGB, m);
558 
559  rt->add_material_textured(ambient, diffuse, specular,
560  shininess, reflectivity, opacity,
561  outline, outlinewidth, transmode, m, m);
562  } else {
563  rt->add_material(ambient, diffuse, specular, shininess, reflectivity,
564  opacity, outline, outlinewidth, transmode, m);
565  }
566  }
567  printf("\n");
568 
569  // XXX Start Nsight Compute Profiles here...
570  PROFILE_START();
571 
573 
574  if (warmup) {
576  PROFILE_PUSH_RANGE("Renderer Warmup Passes", 0);
577  // force warmup passes on an empty scene so our timings of subsequent
578  // scene data are way more realistic
579  for (int w=0; w<100; w++) {
580  rt->render();
581  rt->framebuffer_clear();
582  }
584  }
585 
587 
588 #if 1
589  int coordinit = 0;
590  float3 vmin={ 0 }, vmax={ 0 };
591 
592  std::vector<TriangleMesh> meshes;
593 
594  // Loop over shapes
595  int meshcnt = 0;
596  for (size_t s = 0; s < shapes.size(); s++) {
597  TriangleMesh tm;
598  long numfaces = shapes[s].mesh.num_face_vertices.size();
599  long numverts = numfaces * 3;
600  tm.vertices.resize(numverts);
601  tm.normals.resize(numverts);
602  tm.tex2d.resize(numverts);
603  int texcoords = 0;
604 
605  float3 *verts = tm.vertices.data();
606  float3 *norms = tm.normals.data();
607  float2 *tex2d = tm.tex2d.data();
608  tm.uniform_color = make_float3(0.7); // fall-back
609 
610  // Loop over faces(polygon)
611  size_t index_offset = 0;
612  for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
613  size_t fv = size_t(shapes[s].mesh.num_face_vertices[f]);
614 
615  // Loop over vertices in the face.
616  for (size_t v = 0; v < fv; v++) {
617  // index into attribute buffer
618  tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
619 
620  // access to vertex
621  tinyobj::real_t vx = attrib.vertices[3*size_t(idx.vertex_index)+0];
622  tinyobj::real_t vy = attrib.vertices[3*size_t(idx.vertex_index)+1];
623  tinyobj::real_t vz = attrib.vertices[3*size_t(idx.vertex_index)+2];
624 
625  // Check if `normal_index` is zero or positive.
626  // negative = no normal data
627  tinyobj::real_t nx=0, ny=0, nz=0;
628  if (idx.normal_index >= 0) {
629  nx = attrib.normals[3*size_t(idx.normal_index)+0];
630  ny = attrib.normals[3*size_t(idx.normal_index)+1];
631  nz = attrib.normals[3*size_t(idx.normal_index)+2];
632  }
633 
634  // Check if `texcoord_index` is zero or positive.
635  // negative = no texcoord data
636  tinyobj::real_t tx=0, ty=0;
637  if (idx.texcoord_index >= 0) {
638  texcoords=1;
639  tx = attrib.texcoords[2*size_t(idx.texcoord_index)+0];
640  ty = attrib.texcoords[2*size_t(idx.texcoord_index)+1];
641  }
642 
643  // Optional: vertex colors
644  // tinyobj::real_t red = attrib.colors[3*size_t(idx.vertex_index)+0];
645  // tinyobj::real_t green = attrib.colors[3*size_t(idx.vertex_index)+1];
646  // tinyobj::real_t blue = attrib.colors[3*size_t(idx.vertex_index)+2];
647 
648  float3 newv = make_float3(vx, vy, vz);
649  float3 newn = make_float3(nx, ny, nz);
650 
651  if (!coordinit) {
652  coordinit=1;
653  vmin = vmax = newv;
654  } else {
655  vmin.x = fminf(vmin.x, newv.x);
656  vmin.y = fminf(vmin.y, newv.y);
657  vmin.z = fminf(vmin.z, newv.z);
658  vmax.x = fmaxf(vmax.x, newv.x);
659  vmax.y = fmaxf(vmax.y, newv.y);
660  vmax.z = fmaxf(vmax.z, newv.z);
661  }
662 
663  long vidx = index_offset+v;
664  verts[vidx] = newv;
665  norms[vidx] = newn;
666 
667  //
668  // XXX flip vertical texcoord.ty axis to accomodate the
669  // memory layout of images loaded via stbi_load()...
670  //
671  tex2d[vidx] = make_float2(tx, 1.0f - ty);
672  }
673  index_offset += fv;
674 
675  // per-face material
676  shapes[s].mesh.material_ids[f];
677  }
678 
679  if (!texcoords)
680  tm.tex2d.clear();
681 
682  meshes.push_back(tm);
683  rt->add_trimesh(tm, shapes[s].mesh.material_ids[0]);
684  meshcnt++;
685  }
686  printf("Added %d trimeshes to scene...\n", meshcnt);
687  printf("BBox: min: %.2f %.2f %.2f max: %.2f %.2f %.2f\n",
688  vmin.x, vmin.y, vmin.z, vmax.x, vmax.y, vmax.z);
689  printf("\n");
690 #endif
691 
692  PROFILE_PUSH_RANGE("Render Scene", 0);
693  printf("Rendering frames w/ accumulation buffer...\n");
694  // render 100 accumulated frames
695 // for (int frames = 0; frames < 3; frames++) {
696  rt->render();
697 // }
699 
700  rt->print_raystats_info();
701 
702  PROFILE_PUSH_RANGE("Write Output Image", 0);
703 
704  char filename[1024];
705  sprintf(filename, "out.png");
706  printf("Writing accumulated frames to '%s'...\n", filename);
707  if (filename != NULL) {
708  rt->framebuffer_get_size(imgSize[0], imgSize[1]);
709  size_t bufsz = imgSize[0] * imgSize[1] * sizeof(int);
710  unsigned char *rgb4u = (unsigned char *) calloc(1, bufsz);
711  rt->framebuffer_download_rgb4u(rgb4u);
712 
713 #if 0
714  if (writealpha) {
715 printf("Writing rgba4u alpha channel output image 2\n");
716  if (write_image_file_rgba4u(filename, rgb4u, imgSize[0], imgSize[1]))
717  printf("Failed to write image '%s'!!\n", filename);
718  } else {
719  if (write_image_file_rgb4u(filename, rgb4u, imgSize[0], imgSize[1]))
720  printf("Failed to write image '%s'!!\n", filename);
721  }
722 #else
724 
725  stbi_write_png(filename, imgSize[0], imgSize[1], 4, rgb4u, imgSize[0] * sizeof(int));
726 #endif
727 
728  free(rgb4u);
729  }
730 
731  delete rt;
732 
734  return 0;
735 }
736 
737 
STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean)
void set_ao_maxdist(float dist)
set AO maximum occlusion distance
void set_bg_gradient_topval(float v)
set background gradient "top" value (view direction dot product)
const std::vector< material_t > & GetMaterials() const
const attrib_t & GetAttrib() const
void set_ao_samples(int cnt)
ambient occlusion (samples > 1 == on)
int add_tex2d_rgba4u(const unsigned char *img, int xres, int yres, int texflags, int userindex)
define image to be used in a texture map
int add_material_textured(float ambient, float diffuse, float specular, float shininess, float reflectivity, float opacity, float outline, float outlinewidth, int transmode, int textureindex, int userindex)
const std::vector< shape_t > & GetShapes() const
__host__ __device__ float3 make_float3(const float s)
void framebuffer_get_size(int &fbwidth, int &fbheight)
void add_directional_light(const float *dir, const float *color)
__host__ __device__ float3 fmaxf(const float3 &a, const float3 &b)
const std::string & Error() const
Error message(filled when Load or Parse failed)
int add_material(float ambient, float diffuse, float specular, float shininess, float reflectivity, float opacity, float outline, float outlinewidth, int transmode, int userindex)
add a material with an associated user-provided index
CPU and GPU profiling utility macros/routines.
#define PROFILE_PUSH_RANGE(name, cid)
Pushes a time range annotation onto the profiler&#39;s trace stack, beginning at the time of submission...
Definition: ProfileHooks.h:275
void framebuffer_resize(int fbwidth, int fbheight)
std::vector< float3 PINALLOCS(float3) > normals
Definition: TachyonOptiX.h:288
void camera_dof_enable(int onoff)
depth of field on/off
static int device_count(void)
static GPU device query
void set_camera_lookat(const float *at, const float *V)
set camera orientation to look "at" a point in space, with a given "up" direction (camera ONB "V" vec...
void print_raystats_info(void)
report performance statistics
int main(int argc, const char **argv)
Definition: objloader.cpp:148
Wavefront .obj reader class(v2 API)
std::vector< float3 PINALLOCS(float3) > vertices
Definition: TachyonOptiX.h:286
default behavior
const std::string & Warning() const
Warning message(may be filled after Load or Parse)
std::string mtl_search_path
Search path to .mtl file.
enable cutout/transparency
Adobe sRGB (gamma 2.2)
Output timing/perf data only.
Definition: TachyonOptiX.h:649
void set_ao_direct(float aod)
set AO direct lighting rescale factor
void framebuffer_clear(void)
void set_bg_gradient(float *vec)
set world "up" direction for background gradient
conventional perspective
Definition: TachyonOptiX.h:638
No console output.
Definition: TachyonOptiX.h:648
#define PROFILE_POP_RANGE()
Pops the innermost time range off of the profiler&#39;s trace stack, at the time of execution.
Definition: ProfileHooks.h:279
void set_camera_zoom(float zoomfactor)
set camera zoom factor
float real_t
std::vector< float2 PINALLOCS(float2) > tex2d
Definition: TachyonOptiX.h:293
void set_camera_dof_fnumber(float n)
set depth of field f/stop number
void set_bg_color_grad_bot(float *rgb)
set color for "bottom" of background gradient
void set_camera_type(CameraType m)
set the camera projection mode
void framebuffer_download_rgb4u(unsigned char *imgrgb4u)
void set_camera_stereo_convergence_dist(float dist)
set stereo convergence distance
void shadows_enable(int onoff)
enable/disable shadows
void set_bg_color(float *rgb)
set solid background color
void denoiser_enable(int onoff)
enable/disable denoiser
static char * getmaterialdir(const char *filename)
Definition: objloader.cpp:85
STBIDEF stbi_uc * stbi_load(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels)
void set_ao_ambient(float aoa)
set AO ambient lighting factor
void set_aa_samples(int cnt)
antialiasing (samples > 1 == on)
#define PROFILE_START()
Trigger the beginning of profiler trace capture, for those that support it.
Definition: ProfileHooks.h:253
void set_cue_mode(FogMode mode, float start, float end, float density)
set depth cueing mode and parameters
void print_coords(float *coords, int numpts, int count)
Definition: objloader.cpp:127
void set_bg_gradient_botval(float v)
set background gradient "bottom" value (view direction dot product)
STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes)
void set_verbose_mode(TachyonOptiX::Verbosity mode)
programmatically set verbosity
void set_bg_color_grad_top(float *rgb)
set color for "top" of background gradient
void set_camera_pos(const float *pos)
set the camera position
float3 uniform_color
Definition: TachyonOptiX.h:295
static unsigned int optix_version(void)
static OptiX version query
void set_camera_stereo_eyesep(float eyesep)
set stereo eye separation
void framebuffer_colorspace(int colspace)
Tachyon ray tracing host side routines and internal APIs that provide the core ray OptiX-based RTX-ac...
void set_bg_mode(BGMode m)
set background rendering mode
void set_camera_dof_focal_dist(float d)
set depth of field focal plane distance
void add_trimesh(TriangleMesh &model, int matidx)
static unsigned char * loadimage_rgba4u(const char *searchpath, const char *filename, int &xres, int &yres, int &chinfile)
Definition: objloader.cpp:102
bool ParseFromFile(const std::string &filename, const ObjReaderConfig &config=ObjReaderConfig())
Load .obj and .mtl from a file.
#define PROFILE_INITIALIZE()
Initialize the profiling system.
Definition: ProfileHooks.h:250