Tachyon (current)  Current Main Branch
parametric.cpp
Go to the documentation of this file.
1 /*
2  * parametric.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: parametric.cpp,v 1.11 2022/04/04 05:01:24 johns Exp $
8  *
9  */
10 
17 //
18 // Parametric surface plotting example
19 // John E. Stone, Dec 2021
20 //
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 #include "ProfileHooks.h"
27 
28 #define STB_IMAGE_WRITE_IMPLEMENTATION
29 #include "stb_image_write.h"
30 
31 #include "TachyonOptiX.h"
32 
33 #if defined(TACHYON_USEPINNEDMEMORY)
34 #include <cuda_runtime.h>
35 #endif
36 
37 
38 void HSItoRGB(float h, float s, float i, float &r, float &g, float &b) {
39  float t=2.0f * M_PI * h;
40  float scale = i / 2.0f;
41  r=(1.0f + s*sin(t - 2.0f*M_PI/3.0f)) * scale;
42  g=(1.0f + s*sin(t)) * scale;
43  b=(1.0f + s*sin(t + 2.0f*M_PI/3.0f)) * scale;
44 }
45 
46 
47 template <typename F>
48 float *parametric_lambda(int udiv, float umin, float umax,
49  int vdiv, float vmin, float vmax,
50  F function) {
51  int numpts = udiv * vdiv;
52 #if defined(TACHYON_USEPINNEDMEMORY)
53  float *coords;
54  cudaMallocHost(&coords, numpts * sizeof(float) * 3);
55 #else
56  float *coords = new float[numpts * 3];
57 #endif
58  float uinc = (umax-umin) / udiv;
59  float vinc = (vmax-vmin) / vdiv;
60 
61  int iu, iv;
62  float u = umin;
63  for (iu=0; iu<udiv; iu++,u+=uinc) {
64  int ind = 3*iu*vdiv;
65  float v = vmin;
66  for (iv=0; iv<vdiv; iv++,v+=vinc,ind+=3) {
67  function(coords+ind, u, v);
68  }
69  }
70 
71  return coords;
72 }
73 
74 
75 float * parametric_grid_verts(const char *surftype, int udiv, int vdiv, int &wrapmesh) {
76  const float twopi = 2.0f * M_PI;
77 
78  // wrap mesh by default, unless disabled
79  wrapmesh = 1;
80 
81  // Bour minimal surface example:
82  // https://en.wikipedia.org/wiki/Bour%27s_minimal_surface
83  // https://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/parametric_plot3d.html
84  if (!strcmp(surftype, "bour")) {
85  wrapmesh = 0;
86  return parametric_lambda(udiv, 0.0f, 0.2f * twopi,
87  vdiv, 0.0f, twopi,
88  [=](float *coords, float u, float v) {
89  const float r = 2.0f;
90 
91  float sinv, cosv;
92  sincosf(v, &sinv, &cosv);
93 
94  coords[0] = r * ( u * cosv - 0.5f * (u*u)*cosf(2.0f * v));
95  coords[1] = r * (-u * sinv * (u * cosv + 1.0f));
96  coords[2] = r * (4.0f/3.0f * powf(u, 1.5f) * cosf(3.0f * v * 0.5f));
97  }
98  );
99  }
100 
101 
102  // Sage bowtie example:
103  // https://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/parametric_plot3d.html
104  if (!strcmp(surftype, "bowtie")) {
105  return parametric_lambda(udiv, -M_PI, M_PI,
106  vdiv, -M_PI, M_PI,
107  [=](float *coords, float u, float v) {
108  const float r = 1.0f;
109 
110  float sinu, cosu, sinv, cosv;
111  sincosf(u, &sinu, &cosu);
112  sincosf(v, &sinv, &cosv);
113 
114  const float sqrt2 = 1.41421356237309504880f; // sqrtf(2.0f);
115  coords[0] = r * sinu / (sqrt2 + sinv);
116  coords[1] = r * sinu / (sqrt2 + cosv);
117  coords[2] = r * cosu / (1.0f + sqrt2);
118  }
119  );
120  }
121 
122 
123  // Sage example:
124  // https://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/parametric_plot3d.html
125  if (!strcmp(surftype, "chiclet")) {
126  return parametric_lambda(udiv, 0.0f, twopi,
127  vdiv, -M_PI, M_PI,
128  [=](float *coords, float u, float v) {
129  const float r = 1.5f;
130 
131  float sinu, cosu, sinv, cosv;
132  sincosf(u, &sinu, &cosu);
133  sincosf(v, &sinv, &cosv);
134 
135  coords[0] = 0.5f * r * (sinu + cosv);
136  coords[1] = r * cosu;
137  coords[2] = r * sinv;
138  }
139  );
140  }
141 
142 
143  // Cone
144  if (!strcmp(surftype, "cone")) {
145  return parametric_lambda(udiv, 0.0f, twopi,
146  vdiv, 0.0f, twopi,
147  [=](float *coords, float u, float v) {
148  const float r = 2.0f;
149 
150  float sinu, cosu;
151  sincosf(u, &sinu, &cosu);
152 
153  coords[0] = r * sinu * sinf(v);
154  coords[1] = r * sinf(v);
155  coords[2] = r * cosu * sinf(v);
156  }
157  );
158  }
159 
160 
161  // Klein bottle:
162  // https://de.wikipedia.org/wiki/Kleinsche_Flasche#Beschreibung_im_3-dimensionalen_Raum
163  if (!strcmp(surftype, "klein")) {
164  wrapmesh = 0;
165  float unowrapscale = udiv/float(udiv-1); // scale hack
166  float vnowrapscale = vdiv/float(vdiv-1); // scale hack
167 
168  return parametric_lambda(udiv, 0.0f, twopi,
169  vdiv, 0.0f, twopi,
170  [=](float *coords, float u, float v) {
171  float u2 = u * unowrapscale;
172  float v2 = v * vnowrapscale;
173 
174  float sinu, cosu, sinv, cosv;
175  sincosf(u2, &sinu, &cosu);
176  sincosf(v2, &sinv, &cosv);
177 
178  const float r = 2.0f - cosu;
179  coords[0] = 0.4f * (2.0f * (1.0f - sinu) * cosu +
180  r * cosv * (2.0f * expf(-powf(u2/2.0f - M_PI, 2.0f)) - 1.0f));
181  coords[1] = 0.4f * (-(6.0f * sinu +
182  0.5f * r * sinu * cosv * expf(-powf(u2 - 3.0f * M_PI * 0.5f, 2.0f))));
183  coords[2] = 0.4f * (r * sinv);
184  }
185  );
186  }
187 
188 
189  // Plane
190  if (!strcmp(surftype, "plane")) {
191  wrapmesh = 0;
192 
193  return parametric_lambda(udiv, -M_PI, M_PI,
194  vdiv, -M_PI, M_PI,
195  [=](float *coords, float u, float v) {
196  const float r = 1.0f;
197  coords[0] = r * u;
198  coords[1] = r * v;
199  coords[2] = 0.5f;
200  }
201  );
202  }
203 
204 
205  // A parametric seashell:
206  // https://www.chebfun.org/examples/geom/ParametricSurfaces.html
207  if (!strcmp(surftype, "shell")) {
208  wrapmesh = 0;
209  float unowrapscale = udiv/float(udiv-1); // scale hack
210  float vnowrapscale = vdiv/float(vdiv-1); // scale hack
211 
212  return parametric_lambda(udiv, 0.0f, twopi,
213  vdiv, 0.0f, twopi,
214  [=](float *coords, float u, float v) {
215  float u3 = u * unowrapscale * 3.0f;
216  float v2 = v * vnowrapscale;
217  float coshalfvsqr = cosf(v2 * 0.5f);
218  coshalfvsqr *= coshalfvsqr;
219  float expu_6f = expf(u3/(6.0f * M_PI));
220  coords[0] = 2.0f * ( 1.0f - expu_6f) * cosf(u3) * coshalfvsqr;
221  coords[1] = -5.5f -(-expf(u3/(3.0f * M_PI)) - sinf(v2) + expf(u3/(6.0f * M_PI)) * sinf(v2));
222  coords[2] = 2.0f * (-1.0f + expu_6f) * sinf(u3) * coshalfvsqr;
223  }
224  );
225  }
226 
227 
228  // Sphere
229  if (!strcmp(surftype, "sphere")) {
230  float vnowrapscale = vdiv/float(vdiv-1); // scale hack
231 
232  return parametric_lambda(udiv, 0.0f, twopi,
233  vdiv, M_PI*0.5f, 1.5f*M_PI,
234  [=](float *coords, float u, float v) {
235  const float r = 2.0f;
236  float v2 = v * vnowrapscale;
237  coords[0] = r * sinf(u) * cosf(v2);
238  coords[1] = r * sinf(v2);
239  coords[2] = r * cosf(u) * cosf(v2);
240  }
241  );
242  }
243 
244 
245  // Sage Dini's spiral example:
246  // https://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/parametric_plot3d.html
247  if (!strcmp(surftype, "spiral")) {
248  wrapmesh = 0;
249 
250  return parametric_lambda(udiv, 0.0f, twopi,
251  vdiv, 0.1f, 2.0f,
252  [=](float *coords, float u, float v) {
253  const float r = 2.0f;
254  float u2 = u * 2.0f;
255  float v2 = v;
256 
257  float sinu, cosu, sinv, cosv;
258  sincosf(u2, &sinu, &cosu);
259  sincosf(v2, &sinv, &cosv);
260 
261  coords[0] = r * cosu * sinv;
262  coords[1] = 1.0 + -r * ((cosv + logf(tanf(v2 * 0.5f))) + 0.2f*u2);
263  coords[2] = r * sinu * sinv;
264  }
265  );
266  }
267 
268 
269  if (!strcmp(surftype, "spiral2")) {
270  wrapmesh = 0;
271  float unowrapscale = udiv/float(udiv-1); // scale hack
272  float vnowrapscale = vdiv/float(vdiv-1); // scale hack
273 
274  return parametric_lambda(udiv, 0.0f, twopi,
275  vdiv, 0.0f, twopi,
276  [=](float *coords, float u, float v) {
277  const float r = 0.5f;
278  float u2 = u * unowrapscale * 1.4f;
279  float v2 = v * vnowrapscale * 0.4f;
280 
281  float sinu, cosu, sinv, cosv;
282  sincosf(u2, &sinu, &cosu);
283  sincosf(v2, &sinv, &cosv);
284 
285  coords[0] = -1.0f + r * u2 * sinu * cosv;
286  coords[1] = -3.0f + r * u2 * sinv;
287  coords[2] = r * u2 * cosu * cosv;
288  }
289  );
290  }
291 
292 
293  if (!strcmp(surftype, "torus")) {
294  return parametric_lambda(udiv, 0.0f, twopi,
295  vdiv, 0.0f, twopi,
296  [=](float *coords, float u, float v) {
297  float sinu, cosu, sinv, cosv;
298  sincosf(u, &sinu, &cosu);
299  sincosf(v, &sinv, &cosv);
300 
301  coords[0] = 2.0f * cosu * (1.0f - cosv * 0.5f);
302  coords[1] = 2.0f * sinv * 0.5f;
303  coords[2] = 2.0f * sinu * (1.0f - cosv * 0.5f);
304  }
305  );
306  }
307 
308 
309  // Sage trefoil example:
310  // https://doc.sagemath.org/html/en/reference/plot3d/sage/plot/plot3d/parametric_plot3d.html
311  if (!strcmp(surftype, "trefoil")) {
312  return parametric_lambda(udiv, -M_PI, M_PI,
313  vdiv, -M_PI, M_PI,
314  [=](float *coords, float u, float v) {
315  const float r = 0.7f;
316  float v2 = 2.0f * v;
317  float v3 = 3.0f * v;
318  coords[0] = r * ((4.0f * (1.0f + 0.25f*sinf(v3)) + cosf(u))*cosf(v2));
319  coords[1] = r * ((4.0f * (1.0f + 0.25f*sinf(v3)) + cosf(u))*sinf(v2));
320  coords[2] = r * (sinf(u) + 2.0f*cosf(v3));
321  }
322  );
323  }
324 
325 
326  if (!strcmp(surftype, "trefoil2")) {
327  return parametric_lambda(udiv, 0.0f, twopi,
328  vdiv, 0.0f, twopi,
329  [=](float *coords, float u, float v) {
330  const float r = 2.0f;
331  float u2 = 2.0f * u;
332  float u3 = 3.0f * u;
333  const float twothirdspi = M_PI * 2.0f / 3.0f;
334  coords[0] = r * sinf(u3) / (2.0f + cosf(v));
335  coords[1] = r / 2.0f * (cosf(u) - 2.0f * cosf(u2)) * (2.0f + cosf(v)) * (2.0f + cosf(v + twothirdspi)) / 4.0f;
336  coords[2] = r * (sinf(u) + 2.0f * sinf(u2)) / (2.0f + cosf(v + twothirdspi)) / 4.0f;
337  }
338  );
339  }
340 
341 
342  // Mathematica example:
343  // https://mathematica.stackexchange.com/questions/37698/how-to-plot-a-certain-surface-what-is-its-parametric-equation
344  if (!strcmp(surftype, "twisty")) {
345  return parametric_lambda(udiv, 0.0f, twopi,
346  vdiv, 0.0f, twopi,
347  [=](float *coords, float u, float v) {
348  const float r = 0.5f;
349  float u3 = 3.0f * u;
350  float v3 = 3.0f * v;
351  coords[0] = r * cosf(v) * (6.0f - (1.25f + sinf(u3)) * sinf(u - v3));
352  coords[2] = r * (6.0f - (1.25f + sinf(u3)) * sinf(u - v3)) * sinf(v);
353  coords[1] = r * -cosf(u - v3) * (1.25f + sinf(u3));
354  }
355  );
356  }
357 
358 
359  // Vase
360  if (!strcmp(surftype, "vase")) {
361  return parametric_lambda(udiv, 0.0f, twopi,
362  vdiv, -M_PI, 2.0f/3.0f*M_PI,
363  [=](float *coords, float u, float v) {
364  float sinu, cosu;
365  sincosf(u, &sinu, &cosu);
366  coords[0] = cosu;
367  coords[1] = v;
368  coords[2] = sinu;
369  }
370  );
371  }
372 
373 
374  return NULL; // no surface name was recognized, bail out...
375 }
376 
377 
378 float * parametric_grid_colors3f(int udiv, int vdiv) {
379  int numpts = udiv * vdiv;
380 #if defined(TACHYON_USEPINNEDMEMORY)
381  float *colors;
382  cudaMallocHost(&colors, numpts * sizeof(float) * 3);
383 #else
384  float *colors = new float[numpts * 3];
385 #endif
386 
387  for (int iu=0; iu<udiv; iu++) {
388  for (int iv=0; iv<vdiv; iv++) {
389  int i = iu*vdiv + iv;
390  int ind = 3*i;
391 
392  float h = float(i) / float(numpts);
393  float s = 1.0f;
394 // // stripes
395 // float l = (fmodf(h*40.0f, 1.0f) > 0.5f) ? 0.85f : 0.35f;
396  float l = 1.0f;
397 
398  HSItoRGB(h, s, l, colors[ind], colors[ind + 1], colors[ind + 2]);
399  }
400  }
401 
402  return colors;
403 }
404 
405 
406 float * parametric_grid_colors4f(int udiv, int vdiv) {
407  int numpts = udiv * vdiv;
408 #if defined(TACHYON_USEPINNEDMEMORY)
409  float *colors;
410  cudaMallocHost(&colors, numpts * sizeof(float) * 4);
411 #else
412  float *colors = new float[numpts * 4];
413 #endif
414 
415  for (int iu=0; iu<udiv; iu++) {
416  for (int iv=0; iv<vdiv; iv++) {
417  int i = iu*vdiv + iv;
418  int ind = 4*i;
419 
420  float h = float(i) / float(numpts);
421  float s = 1.0f;
422 // // stripes
423 // float l = (fmodf(h*40.0f, 1.0f) > 0.5f) ? 0.85f : 0.35f;
424  float l = 1.0f;
425 
426  HSItoRGB(h, s, l, colors[ind], colors[ind + 1], colors[ind + 2]);
427  colors[ind + 3] = 1.0f;
428  }
429  }
430 
431  return colors;
432 }
433 
434 
435 int * parametric_quadmesh_indices(int udiv, int vdiv, int wrapmesh) {
436  // if we're not doing wraparound, don't generate associated connections
437  int umax = (wrapmesh) ? udiv : (udiv-1);
438  int vmax = (wrapmesh) ? vdiv : (vdiv-1);
439 
440  int numedges = umax * vmax;
441 #if defined(TACHYON_USEPINNEDMEMORY)
442  int * quadmesh_indices;
443  cudaMallocHost(&quadmesh_indices, numedges * sizeof(int) * 4);
444 #else
445  int * quadmesh_indices = new int[numedges * 4];
446 #endif
447 
448  for (int iu=0; iu<umax; iu++) {
449  for (int iv=0; iv<vmax; iv++) {
450  int vertind = iu * vdiv + iv;
451  int quadind = 4 * (iu * vmax + iv);
452  int iunext = (iu+1) % udiv; // wrap mesh
453  int ivnext = (iv+1) % vdiv; // wrap mesh
454 
455  // mesh needs to wrap around
456  quadmesh_indices[quadind ] = vertind; // v00 v00
457  quadmesh_indices[quadind + 1] = iu * vdiv + ivnext; // v01 v10
458  quadmesh_indices[quadind + 2] = iunext * vdiv + ivnext; // v11 v11
459  quadmesh_indices[quadind + 3] = iunext * vdiv + iv; // v10 v01
460  }
461  }
462 
463  return quadmesh_indices;
464 }
465 
466 
467 int * parametric_trimesh_indices(int udiv, int vdiv, int wrapmesh) {
468  // if we're not doing wraparound, don't generate associated connections
469  int umax = (wrapmesh) ? udiv : (udiv-1);
470  int vmax = (wrapmesh) ? vdiv : (vdiv-1);
471 
472  int numedges = umax * vmax;
473 #if defined(TACHYON_USEPINNEDMEMORY)
474  int * trimesh_indices;
475  cudaMallocHost(&trimesh_indices, numedges * sizeof(int) * 2 * 3);
476 #else
477  int * trimesh_indices = new int[numedges * 2 * 3];
478 #endif
479 
480  for (int iu=0; iu<umax; iu++) {
481  for (int iv=0; iv<vmax; iv++) {
482  int vertind = iu * vdiv + iv;
483  int quadind = 6 * (iu * vmax + iv);
484  int iunext = (iu+1) % udiv; // wrap mesh
485  int ivnext = (iv+1) % vdiv; // wrap mesh
486 
487  // mesh needs to wrap around
488  trimesh_indices[quadind ] = vertind;
489  trimesh_indices[quadind + 1] = iu * vdiv + ivnext;
490  trimesh_indices[quadind + 2] = iunext * vdiv + iv;
491 
492  trimesh_indices[quadind + 3] = iu * vdiv + ivnext;
493  trimesh_indices[quadind + 4] = iunext * vdiv + iv;
494  trimesh_indices[quadind + 5] = iunext * vdiv + ivnext;
495  }
496  }
497 
498  return trimesh_indices;
499 }
500 
501 
502 int * parametric_wiremesh_indices(int udiv, int vdiv, int wrapmesh) {
503  // if we're not doing wraparound, don't generate associated connections
504  int umax = (wrapmesh) ? udiv : (udiv-1);
505  int vmax = (wrapmesh) ? vdiv : (vdiv-1);
506 
507  int numedges = umax * vmax;
508 #if defined(TACHYON_USEPINNEDMEMORY)
509  int * wiremesh_indices;
510  cudaMallocHost(&wiremesh_indices, numedges * sizeof(int) * 2 * 3);
511 #else
512  int * wiremesh_indices = new int[numedges * 2 * 2];
513 #endif
514 
515  for (int iu=0; iu<umax; iu++) {
516  for (int iv=0; iv<vmax; iv++) {
517  int vertind = iu * vdiv + iv;
518  int cylind = 4 * (iu * vmax + iv);
519  int iunext = (iu+1) % udiv; // wrap mesh
520  int ivnext = (iv+1) % vdiv; // wrap mesh
521 
522  // mesh needs to wrap around
523  wiremesh_indices[cylind ] = vertind;
524  wiremesh_indices[cylind + 1] = iu * vdiv + ivnext;
525 
526  wiremesh_indices[cylind + 2] = vertind;
527  wiremesh_indices[cylind + 3] = iunext * vdiv + iv;
528  }
529  }
530 
531  return wiremesh_indices;
532 }
533 
534 
535 //
536 // Draw parametric surface as a triangle mesh
537 //
538 void gen_trimesh(TachyonOptiX *rt, int udiv, int vdiv, int wrapmesh,
539  float *coords, float *colors, int *trimesh_indices, int mat) {
540  int numpts = udiv * vdiv;
541 
542  // if we're not doing wraparound, don't generate associated connections
543  int umax = (wrapmesh) ? udiv : (udiv-1);
544  int vmax = (wrapmesh) ? vdiv : (vdiv-1);
545  int numedges = umax * vmax;
546 
547  TriangleMesh mesh;
548  mesh.vertices.resize(numpts);
549  mesh.vertcolors3f.resize(numpts);
550  mesh.indices.resize(numedges*2);
551 
552  float3 *verts = mesh.vertices.data();
553  float3 *cols = mesh.vertcolors3f.data();
554  int3 *indices = mesh.indices.data();
555 
556  memcpy(verts, coords, numpts * 3 * sizeof(float));
557  memcpy(cols, colors, numpts * 3 * sizeof(float));
558  memcpy(indices, trimesh_indices, numedges * 2 * 3 * sizeof(int));
559 
560  rt->add_trimesh(mesh, mat);
561 }
562 
563 
564 //
565 // Draw parametric surface as a quad mesh
566 //
567 void gen_quadmesh(TachyonOptiX *rt, int udiv, int vdiv, int wrapmesh,
568  float *coords, float *colors, int *quadmesh_indices, int mat) {
569  int numpts = udiv * vdiv;
570 
571  // if we're not doing wraparound, don't generate associated connections
572  int umax = (wrapmesh) ? udiv : (udiv-1);
573  int vmax = (wrapmesh) ? vdiv : (vdiv-1);
574  int numedges = umax * vmax;
575 
576  QuadMesh mesh;
577  mesh.vertices.resize(numpts);
578  mesh.vertcolors3f.resize(numpts);
579  mesh.indices.resize(numedges);
580 
581  float3 *verts = mesh.vertices.data();
582  float3 *cols = mesh.vertcolors3f.data();
583  int4 *indices = mesh.indices.data();
584 
585  memcpy(verts, coords, numpts * 3 * sizeof(float));
586  memcpy(cols, colors, numpts * 3 * sizeof(float));
587  memcpy(indices, quadmesh_indices, numedges * 4 * sizeof(int));
588 
589  rt->add_quadmesh(mesh, mat);
590 }
591 
592 
593 //
594 // Draw points on parametric surface using spheres
595 //
596 void gen_spheresurf(TachyonOptiX *rt, int udiv, int vdiv,
597  float *coords, float radius, float *colors, int mat) {
598  int numpts = udiv * vdiv;
599 
600  SphereArray spheres;
601  spheres.center.resize(numpts);
602  spheres.radius.resize(numpts);
603  spheres.primcolors3f.resize(numpts);
604 
605  float3 *verts = spheres.center.data();
606  float *radii = spheres.radius.data();
607  float3 *cols = spheres.primcolors3f.data();
608 
609  memcpy(verts, coords, numpts * 3 * sizeof(float));
610 
611  if (colors != NULL) {
612  memcpy(cols, colors, numpts * 3 * sizeof(float));
613  } else {
614  for (int i=0; i<numpts; i++) {
615  cols[i]=make_float3(0.3f, 0.3f, 0.3f);
616  }
617  }
618  for (int i=0; i<numpts; i++)
619  radii[i]=radius;
620 
621  rt->add_spherearray(spheres, mat);
622 }
623 
624 
625 
626 //
627 // Draw wire mesh with cylinders
628 //
629 void gen_wiremesh(TachyonOptiX *rt, int udiv, int vdiv, int wrapmesh,
630  float *coords, float radius, float *colors,
631  int *wiremesh_indices, int mat) {
632 // int numpts = udiv * vdiv;
633 
634  // if we're not doing wraparound, don't generate associated connections
635  int umax = (wrapmesh) ? udiv : (udiv-1);
636  int vmax = (wrapmesh) ? vdiv : (vdiv-1);
637  int numedges = umax * vmax;
638 
639  CylinderArray cyls;
640  cyls.start.resize(numedges*2);
641  cyls.end.resize(numedges*2);
642  cyls.radius.resize(numedges*2);
643  cyls.primcolors3f.resize(numedges*2);
644 
645  float3 *vstart = cyls.start.data();
646  float3 *vend = cyls.end.data();
647  float *vrad = cyls.radius.data();
648  float3 *cols = cyls.primcolors3f.data();
649 
650  for (int i=0; i<numedges*2; i++) {
651  int idx1 = 3 * wiremesh_indices[i*2 ];
652  int idx2 = 3 * wiremesh_indices[i*2+1];
653  vstart[i] = make_float3(coords[idx1], coords[idx1+1], coords[idx1+2]);
654  vend[i] = make_float3(coords[idx2], coords[idx2+1], coords[idx2+2]);
655  vrad[i] = radius;
656  if (colors)
657  cols[i] = make_float3(colors[idx1], colors[idx1+1], colors[idx1+2]);
658  else
659  cols[i] = make_float3(0.0f, 0.0f, 0.0f);
660  }
661 
662  rt->add_cylarray(cyls, mat);
663 }
664 
665 
666 
667 //
668 // Draw a quad or triangle mesh for the floor
669 //
670 void gen_floor(TachyonOptiX *rt, float width, float height, float length, int mat) {
671  float vertex[] = {
672  -100.0f, 4.0f, -100.0f,
673  -100.0f, 4.0f, 100.0f,
674  100.0f, 4.0f, -100.0f,
675  100.0f, 4.0f, 100.0f
676  };
677  float color[] = {
678  1.0f, 1.0f, 1.0f, 1.0f,
679  1.0f, 1.0f, 1.0f, 1.0f,
680  1.0f, 1.0f, 1.0f, 1.0f,
681  1.0f, 1.0f, 1.0f, 1.0f
682  };
683  int index[] = {
684  0, 1, 2, // triangle-1
685  1, 2, 3 // triangle-2
686  };
687 
688  vertex[ 0] = -width / 2.0f;
689  vertex[ 3] = -width / 2.0f;
690  vertex[ 6] = width / 2.0f;
691  vertex[ 9] = width / 2.0f;
692 
693  vertex[ 1] = height;
694  vertex[ 4] = height;
695  vertex[ 7] = height;
696  vertex[10] = height;
697 
698  vertex[ 2] = -length / 2.0f;
699  vertex[ 5] = length / 2.0f;
700  vertex[ 8] = -length / 2.0f;
701  vertex[11] = length / 2.0f;
702 
703  TriangleMesh mesh;
704  mesh.vertices.resize(4);
705  mesh.vertcolors3f.resize(4);
706  mesh.indices.resize(2*3);
707 
708  float3 *verts = mesh.vertices.data();
709  float3 *cols = mesh.vertcolors3f.data();
710  int3 *indices = mesh.indices.data();
711 
712  memcpy(verts, vertex, 4 * 3 * sizeof(float));
713  memcpy(cols, color, 4 * 3 * sizeof(float));
714  memcpy(indices, index, 2 * 3 * sizeof(int));
715 
716  rt->add_trimesh(mesh, mat);
717 }
718 
719 
720 
721 void print_coords(float *coords, int numpts, int count) {
722  printf("Coordinate dump:\n");
723  if (count > numpts)
724  count = numpts;
725 
726  int i;
727  for (i=0; i<count; i++) {
728  int ind = i * 3;
729  printf("[%d]: %.3f %.3f %.3f\n",
730  i, coords[ind], coords[ind+1], coords[ind+2]);
731 
732  }
733  printf("...\n");
734  for (i=numpts-count; i<numpts; i++) {
735  int ind = i * 3;
736  printf("[%d]: %.3f %.3f %.3f\n",
737  i, coords[ind], coords[ind+1], coords[ind+2]);
738  }
739 }
740 
741 
742 int main(int argc, const char **argv) {
744 
745  // some sane defaults
746  int imgSize[2] = {4096, 4096 }; // W x H
747  const char *surftype = "twisty";
748  int udiv = 80;
749  int vdiv = 80;
750  int wireframe = 0;
751  int usequads = 0;
752  int nofloor = 0;
753  int nospheres = 0;
754  float radius = 0.025f;
755  int ambientocclusion = 1;
756  int dumpcoords = 0;
757  int nosurf = 0;
758  int warmup = 0;
759 
760  //
761  // camera defaults
762  //
763 #if 0
764  float cam_pos[] = {0.0f, -6.0f, -8.0f}; // look at origin from -Z
765  float cam_up[] = {0.0f, 1.0f, 0.0f}; // Y-up
766  float cam_view[3];
767 
768  // look at origin
769  float invlen = 1.0f / sqrtf(cam_pos[0]*cam_pos[0] +
770  cam_pos[1]*cam_pos[1] +
771  cam_pos[2]*cam_pos[2]);
772  cam_view[0] = -cam_pos[0] * invlen;
773  cam_view[1] = -cam_pos[1] * invlen;
774  cam_view[2] = -cam_pos[2] * invlen;
775 #endif
776 
777  //
778  // parse args
779  //
780  if (argc == 1) {
781  printf("Usage: %s surftype udivs vdivs [optional flags]\n", argv[0]);
782  printf(" optional flags: -nofloor: don't draw floor\n");
783  printf(" -nospheres: don't draw spheres\n");
784  printf(" -quads: draw surfaces using quads\n");
785  printf(" -wireframe: draw wireframe over surfaces\n");
786  printf(" -ao: add renderer-specific AO lighting\n");
787  printf(" -res XXXX YYYY: override default image res\n");
788  return -1;
789  }
790 
791  // parse surface type
792  if (argc > 1) {
793  surftype = argv[1];
794  }
795 
796  // parse udiv/vdiv params
797  if (argc > 3) {
798  udiv = atoi(argv[2]);
799  vdiv = atoi(argv[3]);
800  }
801 
802  // parse remaining optional parameter flags
803  if (argc > 4) {
804  for (int i=4; i<argc; i++) {
805  if (!strcmp("-wireframe", argv[i])) {
806  wireframe = 1;
807  radius = 0.00625f;
808  printf("Drawing wireframe mesh over surface...\n");
809  continue;
810  }
811 
812  if (!strcmp("-quads", argv[i])) {
813  usequads = 1;
814  printf("Drawing surface using quads.\n");
815  continue;
816  }
817 
818  if (!strcmp("-nofloor", argv[i])) {
819  nofloor = 1;
820  printf("Drawing surface without floor.\n");
821  continue;
822  }
823 
824  if (!strcmp("-nosurf", argv[i])) {
825  nosurf = 1;
826  printf("Don't draw surface.\n");
827  continue;
828  }
829 
830  if (!strcmp("-nospheres", argv[i])) {
831  nospheres = 1;
832  printf("Drawing surface without sphere points.\n");
833  continue;
834  }
835 
836  if (!strcmp("-ao", argv[i])) {
837  ambientocclusion = 1;
838  printf("Enabling renderer-specific AO lighting.\n");
839  continue;
840  }
841 
842  if (!strcmp("-noao", argv[i])) {
843  ambientocclusion = 0;
844  printf("Disabling renderer-specific AO lighting.\n");
845  continue;
846  }
847 
848  if (!strcmp("-res", argv[i])) {
849  if ((argc - i) >= 2) {
850  imgSize[0] = atoi(argv[++i]);
851  imgSize[1] = atoi(argv[++i]);
852  printf("Image resolution set to: %d x %d\n", imgSize[0], imgSize[1]);
853  }
854  continue;
855  }
856 
857 #if 0
858  if (!strcmp("-pause", argv[i])) {
859  sleep(10);
860  }
861 #endif
862 
863  if (!strcmp("-dumpcoords", argv[i])) {
864  dumpcoords = 10;
865  if ((argc - i) >= 2) {
866  dumpcoords = atoi(argv[++i]);
867  }
868  }
869 
870  if (!strcmp("-warmup", argv[i])) {
871  warmup = 1;
872  printf("Enabling profiling warm-up pass and timing.\n");
873  continue;
874  }
875 
876  printf("Unrecognized flag: '%s'.\n", argv[i]);
877  }
878  }
879 
880 
881 #if defined(TACHYON_USEPINNEDMEMORY)
882  printf("USING PINNED HOST MEMORY ALLOCATIONS\n");
883 #endif
884 
885 
886  //
887  // Compute parametric surface vertices, faces, colors, and normals
888  //
889  int numpts = udiv * vdiv;
890  printf("Calculating parametric grid type: %s, udiv: %d, vdiv: %d, points: %d\n", surftype, udiv, vdiv, numpts);
891 
892  int wrapmesh = 0; // flag indicating 2-D mesh wraparound
893  float *coords = parametric_grid_verts(surftype, udiv, vdiv, wrapmesh);
894  if (!coords) {
895  printf("Surface type '%s' unrecognized, exiting.\n", surftype);
896  return -1;
897  }
898 
899  if (dumpcoords) {
900  print_coords(coords, numpts, dumpcoords);
901  }
902 
903  PROFILE_PUSH_RANGE("Calculate Mesh", 0);
904  float *colors = parametric_grid_colors3f(udiv, vdiv);
905 // float *colors = parametric_grid_colors4f(udiv, vdiv);
906  int *quadmesh_indices = parametric_quadmesh_indices(udiv, vdiv, wrapmesh);
907  int *trimesh_indices = parametric_trimesh_indices(udiv, vdiv, wrapmesh);
908  int *wiremesh_indices = parametric_wiremesh_indices(udiv, vdiv, wrapmesh);
910 
911  if (!nosurf) {
912  printf("Surface mesh contains %d quads, or %d triangles\n",
913  udiv*vdiv, udiv*vdiv*2);
914  }
915  if (!nospheres) {
916  printf("Surface scene contains %d spheres\n", numpts);
917  }
918 
919 
920  PROFILE_PUSH_RANGE("Initialize Tachyon", 0);
921  printf("Initializing TachyonOptiX...");
922 
925  unsigned int devcount = TachyonOptiX::device_count();
926  unsigned int optixversion = TachyonOptiX::optix_version();
927 
928  printf("Found %u OptiX devices\n", devcount);
929  printf("OptiX version used for build: %d.%d.%d (%u)\n",
930  optixversion/10000,
931  (optixversion%10000)/100,
932  (optixversion%100),
933  optixversion);
934 
935  TachyonOptiX *rt = new TachyonOptiX();
937 
938  PROFILE_PUSH_RANGE("Build Scene", 0);
939  //
940  // Build scene
941  //
942 
943  // create and setup camera
945  rt->framebuffer_resize(imgSize[0], imgSize[1]);
946 // rt->set_verbose_mode(TachyonOptiX::RT_VERB_MIN);
947 // rt->set_verbose_mode(TachyonOptiX::RT_VERB_DEBUG);
948  float rtbgcolor[] = { 1.0, 1.0, 1.0 };
949  float rtbggradtopcolor[] = { 0.6, 0.0, 0.0 };
950  float rtbggradbotcolor[] = { 0.0, 0.0, 0.6 };
951 
952  rt->set_bg_color(rtbgcolor);
953  rt->set_bg_color_grad_top(rtbggradtopcolor);
954  rt->set_bg_color_grad_bot(rtbggradbotcolor);
955 
956  float bggradient[] = { 0.0f, 1.0f, 0.0f };
957  rt->set_bg_gradient(bggradient);
958  rt->set_bg_gradient_topval(1.0f);
959  rt->set_bg_gradient_botval(-1.0f);
960 
961 // rt->set_bg_mode(TachyonOptiX::RT_BACKGROUND_TEXTURE_SOLID);
963 // rt->set_bg_mode(TachyonOptiX::RT_BACKGROUND_TEXTURE_SKY_SPHERE);
964 
965  rt->set_aa_samples(16);
966  rt->shadows_enable(1);
967 
968  if (ambientocclusion) {
969  rt->set_ao_samples(16);
970  rt->set_ao_ambient(0.9);
971  rt->set_ao_direct(0.2);
972  rt->set_ao_maxdist(100.2);
973  }
974 
975  rt->camera_dof_enable(0);
976 
977 
978  float lightdir0[] = { -0.5f, 0.5f, -1.0f };
979  float lightcolor0[] = { 1.0f, 1.0f, 1.0f };
980  rt->add_directional_light(lightdir0, lightcolor0);
981 
982  // set camera params
984 // rt->set_camera_type(TachyonOptiX::RT_ORTHOGRAPHIC);
985 
986  float campos[3] = {0.0f, 10.0f, 12.f};
987 // float camU[3] = {1.0f, 0.0f, 0.0f};
988  float camV[3] = {0.0f, 1.0f, 0.0f};
989 // float camW[3] = {0.0f, 0.0f, 1.0f};
990  float camat[3] = {0.0f, 0.0f, 0.0f};
991 
992  rt->set_camera_pos(campos);
993 // rt->set_camera_ONB(camU, camV, camW);
994  rt->set_camera_lookat(camat, camV);
995 
996  rt->set_camera_zoom(0.5f);
997  rt->set_camera_dof_fnumber(64.0f);
998  rt->set_camera_dof_focal_dist(0.7f);
999  // set stereoscopic display parameters
1000  rt->set_camera_stereo_eyesep(0.6f);
1002 
1003  // set depth cueing parameters
1004  float start = 1.0f;
1005  float end = 30.0f;
1006  float density = 0.33f;
1007 // rt->set_cue_mode(TachyonOptiX::RT_FOG_LINEAR, start, end, density);
1008 // rt->set_cue_mode(TachyonOptiX::RT_FOG_EXP, start, end, density);
1009 // rt->set_cue_mode(TachyonOptiX::RT_FOG_EXP2, start, end, density);
1010  rt->set_cue_mode(TachyonOptiX::RT_FOG_NONE, start, end, density);
1011 
1012  int mat = 0;
1013  float ambient = 0.0f;
1014  float diffuse = 0.7f;
1015  float specular = 0.0f;
1016  float shininess = 0.0f;
1017  float reflectivity = 0.0f;
1018  float opacity = 1.0f;
1019  float outline = 0.0f;
1020  float outlinewidth = 0.0f;
1021  int transmode = 0;
1022 
1023  rt->add_material(ambient, diffuse, specular, shininess, reflectivity,
1024  opacity, outline, outlinewidth, transmode, mat);
1026 
1027 
1028  if (warmup) {
1030  PROFILE_PUSH_RANGE("Renderer Warmup Passes", 0);
1031  // force warmup passes on an empty scene so our timings of subsequent
1032  // scene data are way more realistic
1033  for (int w=0; w<100; w++) {
1034  rt->render();
1035  rt->framebuffer_clear();
1036  }
1038  }
1039 
1041 
1042  // XXX Start Nsight Compute Profiles here...
1043  PROFILE_START();
1044 
1045  PROFILE_PUSH_RANGE("Generate Scene", 0);
1046  if (!nospheres) {
1047  // Draw points on parametric surface using spheres
1048  gen_spheresurf(rt, udiv, vdiv, coords, radius,
1049  (wireframe) ? NULL : colors, mat);
1050  }
1051 
1052  if (!nosurf) {
1053  if (wireframe) {
1054  // Draw wire mesh with cylinders
1055  gen_wiremesh(rt, udiv, vdiv, wrapmesh, coords, radius, (wireframe) ? NULL : colors, wiremesh_indices, mat);
1056  }
1057 
1058  if (usequads) {
1059  // Draw parametric surface as a quad mesh
1060  gen_quadmesh(rt, udiv, vdiv, wrapmesh, coords, colors, quadmesh_indices, mat);
1061  } else {
1062  // Draw parametric surface as a triangle mesh
1063  gen_trimesh(rt, udiv, vdiv, wrapmesh, coords, colors, trimesh_indices, mat);
1064  }
1065  }
1066 
1067  if (!nofloor) {
1068  // Draw a quad or triangle mesh for the floor
1069  gen_floor(rt, 200.0f, -4.0f, 200.0f, mat);
1070  }
1072 
1073  PROFILE_PUSH_RANGE("Render Scene", 0);
1074  printf("Rendering frames w/ accumulation buffer...\n");
1075  // render 100 accumulated frames
1076 // for (int frames = 0; frames < 3; frames++) {
1077  rt->render();
1078 // }
1080 
1081  rt->print_raystats_info();
1082 
1083  PROFILE_PUSH_RANGE("Write Output Image", 0);
1084 
1085  char filename[1024];
1086  sprintf(filename, "parametric-%s-%d-%d.png", surftype, udiv, vdiv);
1087  printf("Writing accumulated frames to '%s'...\n", filename);
1088  if (filename != NULL) {
1089  rt->framebuffer_get_size(imgSize[0], imgSize[1]);
1090  size_t bufsz = imgSize[0] * imgSize[1] * sizeof(int);
1091  unsigned char *rgb4u = (unsigned char *) calloc(1, bufsz);
1092  rt->framebuffer_download_rgb4u(rgb4u);
1093 
1094 #if 0
1095  if (writealpha) {
1096 printf("Writing rgba4u alpha channel output image 2\n");
1097  if (write_image_file_rgba4u(filename, rgb4u, imgSize[0], imgSize[1]))
1098  printf("Failed to write image '%s'!!\n", filename);
1099  } else {
1100  if (write_image_file_rgb4u(filename, rgb4u, imgSize[0], imgSize[1]))
1101  printf("Failed to write image '%s'!!\n", filename);
1102  }
1103 #else
1105 
1106  stbi_write_png(filename, imgSize[0], imgSize[1], 4, rgb4u, imgSize[0] * sizeof(int));
1107 #endif
1108 
1109  free(rgb4u);
1110  }
1111 
1112 
1113 #if defined(TACHYON_USEPINNEDMEMORY)
1114  cudaFreeHost(coords);
1115  cudaFreeHost(colors);
1116  cudaFreeHost(quadmesh_indices);
1117  cudaFreeHost(trimesh_indices);
1118  cudaFreeHost(wiremesh_indices);
1119 #else
1120  delete [] coords;
1121  delete [] colors;
1122  delete [] quadmesh_indices;
1123  delete [] trimesh_indices;
1124  delete [] wiremesh_indices;
1125 #endif
1126 
1127  delete rt;
1128 
1130  return 0;
1131 }
1132 
1133 
STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean)
void gen_spheresurf(TachyonOptiX *rt, int udiv, int vdiv, float *coords, float radius, float *colors, int mat)
Definition: parametric.cpp:596
void set_ao_maxdist(float dist)
set AO maximum occlusion distance
std::vector< float3 PINALLOCS(float3)> center
Definition: TachyonOptiX.h:245
void set_bg_gradient_topval(float v)
set background gradient "top" value (view direction dot product)
float * parametric_grid_verts(const char *surftype, int udiv, int vdiv, int &wrapmesh)
Definition: parametric.cpp:75
void gen_quadmesh(TachyonOptiX *rt, int udiv, int vdiv, int wrapmesh, float *coords, float *colors, int *quadmesh_indices, int mat)
Definition: parametric.cpp:567
std::vector< float3 PINALLOCS(float3)> vertcolors3f
Definition: TachyonOptiX.h:217
void HSItoRGB(float h, float s, float i, float &r, float &g, float &b)
Definition: parametric.cpp:38
std::vector< float PINALLOCS(float)> radius
Definition: TachyonOptiX.h:199
void gen_trimesh(TachyonOptiX *rt, int udiv, int vdiv, int wrapmesh, float *coords, float *colors, int *trimesh_indices, int mat)
Definition: parametric.cpp:538
void set_ao_samples(int cnt)
ambient occlusion (samples > 1 == on)
float * parametric_grid_colors3f(int udiv, int vdiv)
Definition: parametric.cpp:378
void gen_wiremesh(TachyonOptiX *rt, int udiv, int vdiv, int wrapmesh, float *coords, float radius, float *colors, int *wiremesh_indices, int mat)
Definition: parametric.cpp:629
int * parametric_wiremesh_indices(int udiv, int vdiv, int wrapmesh)
Definition: parametric.cpp:502
__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)
std::vector< float3 PINALLOCS(float3)> primcolors3f
Definition: TachyonOptiX.h:200
int main(int argc, const char **argv)
Definition: parametric.cpp:742
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
std::vector< float PINALLOCS(float)> radius
Definition: TachyonOptiX.h:246
void framebuffer_resize(int fbwidth, int fbheight)
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...
#define M_PI
void print_raystats_info(void)
report performance statistics
std::vector< float3 PINALLOCS(float3) > vertices
Definition: TachyonOptiX.h:286
std::vector< float3 PINALLOCS(float3)> start
Definition: TachyonOptiX.h:197
Adobe sRGB (gamma 2.2)
Output timing/perf data only.
Definition: TachyonOptiX.h:649
int * parametric_trimesh_indices(int udiv, int vdiv, int wrapmesh)
Definition: parametric.cpp:467
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
void add_spherearray(SphereArray &model, int matidx)
conventional perspective
Definition: TachyonOptiX.h:638
No console output.
Definition: TachyonOptiX.h:648
std::vector< float3 PINALLOCS(float3) > vertcolors3f
Definition: TachyonOptiX.h:290
float * parametric_grid_colors4f(int udiv, int vdiv)
Definition: parametric.cpp:406
#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
void set_camera_dof_fnumber(float n)
set depth of field f/stop number
std::vector< float3 PINALLOCS(float3)> vertices
Definition: TachyonOptiX.h:213
std::vector< int4 PINALLOCS(int4)> indices
Definition: TachyonOptiX.h:214
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 print_coords(float *coords, int numpts, int count)
Definition: parametric.cpp:721
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 set_ao_ambient(float aoa)
set AO ambient lighting factor
int * parametric_quadmesh_indices(int udiv, int vdiv, int wrapmesh)
Definition: parametric.cpp:435
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 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
__host__ __device__ float length(const float3 &v)
void set_camera_pos(const float *pos)
set the camera position
static unsigned int optix_version(void)
static OptiX version query
std::vector< int3 PINALLOCS(int3) > indices
Definition: TachyonOptiX.h:287
void set_camera_stereo_eyesep(float eyesep)
set stereo eye separation
void gen_floor(TachyonOptiX *rt, float width, float height, float length, int mat)
Definition: parametric.cpp:670
void framebuffer_colorspace(int colspace)
Tachyon ray tracing host side routines and internal APIs that provide the core ray OptiX-based RTX-ac...
void add_cylarray(CylinderArray &model, int matidx)
float * parametric_lambda(int udiv, float umin, float umax, int vdiv, float vmin, float vmax, F function)
Definition: parametric.cpp:48
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
std::vector< float3 PINALLOCS(float3)> primcolors3f
Definition: TachyonOptiX.h:247
void add_trimesh(TriangleMesh &model, int matidx)
std::vector< float3 PINALLOCS(float3)> end
Definition: TachyonOptiX.h:198
void add_quadmesh(QuadMesh &model, int matidx)
#define PROFILE_INITIALIZE()
Initialize the profiling system.
Definition: ProfileHooks.h:250