Skip to main content

Transparency settings not obeyed

33 replies [Last post]
mhakman
Offline
Joined: 2010-03-21

Hello,

I have 2 PointArray shapes without color values. One of them geometrically occludes the other. I set colors using ColoringAttributes and transparency using TransparencyAttributes. If I use TransparencyMode NONE then I see only the outermost object - this is correct. If I specify mode BLENDED or NICEST together with transparency value 0 then I would expect the same picture. What I see is however both objects - as if the outer object was transparent but only where the inner object "shines through". What can be wrong?

Thanks/Mikael

There are more interesting phenomena with transparency. I have 2 objects, one partially obscured by the second in front of it. When I use transparency mode NONE and rotate the whole shebang 180 degrees then the first object becomes the front object and now it obscures the second object. This is as it should be. However, if I use transparency mode NICEST or BLENDED then somehow Java3D decides which object should be obscured and keeps it obscured even when rotation brings it to the front! How come?

Thanks again/Mikael

Message was edited by: mhakman

Message was edited by: mhakman

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
darwinjob
Offline
Joined: 2004-11-16

BTW
You might also want to try isosurface approach - this one will give you excellent quality, low memory footprint and you can play with transparency any way you want.

Google for Marching Cubes algorithm.
Message was edited by: darwinjob

mhakman
Offline
Joined: 2010-03-21

Are you sure it should be Texture3D not Texture2D?

darwinjob
Offline
Joined: 2004-11-16

absolutely :)
you can use Texture2D but then you have to do some things manually.

mhakman
Offline
Joined: 2010-03-21

Ok, could you elaborate a little more on what would be the difference? I understand Texture2D but I'm not sure I understand what Texture3D does. Please?

darwinjob
Offline
Joined: 2004-11-16

hmm... well, I guess we can say that Texture3D is a stack of Texture2Ds, or 3D array with a values. When you assign Texture3D to a quad it is like the quad cuts this stack and gets a texture corresponding to the location of that cut. Visually it looks like Texture2D (quad is flat, right?). You can "cut" at _any_ angle/position. All Texture3D operations are taking the place on GPU side - which is good for the performance.

mhakman
Offline
Joined: 2010-03-21

Let’s se if I understand you correctly, and please correct me if not. My original idea was to have 256 big quads (planes) in z-direction, 256 in y-direction and 256 in x-direction. Disregarding per-hue-transparency problem I planned to have a Texture2D for each of these quads. You are saying that instead I could have _one_ Texture3D for a whole direction (3 Textures3D in total) and each such 3D texture should contain 256 images which then will auto-magically be assigned to each of the planes in that direction. Is this correct? Thanks.

darwinjob
Offline
Joined: 2004-11-16

Nope :)

>My original idea was to have 256 big quads (planes) in z-direction, 256 in y-direction and 256 in x-direction.

That is correct.

>_one_ Texture3D for a whole direction (3 Textures3D in total)
_One_ Texture3D for _all_ 3 directions and for all quads - that is the whole point here. Just think about it as a 3D array in 3D space, then you "cut" this "cube" with your quads, every quad gets the corresponding _virtual_ texture2D automagically (GPU will do it).

mhakman
Offline
Joined: 2010-03-21

Here is the promised screenshot:

http://www.dkab.net/screenshot.tiff

Thanks/Mikael

mhakman
Offline
Joined: 2010-03-21

Yesterday I was looking into Texture3D API for a method that would allow me to specify my images to be used for the cube. I cannot find such API call. How then do you specify your images? Thanks.

darwinjob
Offline
Joined: 2004-11-16

>I cannot find such API call

texture3D.setImage(0, pArray);

But you should not specify the images (well, you can if you really want). Look here:
http://forums.java.net/jive/thread.jspa?messageID=337897

the method:
private void clamp()

mhakman
Offline
Joined: 2010-03-21

> texture3D.setImage(0, pArray);

From the API doc:

public void setImages(ImageComponent[] images)
Sets the array of images for all mipmap levels.

I have only one base level but, if I understand you correctly, I need to specify the images fo Texture3D so that the system has something to work on. Does this call silently doubles its duties as to specify array of images for Texture3D at base level?

> But you should not specify the images

Then from where do images for Texture3D come? Somewhere I need to give the system images to work on! Thanks.

darwinjob
Offline
Joined: 2004-11-16

There is an example in the thread mentioned above where a 3D array of values mapped into Texture3D and visualized. Please see there.

mhakman
Offline
Joined: 2010-03-21

@darwinjob

