Author Topic: PickPolygon reporting nothing  (Read 7408 times)

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« on: February 08, 2007, 10:51:37 pm »
I am getting nothing from pickPolygon in some circumstances.

In the render loop, I try it just after the scene is rendered/drawn/displayed to framebuffer. It works!

Still inside render loop, but before rendering, I very rarely get anything from it.

I do use multiple cameras, and multiple framebuffers.
I am certain it is because of this.
I have tried setting the world to the active camera, and even rendering the scene again, before pickPolygon, but no luck:)

Just incase it is obvious to someone..
Code: [Select]

public synchronized Object3D getObjectAtCursor(int x,int y,RenderPane renderPane)
{
Camera      camera      = renderPane.camera;
FrameBuffer frameBuffer = renderPane.frameBuffer;


world.setCameraTo(camera);
world.renderScene(frameBuffer);
//world.draw(frameBuffer);

SimpleVector td  = Interact2D.reproject2D3D(camera,frameBuffer,x,y);
int[]        res = Interact2D.pickPolygon(
world.getVisibilityList(),td,
Interact2D.EXCLUDE_NOT_SELECTABLE);
if (res == null)
return null;
//Never gets past here,outside of paintComponent().

Object3D obj = world.getObject(Interact2D.getObjectID(res));

return obj;
}
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
PickPolygon reporting nothing
« Reply #1 on: February 08, 2007, 11:47:00 pm »
You need a valid VisLIst for using pickPolygon, i.e. one that represents the currently visible frame. If you do the picking in thread a and the drawing (i.e. the implicit creation of the VisList) in thread b (aka in paintComponent), you'll get random results depending on the current state of the VisList, which can be anything between empty and full. Could that  be the problem here?

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« Reply #2 on: February 09, 2007, 12:13:52 am »
Yes, indeed.

I use the repaint() method to suggest the components to be painted!

How could I avoid this issue?
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
PickPolygon reporting nothing
« Reply #3 on: February 09, 2007, 12:17:57 am »
Maybe by letting the repaint-thread store the current VisList so that the other thread can access it (in a synchronized way)?

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« Reply #4 on: February 09, 2007, 12:21:48 am »
I tried adding a System.out.println(visList.isValid()) to the above code.

This is the result...

Code: [Select]

Java version is: 1.5.0_08
-> support for BufferedImage
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Software renderer disposed
Software renderer (OpenGL mode) initialized
Java version is: 1.5.0_08
-> support for BufferedImage
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Software renderer disposed
Software renderer (OpenGL mode) initialized
Java version is: 1.5.0_08
-> support for BufferedImage
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Software renderer disposed
Software renderer (OpenGL mode) initialized
Java version is: 1.5.0_08
-> support for BufferedImage
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Software renderer disposed
Software renderer (OpenGL mode) initialized
Additional visibility list (1) created with size: 4096
Additional visibility list (2) created with size: 4096
Additional visibility list (3) created with size: 4096
Loading file from InputStream
File from InputStream loaded...28766 bytes
Processing new material Material.004!
Processing new material Material.006!
Processing object from 3DS-file: Plane
Object 'Plane_jPCT0' created using 624 polygons and 321 vertices.
Object Merged..
Model Loaded..
New Bone!
Exception in thread "Thread-1" java.lang.StackOverflowError
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)
at com.threed.jpct.VisList.isValid(Unknown Source)

http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« Reply #5 on: February 09, 2007, 12:25:48 am »
Quote from: "EgonOlsen"
Maybe by letting the repaint-thread store the current VisList so that the other thread can access it (in a synchronized way)?


I've tried simply neglecting to paint anything(if(true)return;), but still no difference.

I only have one thread running, which is a render loop.

Code: [Select]

public class RenderLoop extends Thread
{
protected RenderPane[] renderPanes;

public RenderLoop(RenderPane[] renderPanes)
{
this.renderPanes = renderPanes;

start();
}

public void run()
{
boolean refreshUnselected = false;
long timestamp = 0;
EditorPane editorPane = EditorPane.getInstance();
for(; ;)
{
//Update the editor pane - allow it to handle input.
editorPane.update();

long currentTime = System.currentTimeMillis();
if(timestamp <= currentTime - 500)
{
refreshUnselected = true;
timestamp = currentTime;
}else
refreshUnselected = false;

//Render the panes.
for(RenderPane r : renderPanes)
{
if(r == editorPane.getSelectedRenderPane() || refreshUnselected)
r.repaint();
}
Thread.yield();
}
}


Even after disabling this, the problem persists.
Could this problem be caused in some other way?
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
PickPolygon reporting nothing
« Reply #6 on: February 09, 2007, 01:02:53 am »
Forget about VisList.isValid()...i mean, have a look at the implementation of this method: :oops:

Code: [Select]

public boolean isValid() {
   return isValid();
}


VisList-management got so complicated, that giving this method back its real purpose is pointless. I'll remove it from the next version.
You are right...my idea won't work, because storing the VisList doesn't prevent it from being updated by another thread. The only solution i can think of is to do the picking right after the renderScene in the same thread, i.e. in the paintComponent(). Or are you already doing this? It's still not clear to me, which thread does what in your application and which one calls the getObjectAtCursor()-method!?

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« Reply #7 on: February 09, 2007, 01:15:29 am »
Hehe, that would explain the overflow;).

