Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 54 additions & 11 deletions src/main/kotlin/graphics/scenery/BoundingGrid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import java.util.*
*
* @author Ulrik Günther <[email protected]>
*/
open class BoundingGrid : Mesh("Bounding Grid") {
open class BoundingGrid : Mesh("Bounding Grid"), RenderingOrder {
protected var labels = HashMap<String, TextBoard>()

/** Grid color for the bounding grid. */
Expand All @@ -44,7 +44,7 @@ open class BoundingGrid : Mesh("Bounding Grid") {

/** Line width for the grid. */
@ShaderProperty
var lineWidth: Float = 1.2f
var lineWidth: Float = 1.0f
set(value) {
field = value
updateModifiedAt()
Expand All @@ -53,11 +53,24 @@ open class BoundingGrid : Mesh("Bounding Grid") {
/** Whether to show only the ticks on the grid, or show the full grid. */
@ShaderProperty
var ticksOnly: Int = 1
set(value) {
field = value
if(ticksOnly == 0) {
material().cullingMode = Material.CullingMode.Front
} else {
material().cullingMode = Material.CullingMode.None
}
updateModifiedAt()
}

@ShaderProperty
protected var boundingBoxSize: Vector3f = Vector3f(1.0f)
set(value) {
field = value
updateModifiedAt()
}


/** Slack around transparent objects, 2% by default. */
var slack = 0.02f

Expand All @@ -76,9 +89,21 @@ open class BoundingGrid : Mesh("Bounding Grid") {
init {
setMaterial(ShaderMaterial.fromFiles("DefaultForward.vert", "BoundingGrid.frag")) {
blending.transparent = true
blending.opacity = 0.8f
blending.setOverlayBlending()
cullingMode = Material.CullingMode.Front
blending.opacity = 1.0f
blending.sourceColorBlendFactor = Blending.BlendFactor.One
blending.destinationColorBlendFactor = Blending.BlendFactor.OneMinusSrcAlpha
blending.sourceAlphaBlendFactor = Blending.BlendFactor.One
blending.destinationAlphaBlendFactor = Blending.BlendFactor.OneMinusSrcAlpha
blending.colorBlending = Blending.BlendOp.add
blending.alphaBlending = Blending.BlendOp.add

if(ticksOnly > 0) {
cullingMode = Material.CullingMode.None
} else {
cullingMode = Material.CullingMode.Back
}
depthTest = true
depthOp = Material.DepthTest.LessEqual
}

labels = hashMapOf(
Expand All @@ -88,7 +113,7 @@ open class BoundingGrid : Mesh("Bounding Grid") {
"z" to TextBoard()
)

labels.forEach { s, fontBoard ->
labels.forEach { (s, fontBoard) ->
fontBoard.text = s
fontBoard.fontColor = Vector4f(1.0f, 1.0f, 1.0f, 1.0f)
fontBoard.backgroundColor = Vector4f(0.0f, 0.0f, 0.0f, 1.0f)
Expand Down Expand Up @@ -146,8 +171,9 @@ open class BoundingGrid : Mesh("Bounding Grid") {
}

val b = Box(max - min)
boundingBoxSize = max - min

logger.debug("Bounding box of $node is $maxBoundingBox")
logger.debug("Bounding box of {} is {}", node, maxBoundingBox)

val center = (max - min)*0.5f

Expand All @@ -166,10 +192,25 @@ open class BoundingGrid : Mesh("Bounding Grid") {

boundingBox?.let { bb ->
// label coordinates are relative to the bounding box
labels["0"]?.spatial()?.position = bb.min - Vector3f(0.1f, 0.0f, 0.0f)
labels["x"]?.spatial()?.position = Vector3f(2.0f * bb.max.x() + 0.1f, 0.01f, 0.01f) - center
labels["y"]?.spatial()?.position = Vector3f(-0.1f, 2.0f * bb.max.y(), 0.01f) - center
labels["z"]?.spatial()?.position = Vector3f(-0.1f, 0.01f, 2.0f * bb.max.z()) - center
val hs = 2.0f * bb.halfSize

labels["0"]?.spatial()?.position = bb.min - 0.02f * hs
labels["x"]?.spatial()?.position = Vector3f(2.0f * bb.max.x() + 0.02f* hs.x, -0.02f * hs.y, -0.02f * hs.z) - center
labels["y"]?.spatial()?.position = Vector3f(-0.02f * hs.x, 2.0f * bb.max.y() , 0.02f * hs.z) - center
labels["z"]?.spatial()?.position = Vector3f(-0.02f * hs.x, -0.02f * hs.y, 2.0f * bb.max.z() + 0.02f * hs.z) - center

val scale = Vector3f()
this.spatial().world.getScale(scale)
val fontScale = 0.3f
val invScale = Vector3f(1.0f/maxOf(scale.x, 0.0001f) * fontScale,
1.0f/maxOf(scale.y, 0.0001f) * fontScale,
1.0f/maxOf(scale.z, 0.0001f) * fontScale)

labels["0"]?.spatial()?.scale = invScale
labels["x"]?.spatial()?.scale = invScale
labels["y"]?.spatial()?.scale = invScale
labels["y"]?.spatial()?.scale?.timesAssign(-1.0f)
labels["z"]?.spatial()?.scale = invScale

spatial {
needsUpdate = true
Expand All @@ -193,6 +234,8 @@ open class BoundingGrid : Mesh("Bounding Grid") {
this.ticksOnly = fresh.ticksOnly
}

override var renderingOrder: Int = Int.MAX_VALUE

/**
* Returns this bounding box' coordinates and associated [Node] as String.
*/
Expand Down
42 changes: 26 additions & 16 deletions src/main/kotlin/graphics/scenery/volumes/RAIVolume.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import graphics.scenery.Origin
import graphics.scenery.utils.extensions.minus
import graphics.scenery.utils.extensions.plus
import graphics.scenery.utils.extensions.times
import net.imglib2.realtransform.AffineTransform3D
import net.imglib2.type.numeric.NumericType
import net.imglib2.type.numeric.integer.*
import net.imglib2.type.numeric.real.FloatType
Expand All @@ -23,9 +24,9 @@ class RAIVolume(@Transient val ds: VolumeDataSource, options: VolumeViewerOption
options,
hub
) {
private constructor() : this(VolumeDataSource.RAISource(UnsignedByteType(), emptyList(), ArrayList<ConverterSetup>(), 0, null), VolumeViewerOptions.options(), Hub()) {

}
// Empty secondary constructor is necessary for network serialisation
@Suppress("unused")
private constructor() : this(VolumeDataSource.RAISource(UnsignedByteType(), emptyList(), ArrayList<ConverterSetup>(), 0, null), VolumeViewerOptions.options(), Hub())

init {
name = "Volume (RAI source)"
Expand All @@ -44,9 +45,18 @@ class RAIVolume(@Transient val ds: VolumeDataSource, options: VolumeViewerOption
}

override fun generateBoundingBox(): OrientedBoundingBox {
val preScale = Vector3f(1.0f)
val source = firstSource()

if(source != null) {
val tr = AffineTransform3D()
source.spimSource.getSourceTransform(0, 0, tr)
preScale.set(tr.get(0, 0), tr.get(1,1), tr.get(2, 2))
}

return OrientedBoundingBox(this,
Vector3f(-0.0f, -0.0f, -0.0f),
Vector3f(getDimensions()))
Vector3f(0.0f),
Vector3f(getDimensions()) * preScale)
}

override fun localScale(): Vector3f {
Expand All @@ -69,7 +79,7 @@ class RAIVolume(@Transient val ds: VolumeDataSource, options: VolumeViewerOption
val min = Vector3i(s.min(0).toInt(), s.min(1).toInt(), s.min(2).toInt())
val max = Vector3i(s.max(0).toInt(), s.max(1).toInt(), s.max(2).toInt())
val d = max.sub(min)
logger.debug("Dimensions are $d")
logger.debug("Dimensions are {}", d)
d
} else {
Vector3i(1, 1, 1)
Expand All @@ -81,7 +91,7 @@ class RAIVolume(@Transient val ds: VolumeDataSource, options: VolumeViewerOption
}

/**
* Extension of [VolumeSpatial] for RAI volumes
* Extension of [Volume.VolumeSpatial] for RAI volumes
*/
class RAIVolumeSpatial(volume: RAIVolume): VolumeSpatial(volume) {
override fun composeModel() {
Expand All @@ -90,20 +100,20 @@ class RAIVolume(@Transient val ds: VolumeDataSource, options: VolumeViewerOption
val volume = (node as? RAIVolume) ?: return
val source = volume.firstSource()

val shift = if (source != null) {
val s = source.spimSource.getSource(0, 0)
val min = Vector3f(s.min(0).toFloat(), s.min(1).toFloat(), s.min(2).toFloat())
val max = Vector3f(s.max(0).toFloat(), s.max(1).toFloat(), s.max(2).toFloat())
(max - min) * (-0.5f)
} else {
Vector3f(0.0f, 0.0f, 0.0f)
}

model.translation(position)
model.mul(Matrix4f().set(this.rotation))
model.scale(scale)
model.scale(volume.localScale())
if (volume.origin == Origin.Center) {
val shift = if (source != null) {
val s = source.spimSource.getSource(0, 0)
val min = Vector3f(s.min(0).toFloat(), s.min(1).toFloat(), s.min(2).toFloat())
val max = Vector3f(s.max(0).toFloat(), s.max(1).toFloat(), s.max(2).toFloat())
(max - min) * (-0.5f)
} else {
Vector3f(0.0f, 0.0f, 0.0f)
}

model.translate(shift)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,37 @@ layout(set = 4, binding = 0) uniform ShaderProperties {
float lineWidth;
int ticksOnly;
vec3 gridColor;
vec3 boundingBoxSize;
};

layout(location = 0) out vec4 FragColor;

void main()
{
// draw screen-spaced antialiased grid lines, inspired by
// http://madebyevan.com/shaders/grid - here we scale the incoming
// coords by the numLines factor. For correct AA, the fwidth argument
// also has to be scaled by that factor.
vec2 coord = Vertex.TexCoord;
vec2 grid = abs(fract(coord*numLines - 0.5) - 0.5) / fwidth(coord*numLines);
// line width is determined by the minimum gradient, for thicker lines, we
// divide by lineWidth, lowering the gradient slope.
float line = min(grid.x, grid.y)/lineWidth;
vec3 coord = Vertex.FragPosition.xyz;
vec2 uv = Vertex.TexCoord;
vec3 grid = abs(fract(coord*numLines) - 0.5);
vec3 df = fwidth(coord * numLines);
vec3 grid3D = clamp((grid - df * (lineWidth - 1.0)) / df, 0.0, 1.0);
vec3 axis = vec3(1.0, 1.0, 1.0);
float line = float(length(axis) > 0.0) * pow(grid3D.x, axis.x) * pow(grid3D.y, axis.y) * pow(grid3D.z, axis.z);

// if only ticks should be display, this'll discard the interior
// of the bounding box quad completely, apart from the ticks.
if(ticksOnly > 0) {
if(coord.x > 0.02 && coord.x < 0.98 && coord.y > 0.02 && coord.y < 0.98) {
discard;
}
}

// mix together line colors and black background.
// everything apart from the lines should be transparent.
FragColor = mix(vec4(0.0), vec4(gridColor, Material.Opacity), 1.0 - min(line, 1.0));
float alpha = 1.0 - line;

if(ticksOnly > 0) {
vec2 bl = step(vec2(0.01), uv);
vec2 tr = step(vec2(0.01), 1.0 - uv);
alpha *= (1.0 - bl.x * bl.y * tr.x * tr.y);
}


if(alpha < 0.0001f) {
discard;
}
FragColor = vec4(gridColor * alpha, Material.Opacity * alpha);
}
Binary file not shown.