I took the liberty to copy the code you refer to into my workspace and after slight modification I run it on my test file. The results are _not_ what I expected. Modification consists of replacing double [][][] with int [][][] containing RGBA values because this is what I get when reading my test TIFF file. Also I added control of transparency based on hue/transparency table. I have uploaded 3 files so that you can look and draw the conclusions yourself.

File http://www.dkab.net/screenshot.tiff contains results produced by my own algorithm which uses PointArray to represent the voxels. The problem with my approach is that 256x256x32 is about maximum size. Real files at 512x512x64 make my machine to almost die. Picture is produced using green at 95% transparency; the other colours are fully opaque. You may consider this picture as how it should look.

File http://www.dkab.net/green95.tiff is produced by your code. The same transparency as above is used.

File http://www.dkab.net/allOpaque.tiff is done using your code and all hues fully opaque. In this case you should see a greenish smooth cube and nothing else.

Thanks/Mikael

lamer77
Offline
Joined: 2006-12-22

The fastest way to render something back to front is to do it yourself. Use one geometry with all your primitives (points/triangles/quads) in it. Then create a WakeupOnElapsedFrames(0) behavior that sort all the primites back to front. Use an indexed geometry if you use triangles or quads. Don't bother with BY_REFERENCE as it is to complex. Just set the coordinates on the geometry every frame. I've done this on a transparent marching cube visualisation and the performance is good. You wont get correct sorting against other shapes, but that don't seem to be a problem here.

mhakman
Offline
Joined: 2010-03-21

@lamer77

> Then create a WakeupOnElapsedFrames(0) behavior that sort all the primites back to front. Use an indexed geometry if you use triangles or quads. Don't bother with BY_REFERENCE as it is to complex. Just set the coordinates on the geometry every frame.

I’m not sure I follow. I understand what WakeupOnElapsedFrames does but I don’t understand “sort all the primitives”. If you mean that I should write all the coordinates (or indexes) again on each frame in the order that corresponds to their order along current view path which vary with rotation done by the end user then given 512x512x512 points I don’t think I would have the time (one frame time) to do it. In addition this sorting is not trivial at all given continuous user controllable rotation in 3D.

I think that Java 3D should do this sorting for me. If the “3D” in Java 3D stands only for 3D projection but not for hidden area (volume) removal and proper transparency tracing then my only conclusion is this software is not for me. On the other hand I have seen that Java 3D can do what I need to be done so the question is how do I formulate the problem so that Java 3D understands it? I think the texture approach is right but there is more to it than demonstrated by the code in the other thread referred to above.

Thanks/Mikael

darwinjob
Offline
Joined: 2004-11-16

>Also I added control of transparency based on hue/transparency table.
You have to be careful with that. As you saw, the input values are mapped to byte array, you might want to try something else. Also, they are mapped linearly which is not the only option. Plus, as lamer77 says, the advanced sorting would be nice.

>but there is more to it than demonstrated by the code in the other thread referred to above.
Yep, as I told you above, the best solution would be to go Texture3D+Shaders way.

mhakman
Offline
Joined: 2010-03-21

Does Java3D support octrees directly? I cannot find any reference to them in API docs. How can they then speed-up things? Thanks/Mikael

Renoir Sewjee

I don't think Java3D supports octrees directly but it is fairly easy to
roll your own. I've attached some code to give you an idea of how I've
implemented this. Java3D uses bounds to cull objects for picking and
rendering - by creating an octree large parts of the model can be culled.

Example implementation from my application:

package za.co.issi.commons.j3d.geometry;

import java.awt.Color;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingBox;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.LineArray;
import javax.media.j3d.LineAttributes;
import javax.media.j3d.Material;
import javax.media.j3d.PointArray;
import javax.media.j3d.PointAttributes;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.QuadArray;
import javax.media.j3d.RenderingAttributes;
import javax.media.j3d.Shape3D;
import javax.media.j3d.TransparencyAttributes;
import javax.media.j3d.TriangleArray;

import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import za.co.issi.commons.colours.ColourSource;

import za.co.issi.commons.data.ints.ArrayIntSource;
import za.co.issi.commons.data.ints.IntSource;
import za.co.issi.commons.data.ints.ListIntSource;
import za.co.issi.commons.data.ints.MutableIntSource;

import za.co.issi.commons.geometry.tuples.Tuple3dSource;

import za.co.issi.commons.j3d.CullFace;
import za.co.issi.commons.j3d.LinePattern;
import za.co.issi.commons.j3d.PolygonMode;

/**
* @author Renoir
*/