Well, I have ONE thread. The render loop above.

There are FOUR "renderPanes"(JComponents) which are repainted.

In the loop above, it calls an update method - does the pickPolygon.

Then, it loops through the components, suggesting a repaint with, well, repaint();).

The other stuff is just to make the selected component draw fast, and the others to only update every 200ms, for performance reasons;)

So, they are all in the same thread. Now, I know, im only suggesting a repaint, so it means the actual repaint is on the event dispatcher thread.
I have disabled painting anything at all.

The problem persists.
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
PickPolygon reporting nothing
« Reply #8 on: February 09, 2007, 01:27:14 am »
Ok, got that. So the problem is now, that it works when doing it after the world.renderScene(frameBuffer); and that it doesn't work when doing it before?

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« Reply #9 on: February 09, 2007, 01:31:00 am »
It doesnt work if I include renderScene in the method, as pasted.

However, the code inside the painting loop is essentially the same.
There is some camera movements, but nothing else really.

Its not highly optimised, but thats not important...
Code: [Select]

public synchronized void paintComponent(Graphics g)
{
Object3D model = editorPane.model;

float radianRotX = editorPane.cameraRotationX;
float radianRotY = editorPane.cameraRotationY;

RenderFactory renderFactory = RenderFactory.defaultInstance;

renderFactory.drawBackground(this);


if(model != null)
{
if(viewMode == VIEW_NORMAL)
{
renderFactory.moveCameraAroundModel(
model,radianRotX, radianRotY,
       editorPane.cameraZoom,
       editorPane.cameraPanX,
       editorPane.cameraPanY,this);
}
else if(viewMode == VIEW_SIDE)
{
renderFactory.moveCameraToSide(editorPane.cameraZoom,editorPane.cameraPanX,
       editorPane.cameraPanY,this);
}
else if(viewMode == VIEW_TOP)
{
renderFactory.moveCameraToTop(editorPane.cameraZoom,editorPane.cameraPanX,
       editorPane.cameraPanY,this);
}
else if(viewMode == VIEW_REAR)
{
renderFactory.moveCameraToRear(editorPane.cameraZoom,editorPane.cameraPanX,
       editorPane.cameraPanY,this);
}
}
renderFactory.world.setCameraTo(camera);
renderFrame();
displayFrame(g);

if(model != null)
renderFactory.drawNearestVertex(g,this);

renderFactory.drawSkeleton(g,this);
renderFactory.draw3DCursor(g,this);
//renderFactory.getObjectAtCursor(mouseMapper.getMouseX(),
// mouseMapper.getMouseY(),this);

}

/**
* Renders the model onto the framebuffer.
*/
public void renderFrame()
{
World world = RenderFactory.defaultInstance.getWorld();
//frameBuffer.clear(Color.black);

frameBuffer.clearZBufferOnly();

world.renderScene(frameBuffer);

//world.draw(frameBuffer);
world.drawWireframe(frameBuffer, Color.GRAY);

frameBuffer.update();
    }
/**
* Draws the framebuffer to the graphics context.
*
* @param g graphics context.
*/
public void displayFrame(Graphics g)
{
frameBuffer.display(g);
}


Its worth mentioning that the method...
Code: [Select]

   if(model != null)
         renderFactory.drawNearestVertex(g,this);

...above, has the same pickPolygon function in, and it works fine - after render, of course:).
Taking it out makes no difference.
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« Reply #10 on: February 09, 2007, 01:34:06 am »
Code: [Select]

