vtkOSPRayMoleculeMapperNode.cxx 16 KB
Newer Older
David E. DeMarle's avatar
David E. DeMarle committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*=========================================================================

   Program:   Visualization Toolkit
   Module:    vtkOSPRayMoleculeMapperNode.cxx

   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
   All rights reserved.
   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

      This software is distributed WITHOUT ANY WARRANTY; without even
      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
      PURPOSE.  See the above copyright notice for more information.

 =========================================================================*/
#include "vtkOSPRayMoleculeMapperNode.h"

17
#include "vtkDataSetAttributes.h"
David E. DeMarle's avatar
David E. DeMarle committed
18
#include "vtkInformation.h"
David E. DeMarle's avatar
David E. DeMarle committed
19
#include "vtkLookupTable.h"
David E. DeMarle's avatar
David E. DeMarle committed
20
21
#include "vtkMolecule.h"
#include "vtkMoleculeMapper.h"
David E. DeMarle's avatar
David E. DeMarle committed
22
#include "vtkOSPRayActorNode.h"
23
#include "vtkOSPRayMaterialHelpers.h"
David E. DeMarle's avatar
David E. DeMarle committed
24
25
#include "vtkOSPRayRendererNode.h"
#include "vtkObjectFactory.h"
David E. DeMarle's avatar
David E. DeMarle committed
26
#include "vtkPeriodicTable.h"
David E. DeMarle's avatar
David E. DeMarle committed
27
#include "vtkPoints.h"
David E. DeMarle's avatar
David E. DeMarle committed
28
#include "vtkProperty.h"
David E. DeMarle's avatar
David E. DeMarle committed
29
#include "vtkRenderer.h"
David E. DeMarle's avatar
David E. DeMarle committed
30
#include "vtkUnsignedShortArray.h"
David E. DeMarle's avatar
David E. DeMarle committed
31
32
#include "vtkVector.h"
#include "vtkVectorOperators.h"
David E. DeMarle's avatar
David E. DeMarle committed
33
34

#include <algorithm>
David E. DeMarle's avatar
David E. DeMarle committed
35
#include <string.h>
David E. DeMarle's avatar
David E. DeMarle committed
36
37
38
39
40
#include <vector>

//============================================================================
vtkStandardNewMacro(vtkOSPRayMoleculeMapperNode);

41
//------------------------------------------------------------------------------
42
vtkOSPRayMoleculeMapperNode::vtkOSPRayMoleculeMapperNode() = default;
David E. DeMarle's avatar
David E. DeMarle committed
43

44
//------------------------------------------------------------------------------
45
vtkOSPRayMoleculeMapperNode::~vtkOSPRayMoleculeMapperNode() {}
David E. DeMarle's avatar
David E. DeMarle committed
46

47
//------------------------------------------------------------------------------
David E. DeMarle's avatar
David E. DeMarle committed
48
49
50
51
52
void vtkOSPRayMoleculeMapperNode::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}