public class GeometryArrayOctree
{
private GeometryArrayType geometryArrayType;

private Tuple3dSource vertices;
private Tuple3dSource normals;
private ColourSource colours;

private MutableIntSource elementStartVertexIndices;

private int maxDepth = 6;
private int maxElementsPerNode = 1;

private BranchGroup root;

private PointAttributes pointAttributes;
private LineAttributes lineAttributes;
private PolygonAttributes polygonAttributes;
private ColoringAttributes colouringAttributes;
private TransparencyAttributes transparencyAttributes;
private RenderingAttributes renderingAttributes;
private Material material;
private Appearance appearance;

private Object userData;

public GeometryArrayOctree(GeometryArrayType geometryArrayType,
IntSource elementIndices, IntSource elementVertexCounts, Tuple3dSource
vertices, Tuple3dSource normals, ColourSource colours, Object userData)
{
this.geometryArrayType = geometryArrayType;
this.vertices = vertices;
this.normals = normals;
this.colours = colours;
this.userData = userData;

// Check that all elements to be rendered have a vertex count
consistent with the geometry type.
for (int elementIndex : elementIndices)
{
if (elementVertexCounts.get(elementIndex) !=
geometryArrayType.getNumVerticesPerElement())
{
throw new IllegalArgumentException("element vertex
count not compatable with geometry type");
}
}

// Need to determine the vertices an element is composed of,
knowing both
// the start vertex index and the vertex count of an element
allows this to be done.
elementStartVertexIndices = new
ArrayIntSource((int)elementVertexCounts.size());
for (int i = 0, startVertexIndex = 0; i <
elementVertexCounts.size(); i++)
{
elementStartVertexIndices.set(i, startVertexIndex);
startVertexIndex += elementVertexCounts.get(i);
}

pointAttributes = new PointAttributes(1.0f, true);
pointAttributes.setCapability(PointAttributes.ALLOW_SIZE_READ);
pointAttributes.setCapability(PointAttributes.ALLOW_SIZE_WRITE);

lineAttributes = new LineAttributes(1.0f,
LineAttributes.PATTERN_SOLID, true);
lineAttributes.setCapability(LineAttributes.ALLOW_WIDTH_READ);
lineAttributes.setCapability(LineAttributes.ALLOW_WIDTH_WRITE);
lineAttributes.setCapability(LineAttributes.ALLOW_PATTERN_READ);
lineAttributes.setCapability(LineAttributes.ALLOW_PATTERN_WRITE);

polygonAttributes = new
PolygonAttributes(PolygonAttributes.POLYGON_FILL,
PolygonAttributes.CULL_NONE, 0.0f, true);
polygonAttributes.setCapability(PolygonAttributes.ALLOW_MODE_READ);

polygonAttributes.setCapability(PolygonAttributes.ALLOW_MODE_WRITE);

polygonAttributes.setCapability(PolygonAttributes.ALLOW_CULL_FACE_READ);

polygonAttributes.setCapability(PolygonAttributes.ALLOW_CULL_FACE_WRITE);

polygonAttributes.setCapability(PolygonAttributes.ALLOW_NORMAL_FLIP_READ);

polygonAttributes.setCapability(PolygonAttributes.ALLOW_NORMAL_FLIP_WRITE);

colouringAttributes = new ColoringAttributes(new
Color3f(Color.GRAY), ColoringAttributes.NICEST);

colouringAttributes.setCapability(ColoringAttributes.ALLOW_COLOR_READ);

colouringAttributes.setCapability(ColoringAttributes.ALLOW_COLOR_WRITE);

transparencyAttributes = new
TransparencyAttributes(TransparencyAttributes.NONE, 0.0f);

transparencyAttributes.setCapability(TransparencyAttributes.ALLOW_MODE_READ);

transparencyAttributes.setCapability(TransparencyAttributes.ALLOW_MODE_WRITE);

transparencyAttributes.setCapability(TransparencyAttributes.ALLOW_VALUE_READ);

transparencyAttributes.setCapability(TransparencyAttributes.ALLOW_VALUE_WRITE);

material = new Material();
material.setSpecularColor(0.1f, 0.1f, 0.1f);
material.setCapability(Material.ALLOW_COMPONENT_READ);
material.setCapability(Material.ALLOW_COMPONENT_WRITE);

renderingAttributes = new RenderingAttributes();

renderingAttributes.setCapability(RenderingAttributes.ALLOW_VISIBLE_READ);

renderingAttributes.setCapability(RenderingAttributes.ALLOW_VISIBLE_WRITE);

renderingAttributes.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_READ);

renderingAttributes.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_WRITE);

appearance = new Appearance();
appearance.setPointAttributes(pointAttributes);
appearance.setLineAttributes(lineAttributes);
appearance.setPolygonAttributes(polygonAttributes);
appearance.setColoringAttributes(colouringAttributes);
appearance.setTransparencyAttributes(transparencyAttributes);
appearance.setRenderingAttributes(renderingAttributes);
appearance.setMaterial(material);

root = new BranchGroup();
root.setCapability(BranchGroup.ALLOW_DETACH);
root.setCapability(BranchGroup.ALLOW_BOUNDS_READ);
root.setCapability(BranchGroup.ALLOW_BOUNDS_WRITE);
root.setCapability(BranchGroup.ALLOW_PICKABLE_READ);
root.setCapability(BranchGroup.ALLOW_PICKABLE_WRITE);

/*
* Determine the bounding box of the elements, this will be the
root of the octree.
*/
BoundingBox bounds = new BoundingBox((Bounds)null);

Point3d vertex = new Point3d();
for (int elementIndex : elementIndices)
{
int startVertexIndex =
elementStartVertexIndices.get(elementIndex);
for (int i = 0; i <
geometryArrayType.getNumVerticesPerElement(); i++)
{
vertices.get(startVertexIndex + i, vertex);
bounds.combine(vertex);
}
}

Point3d lower = new Point3d();
bounds.getLower(lower);

Point3d upper = new Point3d();
bounds.getUpper(upper);

Point3d centroid = new Point3d();
centroid.add(lower);
centroid.add(upper);
centroid.scale(0.5);

double scale = Math.max(upper.z - centroid.z, Math.max(upper.y
- centroid.y, upper.x - centroid.x));
lower.set(centroid.x - scale, centroid.y - scale, centroid.z -
scale);
upper.set(centroid.x + scale, centroid.y + scale, centroid.z +
scale);

createSubtree(root, lower, upper, elementIndices, 1);
root.compile();
}

