scalismo.ui.rendering.actor.MeshActor.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2016 University of Basel, Graphics and Vision Research Group
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package scalismo.ui.rendering.actor
import scalismo.common.DiscreteField.ScalarMeshField
import scalismo.geometry._3D
import scalismo.mesh.{LineMesh, TriangleMesh, VertexColorMesh3D}
import scalismo.ui.model._
import scalismo.ui.model.capabilities.Transformable
import scalismo.ui.model.properties._
import scalismo.ui.rendering.Caches
import scalismo.ui.rendering.Caches.{FastCachingTriangleMesh, FastCachingVertexColorMesh}
import scalismo.ui.rendering.actor.MeshActor.MeshRenderable
import scalismo.ui.rendering.actor.mixin._
import scalismo.ui.rendering.util.VtkUtil
import scalismo.ui.view.{ViewportPanel, ViewportPanel2D, ViewportPanel3D}
import scalismo.utils.MeshConversion
import vtk.{vtkPolyData, vtkPolyDataNormals, vtkUnsignedCharArray}
object TriangleMeshActor extends SimpleActorsFactory[TriangleMeshNode] {
override def actorsFor(renderable: TriangleMeshNode, viewport: ViewportPanel): Option[Actors] = {
viewport match {
case _: ViewportPanel3D => Some(new TriangleMeshActor3D(renderable))
case _2d: ViewportPanel2D => Some(new TriangleMeshActor2D(renderable, _2d))
}
}
}
object ScalarMeshFieldActor extends SimpleActorsFactory[ScalarMeshFieldNode] {
override def actorsFor(renderable: ScalarMeshFieldNode, viewport: ViewportPanel): Option[Actors] = {
viewport match {
case _: ViewportPanel3D => Some(new ScalarMeshFieldActor3D(renderable))
case _2d: ViewportPanel2D => Some(new ScalarMeshFieldActor2D(renderable, _2d))
}
}
}
object LineMeshActor extends SimpleActorsFactory[LineMeshNode] {
override def actorsFor(renderable: LineMeshNode, viewport: ViewportPanel): Option[Actors] = {
viewport match {
case _: ViewportPanel3D => Some(new LineMeshActor3D(renderable))
case _2d: ViewportPanel2D => Some(new LineMeshActor2D(renderable, _2d))
}
}
}
object VertexColorMeshActor extends SimpleActorsFactory[VertexColorMeshNode] {
override def actorsFor(renderable: VertexColorMeshNode, viewport: ViewportPanel): Option[Actors] = {
viewport match {
case _: ViewportPanel3D => Some(new VertexColorMeshActor3D(renderable))
case _2d: ViewportPanel2D => Some(new VertexColorMeshActor2D(renderable, _2d))
}
}
}
object MeshActor {
trait MeshRenderable {
type MeshType
def opacity: OpacityProperty
def lineWidth: LineWidthProperty
def mesh: MeshType
def node: SceneNode
}
private[actor] object MeshRenderable {
class TriangleMeshRenderable(override val node: TriangleMeshNode) extends MeshRenderable {
type MeshType = TriangleMesh[_3D]
override def opacity: OpacityProperty = node.opacity
override def mesh: TriangleMesh[_3D] = node.transformedSource
override def lineWidth: LineWidthProperty = node.lineWidth
def color: ColorProperty = node.color
}
class VertexColorMeshRenderable(override val node: VertexColorMeshNode) extends MeshRenderable {
type MeshType = TriangleMesh[_3D]
override def mesh: TriangleMesh[_3D] = node.transformedSource.shape
override def opacity: OpacityProperty = node.opacity
override def lineWidth: LineWidthProperty = node.lineWidth
def colorMesh: VertexColorMesh3D = node.transformedSource
}
class ScalarMeshFieldRenderable(override val node: ScalarMeshFieldNode) extends MeshRenderable {
type MeshType = TriangleMesh[_3D]
override def opacity: OpacityProperty = node.opacity
override def lineWidth: LineWidthProperty = node.lineWidth
override def mesh: TriangleMesh[_3D] = field.mesh
def scalarRange: ScalarRangeProperty = node.scalarRange
def field: ScalarMeshField[Float] = node.transformedSource
}
class LineMeshRenderable(override val node: LineMeshNode) extends MeshRenderable {
type MeshType = LineMesh[_3D]
override def opacity: OpacityProperty = node.opacity
override def lineWidth: LineWidthProperty = node.lineWidth
override def mesh: LineMesh[_3D] = node.transformedSource
def color: ColorProperty = node.color
}
def apply(source: TriangleMeshNode): TriangleMeshRenderable = new TriangleMeshRenderable(source)
def apply(source: VertexColorMeshNode): VertexColorMeshRenderable = new VertexColorMeshRenderable(source)
def apply(source: ScalarMeshFieldNode): ScalarMeshFieldRenderable = new ScalarMeshFieldRenderable(source)
def apply(source: LineMeshNode): LineMeshRenderable = new LineMeshRenderable(source)
}
}
trait MeshActor[R <: MeshRenderable] extends SingleDataSetActor with ActorOpacity with ActorSceneNode {
def renderable: R
override def opacity: OpacityProperty = renderable.opacity
override def sceneNode: SceneNode = renderable.node
protected def meshToPolyData(template: Option[vtkPolyData]): vtkPolyData
protected var polydata: vtkPolyData = meshToPolyData(None)
// this is invoked from within the rerender method, if the geometry has changed.
protected def onGeometryChanged(): Unit
protected def rerender(geometryChanged: Boolean): Unit = {
if (geometryChanged) {
polydata = meshToPolyData(Some(polydata))
onGeometryChanged()
}
actorChanged(geometryChanged)
}
protected def onInstantiated(): Unit = {}
//FIXME: pick control -- this should probably go into a trait or something.
renderable.node match {
case p: HasPickable =>
SetPickable(if (p.pickable.value) 1 else 0)
listenTo(p.pickable)
reactions += {
case NodeProperty.event.PropertyChanged(s) if s == p.pickable =>
SetPickable(if (p.pickable.value) 1 else 0)
}
case _ =>
}
onInstantiated()
rerender(geometryChanged = true)
listenTo(renderable.node)
reactions += {
case Transformable.event.GeometryChanged(_) => rerender(geometryChanged = true)
}
}
trait TriangleMeshActor extends MeshActor[MeshRenderable.TriangleMeshRenderable] with ActorColor {
override def renderable: MeshRenderable.TriangleMeshRenderable
override def color: ColorProperty = renderable.color
override protected def meshToPolyData(template: Option[vtkPolyData]): vtkPolyData = {
Caches.TriangleMeshCache.getOrCreate(FastCachingTriangleMesh(renderable.mesh),
MeshConversion.meshToVtkPolyData(renderable.mesh, template))
}
}
trait VertexColorMeshActor extends MeshActor[MeshRenderable.VertexColorMeshRenderable] {
override def renderable: MeshRenderable.VertexColorMeshRenderable
override protected def meshToPolyData(template: Option[vtkPolyData]): vtkPolyData = {
def colorMeshToVtkPd(colorMesh: VertexColorMesh3D): vtkPolyData = {
val pd = MeshConversion.meshToVtkPolyData(colorMesh.shape)
val vtkColors = new vtkUnsignedCharArray()
vtkColors.SetNumberOfComponents(3)
vtkColors.SetName("RGB")
for (id <- colorMesh.shape.pointSet.pointIds) {
val color = colorMesh.color(id)
vtkColors.InsertNextTuple3((color.r * 255).toShort, (color.g * 255).toShort, (color.b * 255).toShort)
}
pd.GetPointData().SetScalars(vtkColors)
pd
}
Caches.VertexColorMeshCache
.getOrCreate(FastCachingVertexColorMesh(renderable.colorMesh), colorMeshToVtkPd(renderable.colorMesh))
}
}
trait LineMeshActor extends MeshActor[MeshRenderable.LineMeshRenderable] with ActorColor with ActorLineWidth {
override def renderable: MeshRenderable.LineMeshRenderable
override def color: ColorProperty = renderable.color
override protected def meshToPolyData(template: Option[vtkPolyData]): vtkPolyData = {
MeshConversion.lineMeshToVTKPolyData(renderable.mesh, template)
}
override def lineWidth: LineWidthProperty = renderable.lineWidth
}
trait ScalarMeshFieldActor extends MeshActor[MeshRenderable.ScalarMeshFieldRenderable] with ActorScalarRange {
override def renderable: MeshRenderable.ScalarMeshFieldRenderable
override def scalarRange: ScalarRangeProperty = renderable.scalarRange
override protected def meshToPolyData(template: Option[vtkPolyData]): vtkPolyData = {
Caches.ScalarMeshFieldCache
.getOrCreate(renderable.field, MeshConversion.scalarMeshFieldToVtkPolyData(renderable.field))
}
}
abstract class MeshActor3D[R <: MeshRenderable](override val renderable: R) extends MeshActor[R] {
// not declaring this as lazy causes all sorts of weird VTK errors, probably because the methods which use
// it are invoked from the superclass constructor (at which time this class is not necessarily fully initialized)(?)
private lazy val normals: vtkPolyDataNormals = new vtk.vtkPolyDataNormals() {
ComputePointNormalsOn()
ComputeCellNormalsOff()
}
override protected def onInstantiated(): Unit = {
mapper.SetInputConnection(normals.GetOutputPort())
}
override protected def onGeometryChanged(): Unit = {
normals.RemoveAllInputs()
normals.SetInputData(polydata)
normals.Update()
}
}
abstract class MeshActor2D[R <: MeshRenderable](override val renderable: R, viewport: ViewportPanel2D)
extends SlicingActor(viewport)
with MeshActor[R]
with ActorLineWidth {
override def lineWidth: LineWidthProperty = renderable.lineWidth
override protected def onSlicingPositionChanged(): Unit = rerender(geometryChanged = false)
override protected def onGeometryChanged(): Unit = {
planeCutter.SetInputData(polydata)
planeCutter.Modified()
}
override protected def sourceBoundingBox: BoundingBox = VtkUtil.bounds2BoundingBox(polydata.GetBounds())
}
class TriangleMeshActor3D(node: TriangleMeshNode) extends MeshActor3D(MeshRenderable(node)) with TriangleMeshActor
class TriangleMeshActor2D(node: TriangleMeshNode, viewport: ViewportPanel2D)
extends MeshActor2D(MeshRenderable(node), viewport)
with TriangleMeshActor
class VertexColorMeshActor3D(node: VertexColorMeshNode)
extends MeshActor3D(MeshRenderable(node))
with VertexColorMeshActor
class VertexColorMeshActor2D(node: VertexColorMeshNode, viewport: ViewportPanel2D)
extends MeshActor2D(MeshRenderable(node), viewport)
with VertexColorMeshActor
class ScalarMeshFieldActor3D(node: ScalarMeshFieldNode)
extends MeshActor3D(MeshRenderable(node))
with ScalarMeshFieldActor
class ScalarMeshFieldActor2D(node: ScalarMeshFieldNode, viewport: ViewportPanel2D)
extends MeshActor2D(MeshRenderable(node), viewport)
with ScalarMeshFieldActor
class LineMeshActor3D(node: LineMeshNode) extends MeshActor3D(MeshRenderable(node)) with LineMeshActor
class LineMeshActor2D(node: LineMeshNode, viewport: ViewportPanel2D)
extends MeshActor2D(MeshRenderable(node), viewport)
with LineMeshActor
© 2015 - 2024 Weber Informatics LLC | Privacy Policy