www.jpct.net

jPCT - a 3d engine for Java => Support => Topic started by: raft on December 26, 2009, 06:51:21 pm

Title: create a pyramide pointing some location
Post by: raft on December 26, 2009, 06:51:21 pm
hi,

i have two points: from and to. i want to create a pyramide so that, it's bottom center is placed at from and top corner is at to.

i'm using the following code but it doesnt correctly set direction. what's wrong here ?

Code: [Select]
public static Object3D createPyramide(SimpleVector from, SimpleVector to) {
SimpleVector direction = to.calcSub(from);
float length = direction.length();
Object3D p = Primitives.getPyramide(length);
// Pyramide is centered at origin, so move bottom to origin
p.translate(0, -length/2, 0);
p.setRotationMatrix(direction.getRotationMatrix());
p.translate(from);

return p;
}

thanks,
r a f t
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 26, 2009, 09:04:47 pm
Are you sure that the object created by Primitives is pointing in the right direction from the beginning (i.e. into the screen)? Apart from that, doing a separate translation before the rotation has no effect, because all transformations are applied at render time, not when you set them. If you want to rotate around a specific point, try setRotationPivot() instead.
Title: Re: create a pyramide pointing some location
Post by: raft on December 26, 2009, 10:22:37 pm
ah definetely pyramid points upwards initially. thanks :) i forgot using jPCT  ::)

here is the corrected code:
Code: [Select]
public static Object3D createPyramide(SimpleVector from, SimpleVector to) {
SimpleVector direction = to.calcSub(from);
float length = direction.length();
float scale = 3f;
Object3D p = Primitives.getPyramide(length/scale/2, scale);

// move pyramide such that it's bottom center is at origin
p.translate(0, -length/2, 0);
p.translateMesh();
p.getTranslationMatrix().setIdentity();

// make pyramid looking down to positive Z axis
p.rotateX((float)Math.PI/2);
p.rotateMesh();

// set direction
p.setRotationMatrix(direction.getRotationMatrix());

p.translate(from);

p.build();
// build modifies rotation pivot, so set it again
p.setRotationPivot(SimpleVector.ORIGIN);

return p;
}

EDIT:  corrected code sample for future reference (height of pyramide was incorrect)
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 26, 2009, 10:31:05 pm
i forgot using jPCT  ::)
How dare you... ;D
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 11:05:40 am
Code: [Select]
// set direction
p.setRotationMatrix(direction.getRotationMatrix());

this basicly works. center line of pyramide is oriented as i wish. i also update position/direction of pyramide (bone of skeleton indeed) later. it's directed correctly but -i guess- because of gimble lock thing, its orientation in its object space is not preserved especially while closer to y axis.

how can i overcome this ?

r a f t
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 31, 2009, 11:51:55 am
Do you have a screen shot? I don't really get the problem from the description alone... ???
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 12:27:41 pm
not a screenshot but a capture: http://www.aptalkarga.com/tmp/gimble.ogv
watch the bottom most pyramide. while approaching y axis, it rotates around itself
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 31, 2009, 01:05:47 pm
I see...that's because the getRotation()-method from SimpleVector actually is a lookAt()-implementation. It ensures that you "look at" some point in space but it doesn't make any assumptions about the rotation around the lookAt-axis. If you have two vectors, i.e. a direction vector and an up vector, you could do something like setOrientation in Camera:

Code: [Select]
public void setOrientation(SimpleVector dir, SimpleVector up )
    {
        // Code taken from paulcode's thread...only slightly modified.
SimpleVector right = up.calcCross(dir).normalize();
up=up.normalize();
dir=dir.normalize();
        Matrix m = this.backMatrix;
       
        m.set( 0, 0, right.x );
        m.set( 1, 0, right.y );
        m.set( 2, 0, right.z );
        m.set( 3, 0, 0.0f );
       
        m.set( 0, 1, up.x );
        m.set( 1, 1, up.y );
        m.set( 2, 1, up.z );
        m.set( 3, 1, 0.0f );
       
        m.set( 0, 2, dir.x );
        m.set( 1, 2, dir.y );
        m.set( 2, 2, dir.z );
        m.set( 3, 2, 0.0f );
       
        m.set( 0, 3, 0.0f );
        m.set( 1, 3, 0.0f );
        m.set( 2, 3, 0.0f );
        m.set( 3, 3, 1.0f );
    }