private Shape3D createShape(IntSource elementIndices)
{
GeometryArray geometry = null;

int vertexFormat = GeometryArray.COORDINATES;
if (colours.size() > 0) vertexFormat |= GeometryArray.COLOR_3;
if (normals.size() > 0) vertexFormat |= GeometryArray.NORMALS;

int vertexCount =
((int)elementIndices.size())*geometryArrayType.getNumVerticesPerElement();

if (geometryArrayType == GeometryArrayType.POINTS)
geometry = new PointArray(vertexCount, vertexFormat);

else if (geometryArrayType == GeometryArrayType.LINES)
geometry = new LineArray(vertexCount, vertexFormat);

else if (geometryArrayType == GeometryArrayType.TRIS)
geometry = new TriangleArray(vertexCount, vertexFormat);

else if (geometryArrayType == GeometryArrayType.QUADS)
geometry = new QuadArray(vertexCount, vertexFormat);

Point3d vertex = new Point3d();
Vector3d normal = new Vector3d();
Vector3f normalf = new Vector3f();
Color3f colour = new Color3f();

// Mapping shape geometry vertex indices to element vertex indices.
int[] vertexIndexMapping = new int[vertexCount];

int geometryArrayVertexIndex = 0;
for (int elementIndex : elementIndices)
{
int startVertexIndex =
elementStartVertexIndices.get(elementIndex);
for (int i = 0; i <
geometryArrayType.getNumVerticesPerElement(); i++)
{
int vertexIndex = startVertexIndex + i;

vertices.get(vertexIndex, vertex);
geometry.setCoordinate(geometryArrayVertexIndex, vertex);

if (colours.size() > 0)
{
colour.set(colours.get(vertexIndex));
geometry.setColor(geometryArrayVertexIndex, colour);
}

if (normals.size() > 0)
{
normals.get(vertexIndex, normal);
normalf.set(normal);
geometry.setNormal(geometryArrayVertexIndex, normalf);
}

vertexIndexMapping[geometryArrayVertexIndex] = vertexIndex;

geometryArrayVertexIndex++;
}
}

geometry.setCapability(GeometryArray.ALLOW_INTERSECT);

Shape3D shape = new Shape3D(geometry, appearance);
shape.setUserData(new ShapeData(userData, new
ArrayIntSource(vertexIndexMapping)));

return shape;
}

