Render simple lines

Have jReality programming problems or questions? Post them here.
Joe
Posts: 61
Joined: Fri 11. Jul 2008, 19:29

Render simple lines

Post by Joe » Fri 8. Aug 2008, 20:02

Hi,
how can I render a simple line, not a tube. I mean a line like I draw with graphics.drawLine(...), which has always a thickness of one pixel.

With this piece of code, always a tube is rendered. Unfortunately the JavaDoc of the class CommonAttributes is not complete. I think with a special combination of attributes I could reach my aim.

Many thanks and best regards, Joe

Code: Select all

package de.jreality.tutorial;

import de.jreality.geometry.IndexedLineSetFactory;
import de.jreality.scene.Appearance;
import java.awt.Component;

import javax.swing.JFrame;

import de.jreality.scene.SceneGraphComponent;
import de.jreality.shader.CommonAttributes;
import de.jreality.ui.viewerapp.ViewerApp;
import java.awt.Color;

public class SimpleViewer {
   public static void main(String[] args){
      double[][] vertices = new double[][]{{-1, -1, 0}, {1, -1, 0}, {1, 1, 0}, {-1, 1, 0},
                                           {-1, -1, 5}, {1, -1, 5}, {1, 1, 5}, {-1, 1, 5}};
      int[][] faceIndices = new int[][]{   {0, 1}, {5, 4}, {5, 4}, {1, 5}, {2, 6}, {4, 7}};
      IndexedLineSetFactory indexedLineSetFactory = new IndexedLineSetFactory();
      indexedLineSetFactory.setVertexCount(vertices.length);
      indexedLineSetFactory.setVertexCoordinates(vertices);
      indexedLineSetFactory.setLineCount(faceIndices.length);
      indexedLineSetFactory.setEdgeIndices(faceIndices);
      indexedLineSetFactory.setEdgeColors(new Color[]{Color.RED, Color.RED, Color.RED, Color.RED, Color.RED, Color.RED});
      indexedLineSetFactory.update();

      SceneGraphComponent sceneGraphComponent = new SceneGraphComponent();
	  sceneGraphComponent.setGeometry(indexedLineSetFactory.getGeometry());

	  Appearance appearance = new Appearance();
      appearance.setAttribute(CommonAttributes.VERTEX_DRAW, false);
      appearance.setAttribute(CommonAttributes.EDGE_DRAW, true);
	  appearance.setAttribute(CommonAttributes.TUBES_DRAW, false);
	  appearance.setAttribute(CommonAttributes.FACE_DRAW, false);
      sceneGraphComponent.setAppearance(appearance);

	  ViewerApp viewerApp = new ViewerApp(sceneGraphComponent);

	  JFrame frame = new JFrame();
      frame.getContentPane().add((Component)viewerApp.getViewingComponent());

      frame.setSize(512, 512);
      frame.validate();
      frame.setVisible(true);
   }
} 

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Tue 12. Aug 2008, 23:56

Joe,

You have found the way to disable tube-drawing:

Code: Select all

appearance.setAttribute(CommonAttributes.TUBES_DRAW, false); 
does exactly what you want. I think you'll see the difference if you change this to:

Code: Select all

appearance.setAttribute(CommonAttributes.TUBES_DRAW, true);
Then, you should see the lines significantly larger, and drawn with shaded tubes around them.

To control the width of the lines: use

Code: Select all

appearance.setAttribute(CommonAttributes.LINE_WIDTH, 2.0); 
to draw the lines 2 pixels wide. The default is 1 pixel wide.

(If instead you are drawing tubes, you'll need to use the command

Code: Select all

appearance.setAttribute(CommonAttributes.TUBE_RADIUS, 2.0); 
to create tubes with radius 2 in object coordinates.)

This reminds me that there should be a tutorial devoted to different possibilities for rendering lines. I'll put it on the list! In the meantime I hope this helps straighten out your problem.
jReality core developer