Is that an option in this case?
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 01:18:04 pm
possibly. i can use unit Y vector as up vector i guess.
so matrix would be object's rotation matrix and after calculations i will re-set it with Object3D.setRotationMatrix(m), right ?
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 01:34:02 pm
indeed this method seems to behave differently. see the below test case. both pyramides are suuposed to oriented same but that's not the case.
(http://img63.imageshack.us/img63/4663/85822664.png)

Code: [Select]
import java.awt.Color;

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;

public class Orient {


public static Object3D createPyramide(SimpleVector from, SimpleVector to) {
SimpleVector direction = to.calcSub(from);
float length = direction.length();
float scale = 3f;
Object3D p = Primitives.getPyramide(length/scale/2, scale);

// move pyramide such that it's bottom center is at origin
p.translate(0, -length/2, 0);
p.translateMesh();
p.getTranslationMatrix().setIdentity();

// make pyramid looking down to positive Z axis
p.rotateX((float)Math.PI/2);
p.rotateMesh();

// set direction
p.setRotationMatrix(direction.getRotationMatrix());

p.translate(from);

p.build();
// build modifies rotation pivot, so set it again
p.setRotationPivot(SimpleVector.ORIGIN);

return p;
}

public static void setOrientation(Object3D o, SimpleVector dir, SimpleVector up)     {
        // Code taken from paulcode's thread...only slightly modified.
SimpleVector right = up.calcCross(dir).normalize();
up=up.normalize();
dir=dir.normalize();
        Matrix m = o.getRotationMatrix();
       
        m.set( 0, 0, right.x );
        m.set( 1, 0, right.y );
        m.set( 2, 0, right.z );
        m.set( 3, 0, 0.0f );
       
        m.set( 0, 1, up.x );
        m.set( 1, 1, up.y );
        m.set( 2, 1, up.z );
        m.set( 3, 1, 0.0f );
       
        m.set( 0, 2, dir.x );
        m.set( 1, 2, dir.y );
        m.set( 2, 2, dir.z );
        m.set( 3, 2, 0.0f );
       
        m.set( 0, 3, 0.0f );
        m.set( 1, 3, 0.0f );
        m.set( 2, 3, 0.0f );
        m.set( 3, 3, 1.0f );
       
        o.setRotationMatrix(m);
    }

public static void main(String[] args) throws Exception {
World world = new World();
world.setAmbientLight(200, 200, 200);

SimpleVector endPoint = new SimpleVector(50, -50, 0);

Object3D bone1 = createPyramide(SimpleVector.ORIGIN, endPoint);
Object3D bone2 = createPyramide(SimpleVector.ORIGIN, endPoint);

bone1.translate(-20, 0, 0);
bone2.translate(20, 0, 0);

world.addObject(bone1);
world.addObject(bone2);

setOrientation(bone2, endPoint, new SimpleVector(0, -1, 0));

Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 200);

FrameBuffer fb = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_NORMAL);
fb.disableRenderer(IRenderer.RENDERER_SOFTWARE);
fb.enableRenderer(IRenderer.RENDERER_OPENGL);

while (!org.lwjgl.opengl.Display.isCloseRequested()) {
fb.clear();
world.renderScene(fb);
world.draw(fb);
world.drawWireframe(fb, Color.WHITE);

fb.update();
fb.displayGLOnly();
Thread.sleep(10);
}
fb.disableRenderer(IRenderer.RENDERER_OPENGL);
fb.dispose();
System.exit(0);
}
}
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 31, 2009, 03:29:48 pm
My bad...that's most likely because that method is for the camera, which actually is an inverted rotation matrix when viewed from an object's perspective. I've added the setOrientation()-method to Object3D and Matrix as well and i hope that this version works better. Please give it a try: http://www.jpct.net/download/beta/jpct.jar (http://www.jpct.net/download/beta/jpct.jar)
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 03:42:00 pm
thanks. i would just suggest to add such methods :)

but still not solved exactly. now bones becomes flat around y axis. here is the capture:
http://www.aptalkarga.com/tmp/gimble2.ogv
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 31, 2009, 03:59:59 pm
Looks like as if your direction and up vectors are not really perpendicular...

BTW: What are you using to create your screen captures?
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 04:09:40 pm
should they be perpendicular ::) i was using (0,-1,0) as up vector regardless of direction. then how should i calculate a perpendicular up vector ?
Ardor3d's Matrix3 has a similar lookAt method. looking at its bone drawing examples,  always unit y vector is passed as up vector

i'm using gtk-RecordMyDesktop. this is a ubuntu box :)
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 31, 2009, 04:38:04 pm
Yes, when working with direction and up vectors, they have to be perpendicular. Isn't there some matrix assigned to a join that can provide this vector? That would be useful anyway to visualize a rotation around the direction vector (or isn't that possible?).

The up-vector for jPCT's lookAt-methods (and similar) is implicitly set to (0,1,0)...so actually, the behaviour should be similar unless their lookAt works differently.
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 04:45:36 pm
mm, i need to investigate it further..

their look at method is something like:

Code: [Select]
       
        direction.normalize(zAxis); // stores normalized in zAxis
        up.normalize(xAxis).crossLocal(zAxis);
        zAxis.cross(xAxis, yAxis);

        fromAxes(xAxis, yAxis, zAxis);
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 31, 2009, 05:30:22 pm
The algorithm looks the same. However, i've updated the beta-jar with a version that offers a new getRotationMatrix(<SimpleVector>)-method in SimpleVector that takes an additional up-vector. Maybe trying that with an actual jPCTish up vector (0, -1, 0) shows different/better results.
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 05:47:14 pm
this new getRotationMatrix(0,-1,0) method bahaves exactly the same as no arg one for this case.
thanks. i'll look for a reliable up vector
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 06:28:15 pm
and here is a skinned capture rendered in jPCT ;D
www.aptalkarga.com/tmp/seymour.ogv

edit: updated the link with a more correct version (bones weren't rendered correctly)
Title: Re: create a pyramide pointing some location
Post by: EgonOlsen on December 31, 2009, 07:06:18 pm
Very nice.  Is the skeletal animation system also an Ardor port or are you using the loader only?
Title: Re: create a pyramide pointing some location
Post by: raft on December 31, 2009, 07:18:39 pm
indeed all is Ardor's at the moment. except, at the very last stage, ardor's matrix is converted into jPCT's and used in IVertexController.
i'm planning to convert all data to jPCT at load time allowing to be serialized standalone and later reloaded without Ardor