private void createSubtree(BranchGroup parentBranchGroup, Point3d
lower, Point3d upper, IntSource elementIndices, int depth)
{
BranchGroup branchGroup = new BranchGroup();

// Create a leaf node
if (depth >= maxDepth || elementIndices.size() <=
maxElementsPerNode)
{
Shape3D shape = createShape(elementIndices);
branchGroup.addChild(shape);
}

// Create an internal node.
else
{
Point3d centroid = new Point3d();
centroid.add(lower);
centroid.add(upper);
centroid.scale(0.5);

// Child nodes are numbered 0 to 8 and -1 implies that the
parent node
Map> nodeElementMapping = new
HashMap>();

Point3d center = new Point3d();
Point3d vertex = new Point3d();
for (int elementIndex : elementIndices)
{
int startVertexIndex =
elementStartVertexIndices.get(elementIndex);

center.set(0, 0, 0);
for (int i = 0; i <
geometryArrayType.getNumVerticesPerElement(); i++)
center.add(vertices.get(startVertexIndex + i, vertex));

center.scale(1.0/geometryArrayType.getNumVerticesPerElement());

int node = getNodeContainingVertex(center, centroid);

if (!nodeElementMapping.containsKey(node))
nodeElementMapping.put(node, new ArrayList());
nodeElementMapping.get(node).add(elementIndex);
}

for (int node : nodeElementMapping.keySet())
{
createSubtree(branchGroup,
getChildNodeLowerBounds(node, lower,
centroid),
getChildNodeUpperBounds(node, upper,
centroid),
new
ListIntSource(nodeElementMapping.get(node)),
depth + 1);

}
}

parentBranchGroup.addChild(branchGroup);
}

public BranchGroup getBranchGroup()
{
return root;
}

public boolean getUseLighting()
{
return material.getLightingEnable();
}

public void setUseLighting(boolean useLighting)
{
material.setLightingEnable(useLighting);
}

public Color getBaseColour()
{
Color3f colour = new Color3f();
colouringAttributes.getColor(colour);

return colour.get();
}

public void setBaseColour(Color colour)
{
colouringAttributes.setColor(new Color3f(colour));
material.setDiffuseColor(new Color3f(colour));
}

public double getPointSize()
{
return pointAttributes.getPointSize();
}

public void setPointSize(double size)
{
pointAttributes.setPointSize((float)size);
}

public double getLineWidth()
{
return lineAttributes.getLineWidth();
}

public void setLineWidth(double width)
{
lineAttributes.setLineWidth((float)width);
}

public double getTransparency()
{
return transparencyAttributes.getTransparency();
}

public void setTransparency(double transparency)
{
if (transparency <= 0)
{

transparencyAttributes.setTransparencyMode(transparencyAttributes.NONE);
transparencyAttributes.setTransparency(0.0f);
}
else
{

transparencyAttributes.setTransparencyMode(transparencyAttributes.NICEST);
transparencyAttributes.setTransparency((float)transparency);
}
}

public PolygonMode getPolygonMode()
{
int pm = polygonAttributes.getPolygonMode();

if (pm == PolygonAttributes.POLYGON_FILL)
return PolygonMode.FILL;

else if (pm == PolygonAttributes.POLYGON_LINE)
return PolygonMode.LINE;

else if (pm == PolygonAttributes.POLYGON_POINT)
return PolygonMode.POINT;

assert false : "[getPolygonMode] unsupported polygon mode: " + pm;
return null;
}

public void setPolygonMode(PolygonMode polygonMode)
{
if (polygonMode == PolygonMode.FILL)

polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_FILL);

else if (polygonMode == PolygonMode.LINE)

polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_LINE);

else if (polygonMode == PolygonMode.POINT)

polygonAttributes.setPolygonMode(PolygonAttributes.POLYGON_POINT);

else
assert false : "[setPolygonMode] unsupported polygon mode:
" + polygonMode;
}

public CullFace getCullFace()
{
int cf = polygonAttributes.getCullFace();

if (cf == PolygonAttributes.CULL_NONE)
return CullFace.NONE;

else if (cf == PolygonAttributes.CULL_BACK)
return CullFace.BACK;

else if (cf == PolygonAttributes.CULL_FRONT)
return CullFace.FRONT;

assert false : "[getCullFace] unsupported cull face: " + cf;
return null;
}

public void setCullFace(CullFace cullFace)
{
if (cullFace == CullFace.NONE)
polygonAttributes.setCullFace(PolygonAttributes.CULL_NONE);

else if (cullFace == CullFace.BACK)
polygonAttributes.setCullFace(PolygonAttributes.CULL_BACK);

else if (cullFace == CullFace.FRONT)
polygonAttributes.setCullFace(PolygonAttributes.CULL_FRONT);

else
assert false : "[setCullFace] unsupported cull face: " +
cullFace;
}