Joe
Posts: 61
Joined: Fri 11. Jul 2008, 19:29

Post by Joe » Thu 14. Aug 2008, 09:12

Yes, with the attribute TUBE_RADIUS I can set the tube radius, even if TUBES_DRAW is set to false (setting the TUBE_RADIUS seems to activate TUBE drawing).
But the attribute LINE_WIDTH, has no effect to the line width, at least not in the examlpe code from the first post. I can add ...

Code: Select all

appearance.setAttribute(CommonAttributes.LINE_WIDTH, 2.0);
... or ...

Code: Select all

appearance.setAttribute(CommonAttributes.LINE_WIDTH, 20.0);
... the line has always the same width. The appearnce seems not to be complete. Does it work if you run the code with an added LINE_WIDTH attribute?

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Thu 14. Aug 2008, 18:30

The implementation of the LINE_WIDTH attribute in the JOGL backend uses the OpenGL glLineWidth() function. This function is not continuous. That means as you increase the parameter, nothing happens until you reach a certain value, then the width of the line jumps a bit. It's what's called a step function. You can see the effect of the LINE_WIDTH parameter however if you add the following line to your code:

Code: Select all

appearance.setAttribute(CommonAttributes.LINE_WIDTH, 2.0); 
To better experiment with such parameters, I strongly recommend that you work with the standard ViewerApp application rather than creating your own frame, etc, since then you don't have the Navigator panel. In the navigator panel you can play with all these parameters interactively and see what their effect is without having to change your source code.

To do so: select the appearance in the scene graph component you've created, then select DefaultGeometryShader, then DefaultLineShader, and look at the parameters in the inspector at the bottom of the panel. (This is described also in the user tutorial , section 3, "Setting Appearance Attributes".)
jReality core developer

Joe
Posts: 61
Joined: Fri 11. Jul 2008, 19:29

Post by Joe » Tue 19. Aug 2008, 21:10

Currently I worked with the software renderer. I switched to the JOGL renderer and setting the LINE_WIDTH works as expected. But if the software renderer is used, it has no effect. Is this feature only implemented for the JOGL renderer, has it to be configured in another way for the software renderer or is it a bug?

It can be reproduced with the WebStart ViewerApp (thanks for the hot tip with the lineshader inspector).

Load a file, disable faces and points, set the line width to 1 and then switch between the JOGL and the software renderer. Then you will see what I mean.

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Tue 19. Aug 2008, 22:05

I've sent an e-mail to the author of the software renderer, asking him to clarify the situation with regard to the LINE_WIDTH attribute, asking him to post a reply on this topic.
jReality core developer

timh
Posts: 28
Joined: Wed 28. Jun 2006, 20:30
Contact:

Post by timh » Wed 20. Aug 2008, 06:51

Hi,

The software renderer does not support LINE_WIDTH (or POINT_SIZE) Attributes so far. At the moment lines and Points are allways rendered as (fake) tubes and spheres. If there is real need for them I can look into adding support for them (in fact I once had a minimal version of non-tubed lines running but I was not satisfied with the visual results).

best
Tim

Joe
Posts: 61
Joined: Fri 11. Jul 2008, 19:29

Post by Joe » Wed 20. Aug 2008, 08:05

The fake tubes explain the low performance of wireframe models (in software renderer mode).
For me it would be nice to have real lines and points of width and size 1. All other sizes won't be used (by me).

BTW: Thanks for this great free software

timh
Posts: 28
Joined: Wed 28. Jun 2006, 20:30
Contact:

Post by timh » Wed 20. Aug 2008, 09:21

If you need it for wire frame rendering it should be easy to make something for you. The main problems I had were triangles and lines competing in the z-buffer (one would usually like to have the lines allways on top of the corresponding triangles...).
I will look into it.

best
Tim

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Wed 20. Aug 2008, 14:30