/**
* Moves the camera around a 3d object.
* This method accepts x,y orbiting rotation, a zoom level,
* and a panning coordinate.
*
* @param model model to point camera at
* @param x x rotation
* @param y y rotation
* @param zoom zoom level
* @param mx x panning offset
* @param my y panning offset
*/
public void moveCameraAroundModel(Object3D model,float x, float y,float zoom,float mx,float my,RenderPane renderPane)
{
Camera camera = renderPane.camera;

   SimpleVector center = model.getTransformedCenter();
   
   SimpleVector oldCamPos    = camera.getPosition();
   SimpleVector oldestCamPos = new SimpleVector(oldCamPos);
   oldCamPos.scalarMul(4f);

   SimpleVector camPos  = new SimpleVector(center);
   
   
   Matrix cameraRotation = model.getRotationMatrix().cloneMatrix();
   cameraRotation.rotateX(x);
   cameraRotation.rotateY(y);
   
   
   SimpleVector zOffset = cameraRotation.getZAxis();
   zOffset.scalarMul(zoom);
   
   camPos.add(zOffset);
   

   camPos.add(oldCamPos);
   camPos.scalarMul(0.2f);

   SimpleVector delta = camPos.calcSub(oldestCamPos);
   float len = delta.length();

   if (len != 0)
    camera.moveCamera(delta.normalize(), len);
   center.add(new SimpleVector(mx,my,0));
   camera.lookAt(center);
   
  // camera.moveCamera(new SimpleVector(mx,my,0), 1f);
}
public void moveCameraToSide(float zoom,float mx,float my,RenderPane renderPane)
{
Camera camera = renderPane.camera;
SimpleVector center = EditorPane.defaultInstance.model.getTransformedCenter();
camera.setPosition(center);
camera.moveCamera(new SimpleVector(zoom,0,0),1f);
camera.lookAt(center);
//camera.moveCamera(new SimpleVector(0,mx,my),1f);
}
public void moveCameraToTop(float zoom,float mx,float my,RenderPane renderPane)
{
Camera camera = renderPane.camera;
SimpleVector center = EditorPane.defaultInstance.model.getTransformedCenter();
camera.setPosition(center);
camera.moveCamera(new SimpleVector(0,zoom,0),1f);
camera.lookAt(center);
//camera.moveCamera(new SimpleVector(mx,0,my),1f);
}
public void moveCameraToRear(float zoom,float mx,float my,RenderPane renderPane)
{
Camera camera = renderPane.camera;
SimpleVector center = EditorPane.defaultInstance.model.getTransformedCenter();
camera.setPosition(center);
camera.moveCamera(new SimpleVector(0,0,zoom),1f);
camera.lookAt(center);
//camera.moveCamera(new SimpleVector(mx,my,0),1f);
}
/**
* Draws a small rectangle other the vertex closest to the
* mouse cursor.
*
* @param g
* @param renderPane
*/
public void drawNearestVertex(Graphics g,RenderPane renderPane)
{
MouseMapper mouseMapper = renderPane.mouseMapper;
SimpleVector vect = getClosestVertex(
mouseMapper.getMouseX(),
mouseMapper.getMouseY(),
renderPane);
if(vect == null)
return;

SimpleVector vect2D = Interact2D.project3D2D(
world.getCamera(),renderPane.frameBuffer,vect);

if(vect2D == null)
return;

g.setColor(Color.green);
g.fillRect((int)vect2D.x-2, (int)vect2D.y-2, 4,4);
}


Code: [Select]

/**
* Draws the 3d cursor into place on a graphics context.
*
* @param g
* @param frameBuffer
*/
public void draw3DCursor(Graphics g,RenderPane renderPane)
{
SimpleVector vect = EditorPane.defaultInstance.cursor3D;
SimpleVector vect2 = EditorPane.defaultInstance.cursor3D2;
if(vect == null || vect2 == null)
return;

Camera      camera      = renderPane.camera;
FrameBuffer frameBuffer = renderPane.frameBuffer;



SimpleVector vect2D = Interact2D.project3D2D(camera,frameBuffer,vect);
SimpleVector vect2D2 = Interact2D.project3D2D(camera,frameBuffer,vect2);

if(vect2D == null || vect2D2 == null)
return;

g.setColor(Color.white);
g.drawRect((int)vect2D.x-2, (int)vect2D.y-2, 4,4);
g.drawRect((int)vect2D.x-4, (int)vect2D.y-4, 8,8);

MouseMapper mouseMapper = renderPane.mouseMapper;
int mouseX = mouseMapper.getMouseX();
int mouseY = mouseMapper.getMouseY();

g.drawLine(mouseX,mouseY, (int)vect2D2.x, (int)vect2D2.y);
g.drawRect((int)vect2D2.x-4, (int)vect2D2.y-4, 8,8);




}