public LinePattern getLinePattern()
{
int pattern = lineAttributes.getLinePattern();

if (pattern == LineAttributes.PATTERN_SOLID)
return LinePattern.SOLID;

else if (pattern == LineAttributes.PATTERN_DOT)
return LinePattern.DOT;

else if (pattern == LineAttributes.PATTERN_DASH)
return LinePattern.DASH;

else if (pattern == LineAttributes.PATTERN_DASH_DOT)
return LinePattern.DASH_DOT;

assert false : "[getLinePattern] unsupported line pattern: " +
pattern;
return null;
}

public void setLinePattern(LinePattern pattern)
{
if (pattern == LinePattern.SOLID)
lineAttributes.setLinePattern(LineAttributes.PATTERN_SOLID);

else if (pattern == LinePattern.DOT)
lineAttributes.setLinePattern(LineAttributes.PATTERN_DOT);

else if (pattern == LinePattern.DASH)
lineAttributes.setLinePattern(LineAttributes.PATTERN_DASH);

else if (pattern == LinePattern.DASH_DOT)
lineAttributes.setLinePattern(LineAttributes.PATTERN_DASH_DOT);

else
assert false : "[setLinePattern] unsupported line pattern:
" + pattern;
}

public boolean getBackFaceNormalFlip()
{
return polygonAttributes.getBackFaceNormalFlip();
}

public void setBackFaceNormalFlip(boolean state)
{
polygonAttributes.setBackFaceNormalFlip(state);
}

/** Is the rendering attributes visibility flag set? */
public boolean isVisible()
{
return renderingAttributes.getVisible();
}

/** Sets the rendering attributes visibility flag. */
public void setVisible(boolean state)
{
renderingAttributes.setVisible(state);
}

public boolean getDepthBufferEnable()
{
return renderingAttributes.getDepthBufferEnable();
}

public void setDepthBufferEnable(boolean state)
{
renderingAttributes.setDepthBufferEnable(state);
}

public static Point3d getChildNodeLowerBounds(int index, Point3d
lower, Point3d split)
{
Point3d l = new Point3d();

if ((index & 1) == 1)
l.x = split.x;
else
l.x = lower.x;

if ((index & 2) == 2)
l.y = split.y;
else
l.y = lower.y;

if ((index & 4) == 4)
l.z = split.z;
else
l.z = lower.z;

return l;
}

public static Point3d getChildNodeUpperBounds(int index, Point3d
upper, Point3d split)
{
Point3d u = new Point3d();

if ((index & 1) == 1)
u.x = upper.x;
else
u.x = split.x;

if ((index & 2) == 2)
u.y = upper.y;
else
u.y = split.y;

if ((index & 4) == 4)
u.z = upper.z;
else
u.z = split.z;

return u;
}

public static int getNodeContainingVertex(Point3d vertex, Point3d
split)
{
int index = 0;

if (vertex.x >= split.x) index += 1;
if (vertex.y >= split.y) index += 2;
if (vertex.z >= split.z) index += 4;

return index;
}
}

java3d-interest@javadesktop.org wrote:
> Does Java3D support octrees directly? I cannot find any reference to them in API docs. How can they then speed-up things? Thanks/Mikael
> [Message sent by forum member 'mhakman']
>
> http://forums.java.net/jive/thread.jspa?messageID=397982
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
> For additional commands, e-mail: interest-help@java3d.dev.java.net
>

--
Renoir Sewjee
Manager: Numerical Modelling
ISS International (Stellenbosch)

Tel : 021 809 2078
Fax : 021 809 2061
Cell: 0824696108
URL : http://www.issi.co.za/

Confidentiality Warning
____________________________________________________________________

This e-mail message contains confidential information which is
intended for the use of the person to whom it is addressed. If you
received it in error, please notify the sender and delete the
material from any computer. Any disclosure, re-transmission,
dissemination or any other use of this information is strictly
prohibited.
____________________________________________________________________

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

mhakman
Offline
Joined: 2010-03-21

That was a lot of code but it doesn't help me. My problem in the original question is not culling parts of the model or speedup. On the contrary, my models are manually (mouse) rotated so the the scientist can see them from different angles. Nothing is to be culled. Parts are made semi-transparent so that the scientist can look inside while also rotating the model. We call it volume visualisation. I work with a HashTable of coordinate/color lists keyed (today) on hue classification values. I cannot see how octree can help me. The original question is not about model storage but that of inadequate rendering capabilities of Java3D. Thanks/Mikael