Just to return briefly to the original question: if you want to adjust the thickness of lines in the software renderer (or in any backend when TUBES_DRAW is true), use the TUBE_RADIUS parameter, instead of the LINE_WIDTH one. You'll need to convert the parameter to be a distance in object coordinates (lineWidth is a distance in screen coordinates).
jReality core developer

Joe
Posts: 61
Joined: Fri 11. Jul 2008, 19:29

Post by Joe » Wed 20. Aug 2008, 19:55

I'll wait until the software renderer renders simple lines with width 1. But only for interest: How can the TUBE_RADIUS parameter be converted?

timh
Posts: 28
Joined: Wed 28. Jun 2006, 20:30
Contact:

Post by timh » Wed 27. Aug 2008, 07:26

I was on a conference for a couple of days. I do have some line rendering running now, but it still does not behave like the OpenGL counter part: the lines are still subject to perspective shrinking with distance. However I am not sure at the moment which behaviour is desirable in the end. Comments anyone?

best
Tim

User avatar
steffen
Posts: 186
Joined: Fri 16. Jun 2006, 13:30
Location: TU Berlin
Contact:

Post by steffen » Wed 27. Aug 2008, 18:48

How do these lines differ from the tubes exaclty and how do you determine the size?

timh
Posts: 28
Joined: Wed 28. Jun 2006, 20:30
Contact:

Post by timh » Fri 29. Aug 2008, 05:15

They were just thin rectangles in object space with a width that was computed from the lineWidth in screen coordinates, but:

I just checked in a version of the sofware viewer that supports un-tubed lines and "un-sphered" points of fixed width/size similar to OpenGL. No transparency for them at the moment (but this is not a principal problem - just not yet implemented). Unlike OpenGL the lineWidth (and pointSize) is not quantized (does the jogl backend is supposed to use the pointSize attribute? it does not work for me at the moment). Again as in OpenGL the lines and Points are not shaded. In principle one could shade them as rectangles facing the camera (since that is what they are after all) but since OpenGL does not do this, I think for now it is best to leave it like this.

I hope it works as expected (at least it should be considerably faster).
Tim

User avatar
gunn
Posts: 323
Joined: Thu 14. Dec 2006, 09:56
Location: TU Berlin
Contact:

Post by gunn » Mon 1. Sep 2008, 14:30

Regarding the use of POINT_SIZE in the JOGL backend: it works for me. In order to understand why there might be confusion about this, I'm including some more details about how the JOGL backend draws points.

When SPHERES_DRAW is false, the JOGL backend turns on the GL_POINT_SPRITE_ARB option and supplies a texture map of a shaded sphere to be used when rendering the points/sprites. By default the points are drawn in perspective, so they may not appear to be as large as you expect. I know it's confusing; we've been saying that when SPHERES_DRAW is true, the SPHERE_RADIUS is given in object space and the spheres are hence rendered in perspective; while when false, the POINT_SIZE is given in screen coordinates and therefore the points should not be in perspective. But OpenGL allows both; when SPHERES_DRAW is false, and you resize the window, the points do not get bigger, thus showing the dependence on screen coordinates. But more distant points will appear smaller. If you don't want the points to be in perspective, then turn off the attribute "attenuatePointSize" in the DefaultPointShader inspector. ( For more details on how the attenuation works, consult the OpenGL documentation on GL_POINT_SPRITE_ARB).

You can verify that the point sprites aren't really 3D shapes as follows: draw a cluster of overlapping points (with SPHERES_DRAW = false) and notice that any pair of sphere images don't actually intersect like real spheres would; for each pair, one is completely in front of the other, which makes sense, since they are actually texture-mapped quadrilaterals parallel to the viewing plane. So for high-quality images, you probably want to use SPHERES_DRAW = true; but you can get very fast, good performance that looks like spheres, with SPHERES_DRAW = false.

I hope that helps to explain how points are rendered in the JOGL backend. It's another topic that belongs in the tutorial and I intend to include it when I have time to do so.
jReality core developer

Post Reply