1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    TestOSPRayRenderMesh.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 // This test verifies that we can do simple mesh rendering with ospray
16 // and that VTK's many standard rendering modes (points, lines, surface, with
17 // a variety of color controls (actor, point, cell, texture) etc work as
18 // they should.
19 //
20 // The command line arguments are:
21 // -I        => run in interactive mode; unless this is used, the program will
22 //              not allow interaction and exit.
23 //              In interactive mode it responds to the keys listed
24 //              vtkOSPRayTestInteractor.h
25 // -GL       => users OpenGL instead of OSPRay to render
26 // -type N   => where N is one of 0,1,2, or 3 makes meshes consisting of
27 //              points, wireframes, triangles (=the default) or triangle strips
28 // -rep N    => where N is one of 0,1 or 2 draws the meshes as points, lines
29 //              or surfaces
30 
31 #include "vtkActor.h"
32 #include "vtkActorCollection.h"
33 #include "vtkCamera.h"
34 #include "vtkCellData.h"
35 #include "vtkDoubleArray.h"
36 #include "vtkExtractEdges.h"
37 #include "vtkImageData.h"
38 #include "vtkInformation.h"
39 #include "vtkLight.h"
40 #include "vtkLightCollection.h"
41 #include "vtkOSPRayActorNode.h"
42 #include "vtkOSPRayPass.h"
43 #include "vtkOSPRayRendererNode.h"
44 #include "vtkOpenGLRenderer.h"
45 #include "vtkPiecewiseFunction.h"
46 #include "vtkPointData.h"
47 #include "vtkPolyData.h"
48 #include "vtkPolyDataMapper.h"
49 #include "vtkPolyDataNormals.h"
50 #include "vtkProperty.h"
51 #include "vtkRenderWindow.h"
52 #include "vtkRenderWindowInteractor.h"
53 #include "vtkRenderer.h"
54 #include "vtkSmartPointer.h"
55 #include "vtkSphereSource.h"
56 #include "vtkStripper.h"
57 #include "vtkTexture.h"
58 #include "vtkTextureMapToSphere.h"
59 #include "vtkTransformTextureCoords.h"
60 #include "vtkUnsignedCharArray.h"
61 #include "vtkVertexGlyphFilter.h"
62 
63 #include <string>
64 #include <vector>
65 
66 #include "vtkOSPRayTestInteractor.h"
67 
68 class renderable
69 {
70 public:
71   vtkSphereSource* s;
72   vtkPolyDataMapper* m;
73   vtkActor* a;
~renderable()74   ~renderable()
75   {
76     s->Delete();
77     m->Delete();
78     a->Delete();
79   }
80 };
81 
MakeSphereAt(double x,double y,double z,int res,int type,int rep,const char * name)82 renderable* MakeSphereAt(double x, double y, double z, int res, int type, int rep, const char* name)
83 {
84   vtkOSPRayTestInteractor::AddName(name);
85   renderable* ret = new renderable;
86   ret->s = vtkSphereSource::New();
87   ret->s->SetEndTheta(180); // half spheres better show variation and f and back
88   ret->s->SetStartPhi(30);
89   ret->s->SetEndPhi(150);
90   ret->s->SetPhiResolution(res);
91   ret->s->SetThetaResolution(res);
92   ret->s->SetCenter(x, y, z);
93   // make texture coordinate
94   vtkSmartPointer<vtkTextureMapToSphere> tc = vtkSmartPointer<vtkTextureMapToSphere>::New();
95   tc->SetCenter(x, y, z);
96   tc->PreventSeamOn();
97   tc->AutomaticSphereGenerationOff();
98   tc->SetInputConnection(ret->s->GetOutputPort());
99   vtkSmartPointer<vtkTransformTextureCoords> tt = vtkSmartPointer<vtkTransformTextureCoords>::New();
100   tt->SetInputConnection(tc->GetOutputPort());
101   // tt->SetScale(1,0.5,1);
102   // make normals
103   vtkSmartPointer<vtkPolyDataNormals> nl = vtkSmartPointer<vtkPolyDataNormals>::New();
104   nl->SetInputConnection(tt->GetOutputPort());
105   nl->Update();
106   // make more attribute arrays
107   vtkPolyData* pd = nl->GetOutput();
108   // point aligned
109   vtkSmartPointer<vtkDoubleArray> da = vtkSmartPointer<vtkDoubleArray>::New();
110   da->SetName("testarray1");
111   da->SetNumberOfComponents(1);
112   pd->GetPointData()->AddArray(da);
113   int np = pd->GetNumberOfPoints();
114   int nc = pd->GetNumberOfCells();
115   for (int i = 0; i < np; i++)
116   {
117     da->InsertNextValue((double)i / (double)np);
118   }
119   da = vtkSmartPointer<vtkDoubleArray>::New();
120   da->SetName("testarray2");
121   da->SetNumberOfComponents(3);
122   pd->GetPointData()->AddArray(da);
123   for (int i = 0; i < np; i++)
124   {
125     double vals[3] = { (double)i / (double)np, (double)(i * 4) / (double)np - 2.0, 42.0 };
126     da->InsertNextTuple3(vals[0], vals[1], vals[2]);
127   }
128 
129   vtkSmartPointer<vtkUnsignedCharArray> pac = vtkSmartPointer<vtkUnsignedCharArray>::New();
130   pac->SetName("testarrayc1");
131   pac->SetNumberOfComponents(3);
132   pd->GetPointData()->AddArray(pac);
133   for (int i = 0; i < np; i++)
134   {
135     unsigned char vals[3] = { static_cast<unsigned char>(255 * ((double)i / (double)np)),
136       static_cast<unsigned char>(255 * ((double)(i * 4) / (double)np - 2.0)), 42 };
137     pac->InsertNextTuple3(vals[0], vals[1], vals[2]);
138   }
139 
140   vtkSmartPointer<vtkUnsignedCharArray> ca = vtkSmartPointer<vtkUnsignedCharArray>::New();
141   ca->SetName("testarray3");
142   ca->SetNumberOfComponents(3);
143   pd->GetPointData()->AddArray(ca);
144   for (int i = 0; i < np; i++)
145   {
146     unsigned char vals[3] = { static_cast<unsigned char>((double)i / (double)np * 255),
147       static_cast<unsigned char>((double)(1 - i) / (double)np), 42 };
148     ca->InsertNextTuple3(vals[0], vals[1], vals[2]);
149   }
150   // cell aligned
151   da = vtkSmartPointer<vtkDoubleArray>::New();
152   da->SetName("testarray4");
153   da->SetNumberOfComponents(1);
154   pd->GetCellData()->AddArray(da);
155   for (int i = 0; i < pd->GetNumberOfCells(); i++)
156   {
157     da->InsertNextValue((double)i / (double)pd->GetNumberOfCells());
158   }
159   da = vtkSmartPointer<vtkDoubleArray>::New();
160   da->SetName("testarray5");
161   da->SetNumberOfComponents(3);
162   pd->GetCellData()->AddArray(da);
163   for (int i = 0; i < nc; i++)
164   {
165     double vals[3] = { (double)i / (double)nc, (double)(i * 2) / (double)nc, 42.0 };
166     da->InsertNextTuple3(vals[0], vals[1], vals[2]);
167   }
168   ca = vtkSmartPointer<vtkUnsignedCharArray>::New();
169   ca->SetName("testarray6");
170   ca->SetNumberOfComponents(3);
171   pd->GetCellData()->AddArray(ca);
172   for (int i = 0; i < nc; i++)
173   {
174     unsigned char vals[3] = { static_cast<unsigned char>((double)i / (double)np * 255),
175       static_cast<unsigned char>((double)(1 - i) / (double)np), 42 };
176     ca->InsertNextTuple3(vals[0], vals[1], vals[2]);
177   }
178   ret->m = vtkPolyDataMapper::New();
179   ret->m->SetInputData(pd);
180 
181   switch (type)
182   {
183     case 0: // points
184     {
185       vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
186       filter->SetInputData(pd);
187       filter->Update();
188       ret->m->SetInputData(filter->GetOutput());
189       break;
190     }
191     case 1: // lines
192     {
193       vtkSmartPointer<vtkExtractEdges> filter = vtkSmartPointer<vtkExtractEdges>::New();
194       filter->SetInputData(pd);
195       filter->Update();
196       ret->m->SetInputData(filter->GetOutput());
197       break;
198     }
199     case 2: // polys
200       break;
201     case 3: // strips
202     {
203       vtkSmartPointer<vtkStripper> filter = vtkSmartPointer<vtkStripper>::New();
204       filter->SetInputData(pd);
205       filter->Update();
206       ret->m->SetInputData(filter->GetOutput());
207       break;
208     }
209   }
210   ret->a = vtkActor::New();
211   ret->a->SetMapper(ret->m);
212   ret->a->GetProperty()->SetPointSize(20);
213   ret->a->GetProperty()->SetLineWidth(10);
214   if (rep != -1)
215   {
216     ret->a->GetProperty()->SetRepresentation(rep);
217   }
218   return ret;
219 }
220 
TestOSPRayRenderMesh(int argc,char * argv[])221 int TestOSPRayRenderMesh(int argc, char* argv[])
222 {
223   bool useGL = false;
224   int type = 2;
225   int rep = -1;
226   for (int i = 0; i < argc; i++)
227   {
228     if (!strcmp(argv[i], "-GL"))
229     {
230       useGL = true;
231     }
232     if (!strcmp(argv[i], "-type"))
233     {
234       type = atoi(argv[i + 1]);
235     }
236     if (!strcmp(argv[i], "-rep"))
237     {
238       rep = atoi(argv[i + 1]);
239     }
240   }
241 
242   vtkSmartPointer<vtkRenderWindowInteractor> iren =
243     vtkSmartPointer<vtkRenderWindowInteractor>::New();
244   vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
245   iren->SetRenderWindow(renWin);
246   vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
247   renWin->AddRenderer(renderer);
248   renderer->AutomaticLightCreationOn();
249   renderer->SetBackground(0.75, 0.75, 0.75);
250   renderer->SetEnvironmentalBG(0.75, 0.75, 0.75);
251   renWin->SetSize(600, 550);
252   vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
253   camera->SetPosition(2.5, 11, -3);
254   camera->SetFocalPoint(2.5, 0, -3);
255   camera->SetViewUp(0, 0, 1);
256   renderer->SetActiveCamera(camera);
257   renWin->Render();
258 
259   vtkSmartPointer<vtkOSPRayPass> ospray = vtkSmartPointer<vtkOSPRayPass>::New();
260   if (!useGL)
261   {
262     renderer->SetPass(ospray);
263 
264     for (int i = 0; i < argc; ++i)
265     {
266       if (!strcmp(argv[i], "--OSPRayPT"))
267       {
268         vtkOSPRayRendererNode::SetRendererType("OSPRay pathtracer", renderer);
269         break;
270       }
271       if (!strcmp(argv[i], "--OptiX"))
272       {
273         vtkOSPRayRendererNode::SetRendererType("optix pathtracer", renderer);
274         break;
275       }
276     }
277   }
278   // Now, vary most of the many parameters that rendering can vary by.
279   renderable* ren;
280 
281   // representations points, wireframe, surface
282   ren = MakeSphereAt(5, 0, -5, 10, type, rep, "points");
283   ren->a->GetProperty()->SetRepresentationToPoints();
284   renderer->AddActor(ren->a);
285   delete (ren);
286 
287   ren = MakeSphereAt(5, 0, -4, 10, type, rep, "wireframe");
288   ren->a->GetProperty()->SetRepresentationToWireframe();
289   renderer->AddActor(ren->a);
290   delete (ren);
291 
292   ren = MakeSphereAt(5, 0, -3, 10, type, rep, "surface");
293   ren->a->GetProperty()->SetRepresentationToSurface();
294   renderer->AddActor(ren->a);
295   delete (ren);
296 
297   // actor color
298   ren = MakeSphereAt(4, 0, -5, 10, type, rep, "actor_color");
299   ren->a->GetProperty()->SetColor(0, 1, 0);
300   renderer->AddActor(ren->a);
301   delete (ren);
302 
303   // ambient, diffuse, and specular components
304   ren = MakeSphereAt(4, 0, -4, 7, type, rep, "amb/diff/spec");
305   ren->a->GetProperty()->SetAmbient(0.5);
306   ren->a->GetProperty()->SetAmbientColor(0.1, 0.1, 0.3);
307   ren->a->GetProperty()->SetDiffuse(0.4);
308   ren->a->GetProperty()->SetDiffuseColor(0.5, 0.1, 0.1);
309   ren->a->GetProperty()->SetSpecular(0.2);
310   ren->a->GetProperty()->SetSpecularColor(1, 1, 1);
311   ren->a->GetProperty()->SetSpecularPower(100);
312   ren->a->GetProperty()->SetInterpolationToPhong();
313   renderer->AddActor(ren->a);
314   delete (ren);
315 
316   // opacity
317   ren = MakeSphereAt(4, 0, -3, 10, type, rep, "opacity");
318   ren->a->GetProperty()->SetOpacity(0.2);
319   renderer->AddActor(ren->a);
320   delete (ren);
321 
322   // color map cell values
323   ren = MakeSphereAt(3, 0, -5, 10, type, rep, "cell_value");
324   ren->m->SetScalarModeToUseCellFieldData();
325   ren->m->SelectColorArray(0);
326   renderer->AddActor(ren->a);
327   delete (ren);
328 
329   // default color component
330   ren = MakeSphereAt(3, 0, -4, 10, type, rep, "cell_default_comp");
331   ren->m->SetScalarModeToUseCellFieldData();
332   ren->m->SelectColorArray(1);
333   renderer->AddActor(ren->a);
334   delete (ren);
335 
336   // choose color component
337   ren = MakeSphereAt(3, 0, -3, 10, type, rep, "cell_comp_1");
338   ren->m->SetScalarModeToUseCellFieldData();
339   ren->m->SelectColorArray(1);
340   ren->m->ColorByArrayComponent(1, 1); // todo, use lut since this is deprecated
341   renderer->AddActor(ren->a);
342   delete (ren);
343 
344   // RGB direct
345   ren = MakeSphereAt(3, 0, -2, 10, type, rep, "cell_rgb");
346   ren->m->SetScalarModeToUseCellFieldData();
347   ren->m->SelectColorArray(2);
348   renderer->AddActor(ren->a);
349   delete (ren);
350 
351   // RGB through LUT
352   ren = MakeSphereAt(3, 0, -1, 10, type, rep, "cell_rgb_through_LUT");
353   ren->m->SetScalarModeToUseCellFieldData();
354   ren->m->SelectColorArray(2);
355   ren->m->SetColorModeToMapScalars();
356   renderer->AddActor(ren->a);
357   delete (ren);
358 
359   // color map point values
360   ren = MakeSphereAt(2, 0, -5, 6, type, rep, "point_value");
361   ren->m->SetScalarModeToUsePointFieldData();
362   ren->m->SelectColorArray("testarray1");
363   renderer->AddActor(ren->a);
364   delete (ren);
365 
366   // interpolate scalars before mapping
367   ren = MakeSphereAt(2, 0, -4, 6, type, rep, "point_interp");
368   ren->m->SetScalarModeToUsePointFieldData();
369   ren->m->SelectColorArray("testarray1");
370   ren->m->InterpolateScalarsBeforeMappingOn();
371   renderer->AddActor(ren->a);
372   delete (ren);
373 
374   // RGB direct
375   ren = MakeSphereAt(2, 0, -3, 10, type, rep, "point_rgb");
376   ren->m->SetScalarModeToUsePointFieldData();
377   ren->m->SetColorModeToDefault();
378   ren->m->SelectColorArray("testarrayc1");
379   renderer->AddActor(ren->a);
380   delete (ren);
381 
382   // RGB mapped
383   ren = MakeSphereAt(2, 0, -2, 10, type, rep, "point_rgb_through_LUT");
384   ren->m->SetScalarModeToUsePointFieldData();
385   ren->m->SetColorModeToMapScalars();
386   ren->m->SelectColorArray("testarrayc1");
387   renderer->AddActor(ren->a);
388   delete (ren);
389 
390   // unlit, flat, and gouraud lighting
391   ren = MakeSphereAt(1, 0, -5, 7, type, rep, "not_lit");
392   ren->a->GetProperty()->LightingOff();
393   renderer->AddActor(ren->a);
394   delete (ren);
395 
396   ren = MakeSphereAt(1, 0, -4, 7, type, rep, "flat");
397   ren->a->GetProperty()->SetInterpolationToFlat();
398   renderer->AddActor(ren->a);
399   delete (ren);
400 
401   ren = MakeSphereAt(1, 0, -3, 7, type, rep, "gouraud");
402   ren->a->GetProperty()->SetInterpolationToGouraud();
403   renderer->AddActor(ren->a);
404   delete (ren);
405 
406   // texture
407   int maxi = 100;
408   int maxj = 100;
409   vtkSmartPointer<vtkImageData> texin = vtkSmartPointer<vtkImageData>::New();
410   texin->SetExtent(0, maxi, 0, maxj, 0, 0);
411   texin->AllocateScalars(VTK_UNSIGNED_CHAR, 3);
412   vtkUnsignedCharArray* aa =
413     vtkArrayDownCast<vtkUnsignedCharArray>(texin->GetPointData()->GetScalars());
414   int idx = 0;
415   for (int i = 0; i <= maxi; i++)
416   {
417     for (int j = 0; j <= maxj; j++)
418     {
419       bool ival = (i / 10) % 2 == 1;
420       bool jval = (j / 10) % 2 == 1;
421       unsigned char val = (ival ^ jval) ? 255 : 0;
422       aa->SetTuple3(idx, val, val, val);
423       if (j <= 3 || j >= maxj - 3)
424       {
425         aa->SetTuple3(idx, 255, 255, 0);
426       }
427       if (i <= 20 || i >= maxi - 20)
428       {
429         aa->SetTuple3(idx, 255, 0, 0);
430       }
431       idx = idx + 1;
432     }
433   }
434   ren = MakeSphereAt(0, 0, -5, 20, type, rep, "texture");
435   renderer->AddActor(ren->a);
436   vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New();
437   texture->SetInputData(texin);
438   ren->a->SetTexture(texture);
439   delete (ren);
440 
441   // imagespace positional transformations
442   ren = MakeSphereAt(0, 0, -4, 10, type, rep, "transform");
443   ren->a->SetScale(1.2, 1.0, 0.87);
444   renderer->AddActor(ren->a);
445   delete (ren);
446 
447   // TODO: lut manipulation and range effects
448   // TODO: NaN colors
449   // TODO: mapper clipping planes
450   // TODO: hierarchical actors
451 
452   renWin->Render();
453 
454   vtkLight* light = vtkLight::SafeDownCast(renderer->GetLights()->GetItemAsObject(0));
455   double lColor[3];
456   light->GetDiffuseColor(lColor);
457   light->SetPosition(2, 15, -2);
458   light->SetFocalPoint(2, 0, -2);
459   light->PositionalOff();
460 
461   vtkSmartPointer<vtkOSPRayTestInteractor> style = vtkSmartPointer<vtkOSPRayTestInteractor>::New();
462   style->SetPipelineControlPoints(renderer, ospray, nullptr);
463   iren->SetInteractorStyle(style);
464   style->SetCurrentRenderer(renderer);
465 
466   iren->Start();
467 
468   return 0;
469 }
470