Skip to content

Commit

Permalink
Vertex color merge (#31)
Browse files Browse the repository at this point in the history
* implementation of colored mesh, depending on scalismo vertexColor 

* added ply (vertex color) reading to the ui

* added .ply in triangle mesh read

* some refactoring of names
  • Loading branch information
Ghazi-Bouabene authored Feb 22, 2019
1 parent 0409b15 commit 0132970
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 14 deletions.
19 changes: 14 additions & 5 deletions src/main/scala/scalismo/ui/api/ShowInScene.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ package scalismo.ui.api
import scalismo.common._
import scalismo.geometry.{ Landmark, Point, EuclideanVector, _3D }
import scalismo.image.DiscreteScalarImage
import scalismo.mesh.{ LineMesh, ScalarMeshField, TriangleMesh }
import scalismo.mesh.{ LineMesh, ScalarMeshField, TriangleMesh, VertexColorMesh3D }
import scalismo.registration.{ RigidTransformation, RigidTransformationSpace }
import scalismo.statisticalmodel.{ DiscreteLowRankGaussianProcess, LowRankGaussianProcess, StatisticalMeshModel }
import scalismo.ui.model._
Expand Down Expand Up @@ -60,10 +60,6 @@ trait LowPriorityImplicits {
}
}

}

object ShowInScene extends LowPriorityImplicits {

implicit object ShowInSceneMesh extends ShowInScene[TriangleMesh[_3D]] {
override type View = TriangleMeshView

Expand All @@ -74,6 +70,19 @@ object ShowInScene extends LowPriorityImplicits {

}

}

object ShowInScene extends LowPriorityImplicits {

implicit def ShowVertexColorMesh = new ShowInScene[VertexColorMesh3D] {
override type View = VertexColorMeshView

override def showInScene(mesh: VertexColorMesh3D, name: String, group: Group): VertexColorMeshView = {

VertexColorMeshView(group.peer.colorMeshes.add(mesh, name))
}
}

implicit object ShowInSceneLineMesh extends ShowInScene[LineMesh[_3D]] {
override type View = LineMeshView

Expand Down
58 changes: 57 additions & 1 deletion src/main/scala/scalismo/ui/api/Views.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import breeze.linalg.DenseVector
import scalismo.common.{DiscreteDomain, DiscreteField, DiscreteScalarField}
import scalismo.geometry.{EuclideanVector, Landmark, Point, _3D}
import scalismo.image.DiscreteScalarImage
import scalismo.mesh.{LineMesh, ScalarMeshField, TriangleMesh}
import scalismo.mesh.{LineMesh, ScalarMeshField, TriangleMesh, VertexColorMesh3D}
import scalismo.registration.RigidTransformation
import scalismo.statisticalmodel.{DiscreteLowRankGaussianProcess, StatisticalMeshModel}
import scalismo.ui.control.NodeVisibility
Expand Down Expand Up @@ -192,6 +192,62 @@ object TriangleMeshView {
}
}

case class VertexColorMeshView private[ui](override protected[api] val peer: VertexColorMeshNode) extends ObjectView {

type PeerType = VertexColorMeshNode

def opacity = peer.opacity.value

def opacity_=(o: Double): Unit = {
peer.opacity.value = o
}

def lineWidth = peer.lineWidth.value

def lineWidth_=(width: Int): Unit = {
peer.lineWidth.value = width
}

def colorMesh: VertexColorMesh3D = peer.source

def transformedTriangleMesh: VertexColorMesh3D = peer.transformedSource
}

object VertexColorMeshView {

implicit object FindInSceneColorMesh extends FindInScene[VertexColorMeshView] {
override def createView(s: SceneNode): Option[VertexColorMeshView] = {
s match {
case peer: VertexColorMeshNode => Some(VertexColorMeshView(peer))
case _ => None
}
}
}

implicit object callbacksColorMeshView extends HandleCallback[VertexColorMeshView] {

override def registerOnAdd[R](g: Group, f: VertexColorMeshView => R): Unit = {
g.peer.listenTo(g.peer.colorMeshes)
g.peer.reactions += {
case ChildAdded(collection, newNode: VertexColorMeshNode) =>
val tmv = VertexColorMeshView(newNode)
f(tmv)
}
}

override def registerOnRemove[R](g: Group, f: VertexColorMeshView => R): Unit = {
g.peer.listenTo(g.peer.colorMeshes)
g.peer.reactions += {
case ChildRemoved(collection, removedNode: VertexColorMeshNode) =>
val tmv = VertexColorMeshView(removedNode)
f(tmv)
}
}
}
}



case class LineMeshView private[ui] (override protected[api] val peer: LineMeshNode) extends ObjectView {

type PeerType = LineMeshNode
Expand Down
15 changes: 14 additions & 1 deletion src/main/scala/scalismo/ui/model/GroupNode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,27 @@ class GroupNode(override val parent: GroupsNode, initialName: String, private va

val landmarks = new LandmarksNode(this)
val triangleMeshes = new TriangleMeshesNode(this)
val colorMeshes = new VertexColorMeshesNode(this)
val scalarMeshFields = new ScalarMeshFieldsNode(this)
val lineMeshes = new LineMeshesNode(this)
val vectorFields = new VectorFieldsNode(this)
val pointClouds = new PointCloudsNode(this)
val images = new ImagesNode(this)
val scalarFields = new ScalarFieldsNode(this)

override val children: List[SceneNode] = List(genericTransformations, shapeModelTransformations, landmarks, triangleMeshes, lineMeshes, scalarMeshFields, pointClouds, images, scalarFields, vectorFields)
override val children: List[SceneNode] = List(
genericTransformations,
shapeModelTransformations,
landmarks,
triangleMeshes,
colorMeshes,
lineMeshes,
scalarMeshFields,
pointClouds,
images,
scalarFields,
vectorFields
)

// this is a convenience method to add a statistical model as a (gp, mesh) combination.
def addStatisticalMeshModel(model: StatisticalMeshModel, initialName: String): Unit = {
Expand Down
79 changes: 79 additions & 0 deletions src/main/scala/scalismo/ui/model/VertexColorMeshNode.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/

package scalismo.ui.model

import java.io.File

import scalismo.geometry.{ Point, Point3D, _3D }
import scalismo.geometry
import scalismo.io.MeshIO
import scalismo.mesh.VertexColorMesh3D
import scalismo.ui.model.capabilities._
import scalismo.ui.model.properties._
import scalismo.ui.util.{ FileIoMetadata, FileUtil }

import scala.util.{ Failure, Success, Try }

class VertexColorMeshesNode(override val parent: GroupNode) extends SceneNodeCollection[VertexColorMeshNode] with Loadable {
override val name: String = "Vertex Colored Triangle Meshes"

override def loadMetadata: FileIoMetadata = FileIoMetadata.VertexColorMesh

override def load(file: File): Try[Unit] = {
val r = MeshIO.readVertexColorMesh3D(file)
r match {
case Failure(ex) => Failure(ex)
case Success(mesh) =>
add(mesh, FileUtil.basename(file))
Success(())
}
}

def add(mesh: VertexColorMesh3D, name: String): VertexColorMeshNode = {
val node = new VertexColorMeshNode(this, mesh, name)
add(node)
node
}
}

class VertexColorMeshNode(override val parent: VertexColorMeshesNode, override val source: VertexColorMesh3D, initialName: String)
extends Transformable[VertexColorMesh3D] with InverseTransformation with Removeable with Renameable with HasLineWidth with HasOpacity with Saveable {
name = initialName

override def group: GroupNode = parent.parent

override def remove(): Unit = parent.remove(this)

override def inverseTransform(point: Point3D): Point3D = {
val id = transformedSource.shape.pointSet.findClosestPoint(point).id
source.shape.pointSet.point(id)
}

override def transform(untransformed: VertexColorMesh3D, transformation: PointTransformation): VertexColorMesh3D = {
untransformed.transform(transformation)
}

override val opacity = new OpacityProperty()

override val lineWidth = new LineWidthProperty()

override def save(file: File): Try[Unit] = MeshIO.writeVertexColorMesh3D(transformedSource, file)

override def saveMetadata: FileIoMetadata = FileIoMetadata.VertexColorMesh

}
9 changes: 8 additions & 1 deletion src/main/scala/scalismo/ui/rendering/Caches.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ package scalismo.ui.rendering
import scalismo.common.{ DiscreteDomain, DiscreteScalarField }
import scalismo.geometry._3D
import scalismo.image.DiscreteScalarImage
import scalismo.mesh.{ ScalarMeshField, TriangleMesh3D }
import scalismo.mesh.{ ScalarMeshField, TriangleMesh3D, VertexColorMesh3D }
import scalismo.ui.util.Cache
import vtk.{ vtkPolyData, vtkStructuredPoints }

Expand All @@ -35,8 +35,15 @@ object Caches {
override lazy val hashCode: Int = (31 + tm.pointSet.hashCode()) * (31 + tm.triangulation.hashCode())
}

case class FastCachingVertexColorMesh(mesh: VertexColorMesh3D) {
override lazy val hashCode: Int =
(31 + mesh.shape.pointSet.hashCode()) * (31 + mesh.shape.triangulation.hashCode() * 31 + mesh.color.hashCode())
}

final val TriangleMeshCache = new Cache[FastCachingTriangleMesh, vtkPolyData]
final val ImageCache = new Cache[DiscreteScalarImage[_3D, _], vtkStructuredPoints]
final val ScalarMeshFieldCache = new Cache[ScalarMeshField[Float], vtkPolyData]
final val ScalarFieldCache = new Cache[DiscreteScalarField[_3D, DiscreteDomain[_3D], Float], vtkPolyData]
final val VertexColorMeshCache = new Cache[FastCachingVertexColorMesh, vtkPolyData]

}
14 changes: 13 additions & 1 deletion src/main/scala/scalismo/ui/rendering/actor/ActorsFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,19 @@ import scala.reflect.ClassTag
*
*/
object ActorsFactory {
val BuiltinFactories: List[ActorsFactory] = List(BoundingBoxActor, TriangleMeshActor, ScalarMeshFieldActor, LineMeshActor, PointCloudActor, LandmarkActor, ImageActor, ScalarFieldActor, VectorFieldActor, TransformationGlyphActor)
val BuiltinFactories: List[ActorsFactory] = List(
BoundingBoxActor,
TriangleMeshActor,
ScalarMeshFieldActor,
VertexColorMeshActor,
LineMeshActor,
PointCloudActor,
LandmarkActor,
ImageActor,
ScalarFieldActor,
VectorFieldActor,
TransformationGlyphActor
)

var _factories: Map[Class[_ <: Renderable], ActorsFactory] = Map.empty

Expand Down
66 changes: 62 additions & 4 deletions src/main/scala/scalismo/ui/rendering/actor/MeshActor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@
package scalismo.ui.rendering.actor

import scalismo.geometry._3D
import scalismo.mesh.{ LineMesh, ScalarMeshField, TriangleMesh }
import scalismo.mesh.{LineMesh, ScalarMeshField, TriangleMesh, VertexColorMesh3D}
import scalismo.ui.model.capabilities.Transformable
import scalismo.ui.model.properties._
import scalismo.ui.model._
import scalismo.ui.rendering.Caches
import scalismo.ui.rendering.Caches.FastCachingTriangleMesh
import scalismo.ui.rendering.Caches.{FastCachingVertexColorMesh, FastCachingTriangleMesh}
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.ui.view.{ViewportPanel, ViewportPanel2D, ViewportPanel3D}
import scalismo.utils.MeshConversion
import vtk.vtkPolyData
import vtk.{vtkPolyData, vtkUnsignedCharArray}

object TriangleMeshActor extends SimpleActorsFactory[TriangleMeshNode] {

Expand Down Expand Up @@ -60,6 +60,16 @@ object LineMeshActor extends SimpleActorsFactory[LineMeshNode] {
}
}

object VertexColorMeshActor extends SimpleActorsFactory[VertexColorMeshNode] {
override def actorsFor(renderable: VertexColorMeshNode, viewport: ViewportPanel): Option[Actors] = {
viewport match {
case _3d: ViewportPanel3D => Some(new VertexColorMeshActor3D(renderable))
case _2d: ViewportPanel2D => Some(new VertexColorMeshActor2D(renderable, _2d))
}
}
}


object MeshActor {

trait MeshRenderable {
Expand Down Expand Up @@ -90,6 +100,20 @@ object MeshActor {
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 = node.transformedSource
}


class ScalarMeshFieldRenderable(override val node: ScalarMeshFieldNode) extends MeshRenderable {

type MeshType = TriangleMesh[_3D]
Expand Down Expand Up @@ -120,6 +144,8 @@ object MeshActor {

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)
Expand Down Expand Up @@ -189,6 +215,31 @@ trait TriangleMeshActor extends MeshActor[MeshRenderable.TriangleMeshRenderable]

}

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

Expand All @@ -214,6 +265,9 @@ trait ScalarMeshFieldActor extends MeshActor[MeshRenderable.ScalarMeshFieldRende

}




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
Expand Down Expand Up @@ -252,6 +306,10 @@ class TriangleMeshActor3D(node: TriangleMeshNode) extends MeshActor3D(MeshRender

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
Expand Down
Loading

0 comments on commit 0132970

Please sign in to comment.