53
//------------------------------------------------------------------------------
David E. DeMarle's avatar
David E. DeMarle committed
54
55
void vtkOSPRayMoleculeMapperNode::Render(bool prepass)
{
David E. DeMarle's avatar
David E. DeMarle committed
56
  if (!prepass)
David E. DeMarle's avatar
David E. DeMarle committed
57
  {
David E. DeMarle's avatar
David E. DeMarle committed
58
    return;
David E. DeMarle's avatar
David E. DeMarle committed
59
  }
David E. DeMarle's avatar
David E. DeMarle committed
60
61
62
  vtkOSPRayActorNode* aNode = vtkOSPRayActorNode::SafeDownCast(this->Parent);
  vtkActor* act = vtkActor::SafeDownCast(aNode->GetRenderable());
  if (act->GetVisibility() == false)
David E. DeMarle's avatar
David E. DeMarle committed
63
  {
David E. DeMarle's avatar
David E. DeMarle committed
64
65
66
67
68
69
70
71
72
73
    return;
  }

  vtkOSPRayRendererNode* orn =
    static_cast<vtkOSPRayRendererNode*>(this->GetFirstAncestorOfType("vtkOSPRayRendererNode"));
  RTW::Backend* backend = orn->GetBackend();
  if (backend == nullptr)
  {
    return;
  }
David E. DeMarle's avatar
David E. DeMarle committed
74

75
  vtkProperty* property = act->GetProperty();
David E. DeMarle's avatar
David E. DeMarle committed
76
77
  vtkMoleculeMapper* mapper = vtkMoleculeMapper::SafeDownCast(this->GetRenderable());
  vtkMolecule* molecule = mapper->GetInput();
78
  vtkScalarsToColors* lut = mapper->GetLookupTable();
79
80
81
82

  if (act->GetMTime() > this->BuildTime || property->GetMTime() > this->BuildTime ||
    mapper->GetMTime() > this->BuildTime || lut->GetMTime() > this->BuildTime ||
    molecule->GetMTime() > this->BuildTime)
David E. DeMarle's avatar
David E. DeMarle committed
83
  {
84
    // free up whatever we did last time
85
    for (auto instance : this->Instances)
86
    {
87
      ospRelease(&(*instance));
88
    }
89
    this->Instances.clear();
David E. DeMarle's avatar
David E. DeMarle committed
90

91
92
93
94
95
96
97
98
99
100
101
102
103
    // some state that affect everything we draw
    double opacity = property->GetOpacity();
    float specPower = static_cast<float>(property->GetSpecularPower());
    float specAdjust = 2.0f / (2.0f + specPower);
    float specularf[3];
    specularf[0] =
      static_cast<float>(property->GetSpecularColor()[0] * property->GetSpecular() * specAdjust);
    specularf[1] =
      static_cast<float>(property->GetSpecularColor()[1] * property->GetSpecular() * specAdjust);
    specularf[2] =
      static_cast<float>(property->GetSpecularColor()[2] * property->GetSpecular() * specAdjust);
    // setup color/appearance of each element that we may draw
    std::vector<OSPMaterial> _elementMaterials;
104
105
    for (int i = 0; i < mapper->GetPeriodicTable()->GetNumberOfElements(); i++)
    {
106
107
108
109
      // todo: I'm no physicist, but I don't think the periodic table changes often. We should
      // rethink when we construct this. todo: unify with
      // vtkOSPRayPolyDataMapperNode::CellMaterials() and lookup custom materials from discrete LUT.
      // That way we can have glowing Thorium with matte Calcium and reflective Aluminum.
110
      const unsigned char* ucolor = lut->MapValue(static_cast<unsigned short>(i));
111
      auto oMaterial = vtkOSPRayMaterialHelpers::NewMaterial(orn, orn->GetORenderer(), "obj");
112
113
      float diffusef[] = { static_cast<float>(ucolor[0]) / (255.0f),
        static_cast<float>(ucolor[1]) / (255.0f), static_cast<float>(ucolor[2]) / (255.0f) };
114
115
116
117
      ospSetVec3f(oMaterial, "kd", diffusef[0], diffusef[1], diffusef[2]);
      ospSetVec3f(oMaterial, "ks", specularf[0], specularf[1], specularf[2]);
      ospSetFloat(oMaterial, "ns", specPower);
      ospSetFloat(oMaterial, "d", opacity);
118
      ospCommit(oMaterial);
119
      _elementMaterials.push_back(oMaterial);
120
    }
121
122
    auto elementMaterials =
      ospNewCopyData1D(&_elementMaterials[0], OSP_OBJECT, _elementMaterials.size());
123
    ospCommit(elementMaterials);
124

125
    // now translate the three things we may actually draw into OSPRay calls
David E. DeMarle's avatar
David E. DeMarle committed
126
127
    if (mapper->GetRenderAtoms())
    {
128
129
130
      OSPGeometry atoms = ospNewGeometry("sphere");
      OSPGeometricModel atomsModel = ospNewGeometricModel(atoms);
      ospRelease(atoms);
131

David E. DeMarle's avatar
David E. DeMarle committed
132
      const vtkIdType numAtoms = molecule->GetNumberOfAtoms();
David E. DeMarle's avatar
David E. DeMarle committed
133
      vtkPoints* allPoints = molecule->GetAtomicPositionArray();
134
135
136
      std::vector<osp::vec3f> vertices;
      std::vector<float> radii;
      std::vector<OSPMaterial> materials;
David E. DeMarle's avatar
David E. DeMarle committed
137
      vtkUnsignedShortArray* atomicNumbers = molecule->GetAtomicNumberArray();
David E. DeMarle's avatar
David E. DeMarle committed
138

David E. DeMarle's avatar
David E. DeMarle committed
139
      for (vtkIdType i = 0; i < numAtoms; i++)
David E. DeMarle's avatar
David E. DeMarle committed
140
      {
141
142
143
        vertices.emplace_back(osp::vec3f{ static_cast<float>(allPoints->GetPoint(i)[0]),
          static_cast<float>(allPoints->GetPoint(i)[1]),
          static_cast<float>(allPoints->GetPoint(i)[2]) });
David E. DeMarle's avatar
David E. DeMarle committed
144

145
        materials.emplace_back(_elementMaterials[atomicNumbers->GetValue(i)]);
David E. DeMarle's avatar
David E. DeMarle committed
146
      }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

      switch (mapper->GetAtomicRadiusType())
      {
        default:
          vtkWarningMacro(<< "Unknown radius type: " << mapper->GetAtomicRadiusType()
                          << ". Falling back to 'VDWRadius'.");
          VTK_FALLTHROUGH;
        case vtkMoleculeMapper::VDWRadius:
          for (vtkIdType i = 0; i < numAtoms; i++)
          {
            radii.emplace_back(mapper->GetAtomicRadiusScaleFactor() *
              mapper->GetPeriodicTable()->GetVDWRadius(atomicNumbers->GetValue(i)));
          }
          break;
        case vtkMoleculeMapper::CovalentRadius:
          for (vtkIdType i = 0; i < numAtoms; i++)
          {
            radii.emplace_back(mapper->GetAtomicRadiusScaleFactor() *
              mapper->GetPeriodicTable()->GetCovalentRadius(atomicNumbers->GetValue(i)));
          }
          break;
        case vtkMoleculeMapper::UnitRadius:
          for (vtkIdType i = 0; i < numAtoms; i++)
          {
            radii.emplace_back(mapper->GetAtomicRadiusScaleFactor());
          }
          break;
        case vtkMoleculeMapper::CustomArrayRadius:
          vtkDataArray* allRadii =
            molecule->GetVertexData()->GetArray(mapper->GetAtomicRadiusArrayName());
          if (!allRadii)
          {
            vtkWarningMacro("AtomicRadiusType set to CustomArrayRadius, but no array named "
              << mapper->GetAtomicRadiusArrayName() << " found in input VertexData.");
            for (vtkIdType i = 0; i < numAtoms; i++)
            {
              radii.emplace_back(mapper->GetAtomicRadiusScaleFactor());
            }
            break;
          }
          for (vtkIdType i = 0; i < numAtoms; i++)
          {
            radii.emplace_back(allRadii->GetTuple1(i));
          }
          break;
      }
193
194
195
196
197
198
199
200
201
202
203
204
      OSPData vertData = ospNewCopyData1D(vertices.data(), OSP_VEC3F, numAtoms);
      ospCommit(vertData);
      OSPData radiiData = ospNewCopyData1D(radii.data(), OSP_FLOAT, numAtoms);
      ospCommit(radiiData);
      OSPData materialsData = ospNewCopyData1D(materials.data(), OSP_MATERIAL, numAtoms);
      ospCommit(materialsData);

      ospSetObject(atoms, "sphere.position", vertData);
      ospSetObject(atoms, "sphere.radius", radiiData);
      ospSetObject(atomsModel, "material", materialsData);

      this->GeometricModels.emplace_back(atomsModel);
205
      ospCommit(atoms);
206
207
208
209
      ospCommit(atomsModel);
      ospRelease(vertData);
      ospRelease(radiiData);
      ospRelease(materialsData);
David E. DeMarle's avatar
David E. DeMarle committed
210
    }
David E. DeMarle's avatar
David E. DeMarle committed
211
212
213

    if (mapper->GetRenderBonds())
    {
214
215
216
      OSPGeometry bonds = ospNewGeometry("curve");
      OSPGeometricModel bondsModel = ospNewGeometricModel(bonds);
      ospRelease(bonds);
David E. DeMarle's avatar
David E. DeMarle committed
217
218
219
220
221
222
223
224

      vtkVector3f pos1, pos2;
      vtkIdType atomIds[2];
      vtkVector3f bondVec;
      float bondRadius = mapper->GetBondRadius();
      vtkVector3f bondCenter;

      const vtkIdType numBonds = molecule->GetNumberOfBonds();
225
226
227
      std::vector<osp::vec4f> vertsAndRadii;
      std::vector<OSPMaterial> materials;
      std::vector<unsigned int> indices;
David E. DeMarle's avatar
David E. DeMarle committed
228
229
230
231

      vtkUnsignedShortArray* atomicNumbers = molecule->GetAtomicNumberArray();
      for (vtkIdType bondInd = 0; bondInd < numBonds; ++bondInd)
      {
232
233
234
235
        // each endpoint is doubled because we need to use OSP_BEZIER to vary width
        indices.push_back(bondInd * 8 + 0);
        indices.push_back(bondInd * 8 + 4);

David E. DeMarle's avatar
David E. DeMarle committed
236
237
238
239
240
241
242
243
244
245
246
247
248
249
        vtkBond bond = molecule->GetBond(bondInd);
        pos1 = bond.GetBeginAtom().GetPosition();
        pos2 = bond.GetEndAtom().GetPosition();
        atomIds[0] = bond.GetBeginAtomId();
        atomIds[1] = bond.GetEndAtomId();

        // Compute additional bond info
        // - Normalized vector in direction of bond
        bondVec = pos2 - pos1;
        // - Center of bond for translation
        bondCenter[0] = (pos1[0] + pos2[0]) * 0.5;
        bondCenter[1] = (pos1[1] + pos2[1]) * 0.5;
        bondCenter[2] = (pos1[2] + pos2[2]) * 0.5;

250
251
252
253
254
255
256
257
        auto start = osp::vec4f{ static_cast<float>(pos1.GetX()), static_cast<float>(pos1.GetY()),
          static_cast<float>(pos1.GetZ()), bondRadius };
        auto mid =
          osp::vec4f{ static_cast<float>(bondCenter.GetX()), static_cast<float>(bondCenter.GetY()),
            static_cast<float>(bondCenter.GetZ()), bondRadius };
        auto end = osp::vec4f{ static_cast<float>(pos2.GetX()), static_cast<float>(pos2.GetY()),
          static_cast<float>(pos2.GetZ()), bondRadius };

258
        // tube from atom1 to midpoint
259
260
        materials.emplace_back(_elementMaterials[atomicNumbers->GetValue(atomIds[0])]);
        vertsAndRadii.emplace_back(start);
261
        vertsAndRadii.emplace_back(start);
262
263
        vertsAndRadii.emplace_back(mid);
        vertsAndRadii.emplace_back(mid);
David E. DeMarle's avatar
David E. DeMarle committed
264

265
        // tube from midpoint to atom2
266
267
        materials.emplace_back(_elementMaterials[atomicNumbers->GetValue(atomIds[1])]);
        vertsAndRadii.emplace_back(mid);
268
        vertsAndRadii.emplace_back(mid);
269
270
        vertsAndRadii.emplace_back(end);
        vertsAndRadii.emplace_back(end);
David E. DeMarle's avatar
David E. DeMarle committed
271
272
      }

273
274
275
276
277
278
279
280
281
282
      OSPData vertsAndRadiiData =
        ospNewCopyData1D(vertsAndRadii.data(), OSP_VEC4F, vertsAndRadii.size());
      ospCommit(vertsAndRadiiData);
      ospSetObject(bonds, "vertex.position_radius", vertsAndRadiiData);
      ospRelease(vertsAndRadiiData);

      OSPData indicesData = ospNewCopyData1D(indices.data(), OSP_UINT, indices.size());
      ospCommit(indicesData);
      ospSetObject(bonds, "index", indicesData);
      ospRelease(indicesData);
David E. DeMarle's avatar
David E. DeMarle committed
283

284
285
      if (mapper->GetBondColorMode() == vtkMoleculeMapper::DiscreteByAtom)
      {
286
        OSPData materialData = ospNewCopyData1D(materials.data(), OSP_MATERIAL, materials.size());
287
288
289
        ospCommit(materialData);
        ospSetObject(bondsModel, "material", materialData);
        ospRelease(materialData);
290
291
292
      }
      else
      {
293
        auto oMaterial = vtkOSPRayMaterialHelpers::NewMaterial(orn, orn->GetORenderer(), "obj");
294
295
296
        unsigned char* vcolor = mapper->GetBondColor();
        float diffusef[] = { static_cast<float>(vcolor[0]) / (255.0f),
          static_cast<float>(vcolor[1]) / (255.0f), static_cast<float>(vcolor[2]) / (255.0f) };
297
298
299
300
        ospSetVec3f(oMaterial, "kd", diffusef[0], diffusef[1], diffusef[2]);
        ospSetVec3f(oMaterial, "ks", specularf[0], specularf[1], specularf[2]);
        ospSetInt(oMaterial, "ns", specPower);
        ospSetInt(oMaterial, "d", opacity);
301
        ospCommit(oMaterial);
302
303
        ospSetObjectAsData(bondsModel, "material", OSP_MATERIAL, oMaterial);
        ospRelease(oMaterial);
304
      }
David E. DeMarle's avatar
David E. DeMarle committed
305

306
307
308
309
      ospSetInt(bonds, "type", OSP_ROUND);
      ospSetInt(bonds, "basis", OSP_BEZIER);

      this->GeometricModels.emplace_back(bondsModel);
310
      ospCommit(bonds);
311
      ospCommit(bondsModel);
David E. DeMarle's avatar
David E. DeMarle committed
312
313
    }

David E. DeMarle's avatar
David E. DeMarle committed
314
    if (mapper->GetRenderLattice() && molecule->HasLattice())
David E. DeMarle's avatar
David E. DeMarle committed
315
    {
316
317
318
      OSPGeometry lattice = ospNewGeometry("curve");
      OSPGeometricModel latticeModel = ospNewGeometricModel(lattice);
      ospRelease(lattice);
David E. DeMarle's avatar
David E. DeMarle committed
319
320
321
322
323
324
325

      vtkVector3d a;
      vtkVector3d b;
      vtkVector3d c;
      vtkVector3d origin;

      molecule->GetLattice(a, b, c, origin);
326
      std::vector<osp::vec3f> vertices;
David E. DeMarle's avatar
David E. DeMarle committed
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
      for (int i = 0; i < 8; ++i)
      {
        vtkVector3d corner;
        switch (i)
        {
          case 0:
            corner = origin;
            break;
          case 1:
            corner = origin + a;
            break;
          case 2:
            corner = origin + b;
            break;
          case 3:
            corner = origin + c;
            break;
          case 4:
            corner = origin + a + b;
            break;
          case 5:
            corner = origin + a + c;
            break;
          case 6:
            corner = origin + b + c;
            break;
          case 7:
            corner = origin + a + b + c;
            break;
        }
357
358
        vertices.emplace_back(osp::vec3f{ static_cast<float>(corner.GetData()[0]),
          static_cast<float>(corner.GetData()[1]), static_cast<float>(corner.GetData()[2]) });
David E. DeMarle's avatar
David E. DeMarle committed
359
      }
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
      OSPData verticesData = ospNewCopyData1D(vertices.data(), OSP_VEC3F, vertices.size());
      ospCommit(verticesData);
      ospSetObject(lattice, "vertex.position", verticesData);
      ospRelease(verticesData);

      std::vector<unsigned int> indices;
      indices.emplace_back(0);
      indices.emplace_back(1);
      indices.emplace_back(1);
      indices.emplace_back(4);
      indices.emplace_back(4);
      indices.emplace_back(2);
      indices.emplace_back(2);
      indices.emplace_back(0);
      indices.emplace_back(0);
      indices.emplace_back(3);
      indices.emplace_back(2);
      indices.emplace_back(6);
      indices.emplace_back(4);
      indices.emplace_back(7);
      indices.emplace_back(1);
      indices.emplace_back(5);
      indices.emplace_back(6);
      indices.emplace_back(5);
      indices.emplace_back(3);
      indices.emplace_back(5);
      indices.emplace_back(3);
      indices.emplace_back(5);
      indices.emplace_back(7);
      indices.emplace_back(6);
      indices.emplace_back(7);
      OSPData indicesData = ospNewCopyData1D(indices.data(), OSP_UINT, indices.size());
      ospCommit(indicesData);
      ospSetObject(lattice, "index", indicesData);
      ospRelease(indicesData);
David E. DeMarle's avatar
David E. DeMarle committed
395

David E. DeMarle's avatar
David E. DeMarle committed
396
      double length = mapper->GetLength();
David E. DeMarle's avatar
David E. DeMarle committed
397
      double lineWidth = length / 1000.0 * property->GetLineWidth();
398
      ospSetFloat(lattice, "radius", lineWidth);
David E. DeMarle's avatar
David E. DeMarle committed
399

David E. DeMarle's avatar
David E. DeMarle committed
400
      float ocolor[4];
David E. DeMarle's avatar
David E. DeMarle committed
401
402
403
404
      unsigned char* vcolor = mapper->GetLatticeColor();
      ocolor[0] = vcolor[0] / 255.0;
      ocolor[1] = vcolor[1] / 255.0;
      ocolor[2] = vcolor[2] / 255.0;
David E. DeMarle's avatar
David E. DeMarle committed
405
      ocolor[3] = opacity;
406
      ospSetVec3f(latticeModel, "color", ocolor[0], ocolor[1], ocolor[2]);
David E. DeMarle's avatar
David E. DeMarle committed
407

408
409
      ospSetInt(lattice, "type", OSP_ROUND);
      ospSetInt(lattice, "basis", OSP_LINEAR);
David E. DeMarle's avatar
David E. DeMarle committed
410

411
412
413
      this->GeometricModels.emplace_back(latticeModel);
      ospCommit(lattice);
      ospCommit(latticeModel);
David E. DeMarle's avatar
David E. DeMarle committed
414
415
    }

David E. DeMarle's avatar
David E. DeMarle committed
416
    this->BuildTime.Modified();
David E. DeMarle's avatar
David E. DeMarle committed
417
  }
David E. DeMarle's avatar
David E. DeMarle committed
418

419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
  for (auto g : this->GeometricModels)
  {
    OSPGroup group = ospNewGroup();
    OSPInstance instance = ospNewInstance(group);
    ospCommit(instance);
    ospRelease(group);
    OSPData data = ospNewCopyData1D(&g, OSP_GEOMETRIC_MODEL, 1);
    ospRelease(&(*g));
    ospCommit(data);
    ospSetObject(group, "geometry", data);
    ospCommit(group);
    ospRelease(data);
    this->Instances.emplace_back(instance);
  }
  this->GeometricModels.clear();

  for (auto instance : this->Instances)
436
  {
437
    orn->Instances.emplace_back(instance);
438
  }
David E. DeMarle's avatar
David E. DeMarle committed
439
}