darwinjob
Offline
Joined: 2004-11-16

Could you post the screenshot of what you currently get? What are the dimensions of the dataset(s)?

mhakman
Offline
Joined: 2010-03-21

Dimensions of the dataset vary from 256x256x32 to 512x512x64. I try to post a screenshot (256x256x32). How do you post a screenshot?

If you look at the yellow object, - its top is shaded by a green wall. That wall is behind the yellow object so no shade should be visible. Please note that I have 6 Shape3D objects - each shape gathers points (PointArray) that fall into the range of one of the 6 base colors. In this simple example colors correspond to visible objects, the cube is greenish, the cone is red and the double cone is yellow. In a real case this will not be true - a certain color range will be spread all over the image and therefore each Shape3D will be inter-twinned with the other shapes. Note also that the pure colors are used only for classification into shapes. The actual colors drawn are those present at a particular point. In the screenshot, both red and yellow object are fully opaque, the cube is 0.05 opaque, i. e. 95% transparent.

darwinjob
Offline
Joined: 2004-11-16

>How do you post a screenshot?
I guess you have to use one of these free image hosting servises.

512x512x... is not many so you might want to try a volume rendering techniques - to visualize your points as voxels. You could merge all datasets into one volume and then render it using e.g. Texture Mapping. See Texture3D.

mhakman
Offline
Joined: 2010-03-21

Ok, I'll put the screenshot on my site and give you an URL. I'm not sure I get time to do it today.

No, already 256x256x32 points rendered as voxels, i.e 6 quads each is too much for my 2.5 GHz MacBookPro. Perhaps if I get more memory which I'm waiting for delivery for.

Yes, texture mapping seems to be the right way. I'm working on it right now. If I think right I'll end up with 6*2*(nx+ny+nz) quads which is much less than 6*6*nx*ny*nz when using the above "naive" method. The first 6 is for the six base colors. The second 6 is for the six sides of a voxel. Also I need to interpolate Z as to get nz=256 or so which makes the problem even larger.

darwinjob
Offline
Joined: 2004-11-16