Code: [Select]

/**
* Draws the bone structure of the skeleton onto
* a graphics context.
*
* @param g
*/
public void drawSkeleton(Graphics g,RenderPane renderPane)
{
SimpleSkeleton skeleton = EditorPane.defaultInstance.skeleton;

if(skeleton == null)
return;

List<SimpleBone> bones  = skeleton.getBones();

drawBones(g,bones,renderPane);
}
private void drawBones(Graphics g,List<SimpleBone> bones,RenderPane renderPane)
{
for(SimpleBone bone : bones)
{
drawBone(g,bone,renderPane);
drawBones(g,bone.getChildren(),renderPane);
}
}
/**
* Draws a single bone, using the pivot, and
* end point vectors.
*
* @param g
* @param bone
*/
Color color = new Color(0x4d,0xef,0x92);
private void drawBone(Graphics g,SimpleBone bone,RenderPane renderPane)
{
Graphics2D g2 = (Graphics2D)g;

Stroke strokeOld = g2.getStroke();

g2.setStroke(new BasicStroke(5.0f,                     // Line width
                BasicStroke.CAP_ROUND,    // End-cap style
                BasicStroke.JOIN_ROUND)); // Vertex join style

g2.setColor(color);

Camera      camera      = renderPane.camera;
FrameBuffer frameBuffer = renderPane.frameBuffer;


SimpleVector pivot2D    = Interact2D.project3D2D(camera,frameBuffer,bone.getPivot());
SimpleVector endPoint2D = Interact2D.project3D2D(camera,frameBuffer,bone.getEndPoint());

if(pivot2D == null || endPoint2D == null)
return;

g.drawLine((int)pivot2D.x,(int)pivot2D.y,(int)endPoint2D.x,(int)endPoint2D.y);

if(((Bone)bone).endPointSelected())
g2.setColor(Color.orange);
else
g2.setColor(Color.gray);

g2.drawOval((int)endPoint2D.x-6,(int)endPoint2D.y-6, 11, 11);

if(bone.isRoot()){
if(((Bone)bone).pivotSelected() )
g2.setColor(Color.orange);
else
g2.setColor(Color.gray);

g2.drawOval((int)pivot2D.x-6,(int)pivot2D.y-6, 11, 11);
}
g2.setStroke(strokeOld);
}
/**
* Draws a background onto the framebuffer of a renderpane.
*
* @param renderFactory
*/
public void drawBackground(RenderPane renderPane)
{
FrameBuffer frameBuffer = renderPane.frameBuffer;
int width  = frameBuffer.getOutputWidth();
int height = frameBuffer.getOutputHeight();

Graphics g = frameBuffer.getGraphics();

//Draw base colour.
if(EditorPane.defaultInstance.selectedRenderPane == renderPane)
g.setColor(new Color(0x00,0x25,0x0a));
else
g.setColor(new Color(0x00,0x14,0x09));

g.fillRect(0,0,width,height);

g.setColor(new Color(0x00,0x35,0x0e));
//Draw the vertical lines.
int i = 0,num = (width / 32) + 1;
while(i<num)
{
g.drawLine(i * 32,0, i * 32,height);

i++;
}
//Draw the horizontal lines.
i = 0; num = (height / 32) + 1;
while(i<num)
{
g.drawLine(0,i * 32, width,i * 32);

i++;
}

//Draw origin crosshair
g.setColor(Color.GRAY);
g.drawLine(width/2, height/2-5, width/2, height/2+5);
g.drawLine(width/2-5, height/2, width/2+5, height/2);


}


Thats everything:)
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
PickPolygon reporting nothing
« Reply #11 on: February 09, 2007, 01:17:25 pm »
Have you done a setSelectable(Object3D.MOUSE_SELECTABLE); on these objects?

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« Reply #12 on: February 09, 2007, 01:23:40 pm »
Yes, and it all works, but only in paintComponent
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
PickPolygon reporting nothing
« Reply #13 on: February 09, 2007, 01:49:02 pm »
Good...at least i'm coming close to understand the actual problem now... :wink: Another question: paintComponent() and getObjectAtCursor() are part of the same class?

Offline cyberkilla

  • float
  • ****
  • Posts: 413
    • View Profile
    • http://futurerp.net
PickPolygon reporting nothing
« Reply #14 on: February 09, 2007, 01:56:34 pm »
No...

getObjectAtCursor() is in RenderFactory.
and
paintComponent() is in RenderPane.
http://futurerp.net - Text Based MMORPG
http://beta.rpwar.com - 3D Isometric MMORPG