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 "vtkOpenGLRenderer.h"
42 #include "vtkOSPRayActorNode.h"
43 #include "vtkOSPRayPass.h"
44 #include "vtkPiecewiseFunction.h"
45 #include "vtkPointData.h"
46 #include "vtkPolyData.h"
47 #include "vtkPolyDataMapper.h"
48 #include "vtkPolyDataNormals.h"
49 #include "vtkProperty.h"
50 #include "vtkRenderer.h"
51 #include "vtkRenderWindow.h"
52 #include "vtkRenderWindowInteractor.h"
53 #include "vtkSmartPointer.h"
54 #include "vtkSphereSource.h"
55 #include "vtkStripper.h"
56 #include "vtkTexture.h"
57 #include "vtkTextureMapToSphere.h"
58 #include "vtkTransformTextureCoords.h"
59 #include "vtkUnsignedCharArray.h"
60 #include "vtkVertexGlyphFilter.h"
61 
62 #include <vector>
63 #include <string>
64 
65 #include "vtkOSPRayTestInteractor.h"
66 
67 class renderable
68 {
69 public:
70   vtkSphereSource *s;
71   vtkPolyDataMapper *m;
72   vtkActor *a;
~renderable()73   ~renderable()
74   {
75     s->Delete();
76     m->Delete();
77     a->Delete();
78   }
79 };
80 
MakeSphereAt(double x,double y,double z,int res,int type,int rep,const char * name)81 renderable *MakeSphereAt(double x, double y, double z, int res,
82                          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 =
95     vtkSmartPointer<vtkTextureMapToSphere>::New();
96   tc->SetCenter(x,y,z);
97   tc->PreventSeamOn();
98   tc->AutomaticSphereGenerationOff();
99   tc->SetInputConnection(ret->s->GetOutputPort());
100   vtkSmartPointer<vtkTransformTextureCoords> tt =
101     vtkSmartPointer<vtkTransformTextureCoords>::New();
102   tt->SetInputConnection(tc->GetOutputPort());
103   //tt->SetScale(1,0.5,1);
104   //make normals
105   vtkSmartPointer<vtkPolyDataNormals> nl =
106     vtkSmartPointer<vtkPolyDataNormals>::New();
107   nl->SetInputConnection(tt->GetOutputPort());
108   nl->Update();
109   //make more attribute arrays
110   vtkPolyData *pd = nl->GetOutput();
111   //point aligned
112   vtkSmartPointer<vtkDoubleArray> da = vtkSmartPointer<vtkDoubleArray>::New();
113   da->SetName("testarray1");
114   da->SetNumberOfComponents(1);
115   pd->GetPointData()->AddArray(da);
116   int np = pd->GetNumberOfPoints();
117   int nc = pd->GetNumberOfCells();
118   for (int i = 0; i < np; i++)
119   {
120     da->InsertNextValue((double)i/(double)np);
121   }
122   da = vtkSmartPointer<vtkDoubleArray>::New();
123   da->SetName("testarray2");
124   da->SetNumberOfComponents(3);
125   pd->GetPointData()->AddArray(da);
126   for (int i = 0; i < np; i++)
127   {
128     double vals[3] = {(double)i/(double)np, (double)(i*4)/(double)np-2.0, 42.0};
129     da->InsertNextTuple3(vals[0],vals[1],vals[2]);
130   }
131 
132   vtkSmartPointer<vtkUnsignedCharArray> pac =
133     vtkSmartPointer<vtkUnsignedCharArray>::New();
134   pac->SetName("testarrayc1");
135   pac->SetNumberOfComponents(3);
136   pd->GetPointData()->AddArray(pac);
137   for (int i = 0; i < np; i++)
138   {
139     unsigned char vals[3] =
140       {static_cast<unsigned char>(255*((double)i/(double)np)),
141        static_cast<unsigned char>(255*((double)(i*4)/(double)np-2.0)),
142        42};
143     pac->InsertNextTuple3(vals[0],vals[1],vals[2]);
144   }
145 
146   vtkSmartPointer<vtkUnsignedCharArray> ca =
147     vtkSmartPointer<vtkUnsignedCharArray>::New();
148   ca->SetName("testarray3");
149   ca->SetNumberOfComponents(3);
150   pd->GetPointData()->AddArray(ca);
151   for (int i = 0; i < np; i++)
152   {
153     unsigned char vals[3] =
154       {static_cast<unsigned char>((double)i/(double)np*255),
155        static_cast<unsigned char>((double)(1-i)/(double)np),
156        42};
157     ca->InsertNextTuple3(vals[0],vals[1],vals[2]);
158   }
159   //cell aligned
160   da = vtkSmartPointer<vtkDoubleArray>::New();
161   da->SetName("testarray4");
162   da->SetNumberOfComponents(1);
163   pd->GetCellData()->AddArray(da);
164   for (int i = 0; i < pd->GetNumberOfCells(); i++)
165   {
166     da->InsertNextValue((double)i/(double)pd->GetNumberOfCells());
167   }
168   da = vtkSmartPointer<vtkDoubleArray>::New();
169   da->SetName("testarray5");
170   da->SetNumberOfComponents(3);
171   pd->GetCellData()->AddArray(da);
172   for (int i = 0; i < nc; i++)
173   {
174     double vals[3] = {(double)i/(double)nc, (double)(i*2)/(double)nc, 42.0};
175     da->InsertNextTuple3(vals[0],vals[1],vals[2]);
176   }
177   ca = vtkSmartPointer<vtkUnsignedCharArray>::New();
178   ca->SetName("testarray6");
179   ca->SetNumberOfComponents(3);
180   pd->GetCellData()->AddArray(ca);
181   for (int i = 0; i < nc; i++)
182   {
183     unsigned char vals[3] =
184       {static_cast<unsigned char>((double)i/(double)np*255),
185        static_cast<unsigned char>((double)(1-i)/(double)np),
186        42};
187     ca->InsertNextTuple3(vals[0],vals[1],vals[2]);
188   }
189   ret->m = vtkPolyDataMapper::New();
190   ret->m->SetInputData(pd);
191 
192   switch (type)
193   {
194     case 0: //points
195     {
196       vtkSmartPointer<vtkVertexGlyphFilter> filter =
197         vtkSmartPointer<vtkVertexGlyphFilter>::New();
198       filter->SetInputData(pd);
199       filter->Update();
200       ret->m->SetInputData(filter->GetOutput());
201       break;
202     }
203     case 1: //lines
204     {
205       vtkSmartPointer<vtkExtractEdges> filter =
206         vtkSmartPointer<vtkExtractEdges>::New();
207       filter->SetInputData(pd);
208       filter->Update();
209       ret->m->SetInputData(filter->GetOutput());
210       break;
211     }
212     case 2: //polys
213       break;
214     case 3: //strips
215     {
216       vtkSmartPointer<vtkStripper> filter =
217         vtkSmartPointer<vtkStripper>::New();
218       filter->SetInputData(pd);
219       filter->Update();
220       ret->m->SetInputData(filter->GetOutput());
221       break;
222     }
223   }
224   ret->a=vtkActor::New();
225   ret->a->SetMapper(ret->m);
226   ret->a->GetProperty()->SetPointSize(20);
227   ret->a->GetProperty()->SetLineWidth(10);
228   if (rep != -1)
229   {
230     ret->a->GetProperty()->SetRepresentation(rep);
231   }
232   return ret;
233 }
234 
TestOSPRayRenderMesh(int argc,char * argv[])235 int TestOSPRayRenderMesh(int argc, char* argv[])
236 {
237   bool useGL = false;
238   int type = 2;
239   int rep = -1;
240   for (int i = 0; i < argc; i++)
241   {
242     if (!strcmp(argv[i], "-GL"))
243     {
244       useGL = true;
245     }
246     if (!strcmp(argv[i], "-type"))
247     {
248       type = atoi(argv[i+1]);
249     }
250     if (!strcmp(argv[i], "-rep"))
251     {
252       rep = atoi(argv[i+1]);
253     }
254   }
255 
256   vtkSmartPointer<vtkRenderWindowInteractor> iren =
257     vtkSmartPointer<vtkRenderWindowInteractor>::New();
258   vtkSmartPointer<vtkRenderWindow> renWin =
259     vtkSmartPointer<vtkRenderWindow>::New();
260   iren->SetRenderWindow(renWin);
261   vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
262   renWin->AddRenderer(renderer);
263   renderer->AutomaticLightCreationOn();
264   renderer->SetBackground(0.75,0.75,0.75);
265   renWin->SetSize(600,550);
266   vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
267   camera->SetPosition(2.5,11,-3);
268   camera->SetFocalPoint(2.5,0,-3);
269   camera->SetViewUp(0,0,1);
270   renderer->SetActiveCamera(camera);
271   renWin->Render();
272 
273   vtkSmartPointer<vtkOSPRayPass> ospray = vtkSmartPointer<vtkOSPRayPass>::New();
274   if (!useGL)
275   {
276     renderer->SetPass(ospray);
277   }
278   //Now, vary most of the many parameters that rendering can vary by.
279 
280   //representations points, wireframe, surface
281   renderable *ren = MakeSphereAt(5,0,-5, 10, type, rep, "points");
282   ren->a->GetProperty()->SetRepresentationToPoints();
283   renderer->AddActor(ren->a);
284   delete(ren);
285 
286   ren = MakeSphereAt(5,0,-4, 10, type, rep, "wireframe");
287   ren->a->GetProperty()->SetRepresentationToWireframe();
288   renderer->AddActor(ren->a);
289   delete(ren);
290 
291   ren = MakeSphereAt(5,0,-3, 10, type, rep, "surface");
292   ren->a->GetProperty()->SetRepresentationToSurface();
293   renderer->AddActor(ren->a);
294   delete(ren);
295 
296   //actor color
297   ren = MakeSphereAt(4,0,-5, 10, type, rep, "actor_color");
298   ren->a->GetProperty()->SetColor(0,1,0);
299   renderer->AddActor(ren->a);
300   delete(ren);
301 
302   //ambient, diffuse, and specular components
303   ren = MakeSphereAt(4,0,-4, 7, type, rep, "amb/diff/spec");
304   ren->a->GetProperty()->SetAmbient(0.5);
305   ren->a->GetProperty()->SetAmbientColor(0.1,0.1,0.3);
306   ren->a->GetProperty()->SetDiffuse(0.4);
307   ren->a->GetProperty()->SetDiffuseColor(0.5,0.1,0.1);
308   ren->a->GetProperty()->SetSpecular(0.2);
309   ren->a->GetProperty()->SetSpecularColor(1,1,1);
310   ren->a->GetProperty()->SetSpecularPower(100);
311   ren->a->GetProperty()->SetInterpolationToPhong();
312   renderer->AddActor(ren->a);
313   delete(ren);
314 
315   //opacity
316   ren = MakeSphereAt(4,0,-3, 10, type, rep, "opacity");
317   ren->a->GetProperty()->SetOpacity(0.2);
318   renderer->AddActor(ren->a);
319   delete(ren);
320 
321   //color map cell values
322   ren = MakeSphereAt(3,0,-5, 10, type, rep, "cell_value");
323   ren->m->SetScalarModeToUseCellFieldData();
324   ren->m->SelectColorArray(0);
325   renderer->AddActor(ren->a);
326   delete(ren);
327 
328   //default color component
329   ren = MakeSphereAt(3,0,-4, 10, type, rep, "cell_default_comp");
330   ren->m->SetScalarModeToUseCellFieldData();
331   ren->m->SelectColorArray(1);
332   renderer->AddActor(ren->a);
333   delete(ren);
334 
335   //choose color component
336   ren = MakeSphereAt(3,0,-3, 10, type, rep, "cell_comp_1");
337   ren->m->SetScalarModeToUseCellFieldData();
338   ren->m->SelectColorArray(1);
339   ren->m->ColorByArrayComponent(1,1); //todo, use lut since this is deprecated
340   renderer->AddActor(ren->a);
341   delete(ren);
342 
343   //RGB direct
344   ren = MakeSphereAt(3,0,-2, 10, type, rep, "cell_rgb");
345   ren->m->SetScalarModeToUseCellFieldData();
346   ren->m->SelectColorArray(2);
347   renderer->AddActor(ren->a);
348   delete(ren);
349 
350   //RGB through LUT
351   ren = MakeSphereAt(3,0,-1, 10, type, rep, "cell_rgb_through_LUT");
352   ren->m->SetScalarModeToUseCellFieldData();
353   ren->m->SelectColorArray(2);
354   ren->m->SetColorModeToMapScalars();
355   renderer->AddActor(ren->a);
356   delete(ren);
357 
358   //color map point values
359   ren = MakeSphereAt(2,0,-5,6, type, rep, "point_value");
360   ren->m->SetScalarModeToUsePointFieldData();
361   ren->m->SelectColorArray("testarray1");
362   renderer->AddActor(ren->a);
363   delete(ren);
364 
365   //interpolate scalars before mapping
366   ren = MakeSphereAt(2,0,-4,6, type, rep, "point_interp");
367   ren->m->SetScalarModeToUsePointFieldData();
368   ren->m->SelectColorArray("testarray1");
369   ren->m->InterpolateScalarsBeforeMappingOn();
370   renderer->AddActor(ren->a);
371   delete(ren);
372 
373   //RGB direct
374   ren = MakeSphereAt(2,0,-3, 10, type, rep, "point_rgb");
375   ren->m->SetScalarModeToUsePointFieldData();
376   ren->m->SetColorModeToDefault();
377   ren->m->SelectColorArray("testarrayc1");
378   renderer->AddActor(ren->a);
379   delete(ren);
380 
381   //RGB mapped
382   ren = MakeSphereAt(2,0,-2, 10, type, rep, "point_rgb_through_LUT");
383   ren->m->SetScalarModeToUsePointFieldData();
384   ren->m->SetColorModeToMapScalars();
385   ren->m->SelectColorArray("testarrayc1");
386   renderer->AddActor(ren->a);
387   delete(ren);
388 
389   //unlit, flat, and gouraud lighting
390   ren = MakeSphereAt(1,0,-5,7, type, rep, "not_lit");
391   ren->a->GetProperty()->LightingOff();
392   renderer->AddActor(ren->a);
393   delete(ren);
394 
395   ren = MakeSphereAt(1,0,-4,7, type, rep, "flat");
396   ren->a->GetProperty()->SetInterpolationToFlat();
397   renderer->AddActor(ren->a);
398   delete(ren);
399 
400   ren = MakeSphereAt(1,0,-3,7, type, rep, "gouraud");
401   ren->a->GetProperty()->SetInterpolationToGouraud();
402   renderer->AddActor(ren->a);
403   delete(ren);
404 
405   //texture
406   int maxi = 100;
407   int maxj = 100;
408   vtkSmartPointer<vtkImageData> texin = vtkSmartPointer<vtkImageData>::New();
409   texin->SetExtent(0,maxi,0,maxj,0,0);
410   texin->AllocateScalars(VTK_UNSIGNED_CHAR, 3);
411   vtkUnsignedCharArray *aa =
412     vtkArrayDownCast<vtkUnsignedCharArray>(texin->GetPointData()->GetScalars());
413   int idx = 0;
414   for (int i = 0; i<=maxi; i++)
415   {
416     for (int j = 0; j<=maxj; j++)
417     {
418       bool ival = (i/10)%2==1;
419       bool jval = (j/10)%2==1;
420       unsigned char val = (ival^jval) ? 255 : 0;
421       aa->SetTuple3(idx, val, val, val);
422       if (j <= 3 || j >= maxj-3)
423       {
424         aa->SetTuple3(idx, 255, 255, 0);
425       }
426       if (i <= 20 || i >= maxi-20)
427       {
428         aa->SetTuple3(idx, 255, 0, 0);
429       }
430       idx = idx + 1;
431     }
432   }
433   ren = MakeSphereAt(0,0,-5,20,type, rep, "texture");
434   renderer->AddActor(ren->a);
435   vtkSmartPointer<vtkTexture> texture =
436     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 =
455     vtkLight::SafeDownCast(renderer->GetLights()->GetItemAsObject(0));
456   double lColor[3];
457   light->GetDiffuseColor(lColor);
458   light->SetPosition(2,15,-2);
459   light->SetFocalPoint(2,0,-2);
460   light->PositionalOff();
461 
462   vtkSmartPointer<vtkOSPRayTestInteractor> style =
463     vtkSmartPointer<vtkOSPRayTestInteractor>::New();
464   style->
465     SetPipelineControlPoints(renderer, ospray, nullptr);
466   iren->SetInteractorStyle(style);
467   style->SetCurrentRenderer(renderer);
468 
469   iren->Start();
470 
471   return 0;
472 }
473