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