Ok, so you deal with the voxels already. But I would like to suggest the following. Instead of having 6 quads per voxel, let's use one "big" quad per "layer": 256*256*32 intersecting quads. Every such quad will be _textured_ by single RGBA Texture3D. You don't need to interpolate anything - it will be done by videocard (it must support Texture3D, check it here: http://download.java.net/media/java3d/webstart/test/QueryProperties.jnlp). Alpha channel is essential because this is how you designate "empty" voxels - fully transparent.

Here is the example of this approach:
http://software.incf.org/static/software/25/projectimage/82/ct_and_pet.png
http://software.incf.org/static/software/25/projectimage/33/ct1.png
http://software.incf.org/static/software/25/projectimage/34/ct2.png
http://software.incf.org/software/atlas3d/home/image/

The thread with the code:
http://forums.java.net/jive/thread.jspa?messageID=337897

This is not the best solution though, the most elegant would be to use programmable shaders, which I have no knowledge of :(

Also, consider to use ModelClip to dynamically clip off unwanted parts of the model.

Let me know if you need further explanations.

mhakman
Offline
Joined: 2010-03-21

Yes, I’m already working along these lines. Except that I didn’t know it will interpolate for me – very good. But I still need to have separate shapes or textures for each of the six base color ranges – I need to change transparency on a per color basis. Then I need 6 big layers per each x,y,z plane resulting in 6 * (nx + ny + nz) shapes or textures. The question is then should I use nx+ny+nz shapes with 6 textures each or should I use 6 * (nx +ny +nz) shapes with one texture each?

Another question: is there a way to dynamically apply a threshold – all voxels below certain user-changeable value should show as empty?

BTW, many thanks for the links to related topics.

chrismcband
Offline
Joined: 2006-07-10

Use View.setTransparencySortingPolicy(View.TRANSPARENCY_SORT_GEOMETRY). This should make sure the geometries are sorted so the colors blend correctly.

mhakman
Offline
Joined: 2010-03-21

Yes, TRANSPARENCY_SORT_GEOMETRY helps a lot. Now the object in front (after rotation) is mostly shown in front. I'm writing "mostly" because I still se some "shadows" from objects that are behind (after rotation) the actual object. Also, if I make the enclosing object fully opaque then at some rotation angles, the enclosed objects are visible. They shouldn't be. Moreover if I make the enclosing object semi-transparent then the visibility of enclosed objects depends on rotation angle. It shouldn't because the whole thing is symmetrical around the 3 axes. It is how Java3D does it or are there more options/switches to set? Thanks/Mikael

lamer77
Offline
Joined: 2006-12-22

Transparent objects has to be rendered back to front to look correct. TRANSPARENCY_SORT_GEOMETRY will sort the shaped on distance to the view. If you come up with a better way you can use com.sun.j3d.utils.scenegraph.transparency.TransparencySortController to alter the order the shapes are rendered.

mhakman
Offline
Joined: 2010-03-21

If it sorts based on the whole objects then it will not work correctly for my purposes. I have objects that fully enclose (or are intertwined with) other objects that in turn enclose or intertwine yet other objects etc. You have to “sort” every point and then ray-trace it to the projection plane mixing with the other points along the ray to get it right. I thought Java3D did it this way. Perhaps I expect too much from it. But the 3D in its name leads to (perhaps incorrect) conclusion that it will render 3D objects correctly independent of object’s complexity. As you describe it, it will only render right given a few special and degenerate cases. This is certainly not what I expected. Thanks/Mikael

Renoir Sewjee

Hi,

Put the different parts of your object in separate Shape3Ds. I think
that tris and quads within a single Shape3D are not transparency sorted.

Regards,
Renoir

java3d-interest@javadesktop.org wrote:
> If it sorts based on the whole objects then it will not work correctly for my purposes. I have objects that fully enclose (or are intertwined with) other objects that in turn enclose or intertwine yet other objects etc. You have to “sort” every point and then ray-trace it to the projection plane mixing with the other points along the ray to get it right. I thought Java3D did it this way. Perhaps I expect too much from it. But the 3D in its name leads to (perhaps incorrect) conclusion that it will render 3D objects correctly independent of object’s complexity. As you describe it, it will only render right given a few special and degenerate cases. This is certainly not what I expected. Thanks/Mikael
> [Message sent by forum member 'mhakman']
>
> http://forums.java.net/jive/thread.jspa?messageID=397754
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
> For additional commands, e-mail: interest-help@java3d.dev.java.net
>

--
Renoir Sewjee
Manager: Numerical Modelling
ISS International (Stellenbosch)

Tel : 021 809 2078
Fax : 021 809 2061
Cell: 0824696108
URL : http://www.issi.co.za/

Confidentiality Warning
____________________________________________________________________

This e-mail message contains confidential information which is
intended for the use of the person to whom it is addressed. If you
received it in error, please notify the sender and delete the
material from any computer. Any disclosure, re-transmission,
dissemination or any other use of this information is strictly
prohibited.
____________________________________________________________________

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

mhakman
Offline
Joined: 2010-03-21

I cannot do that because I don’t know what the parts are! I get a 3-d matrix with colour points to my app. The best I can do is to remove black points and then sort on hue- ranges into separate Shape3D (PointArray) objects, which I already do. I tried to use z-planes from this matrix as Shape3D object each. Then the picture is ugly – you can clearly see the banding caused by these separate slabs.

Thanks/Mikael

Renoir Sewjee

I use an octree to separate my points/tris/quads using BranchGroups for
internal nodes and Shape3Ds for the leaves of the octree. This also
speeds up picking and rendering.

java3d-interest@javadesktop.org wrote:
> I cannot do that because I don’t know what the parts are! I get a 3-d matrix with colour points to my app. The best I can do is to remove black points and then sort on hue- ranges into separate Shape3D (PointArray) objects, which I already do. I tried to use z-planes from this matrix as Shape3D object each. Then the picture is ugly – you can clearly see the banding caused by these separate slabs.
>
> Thanks/Mikael
> [Message sent by forum member 'mhakman']
>
> http://forums.java.net/jive/thread.jspa?messageID=397779
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
> For additional commands, e-mail: interest-help@java3d.dev.java.net
>

--
Renoir Sewjee
Manager: Numerical Modelling
ISS International (Stellenbosch)

Tel : 021 809 2078
Fax : 021 809 2061
Cell: 0824696108
URL : http://www.issi.co.za/

Confidentiality Warning
____________________________________________________________________

This e-mail message contains confidential information which is
intended for the use of the person to whom it is addressed. If you
received it in error, please notify the sender and delete the
material from any computer. Any disclosure, re-transmission,
dissemination or any other use of this information is strictly
prohibited.
____________________________________________________________________

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

mhakman
Offline
Joined: 2010-03-21

What is octree? Thanks.