### Author Topic: create a pyramide pointing some location  (Read 7417 times)

#### raft

• Posts: 1991
##### create a pyramide pointing some location
« 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

#### EgonOlsen

• Posts: 12065
##### Re: create a pyramide pointing some location
« Reply #1 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.

#### raft

• Posts: 1991
##### Re: create a pyramide pointing some location
« Reply #2 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)
« Last Edit: December 27, 2009, 01:13:58 pm by raft »

#### EgonOlsen

• Posts: 12065
##### Re: create a pyramide pointing some location
« Reply #3 on: December 26, 2009, 10:31:05 pm »
i forgot using jPCT
How dare you...

#### raft

• Posts: 1991
##### Re: create a pyramide pointing some location
« Reply #4 on: December 31, 2009, 11:05:40 am »
Code: [Select]
`// set directionp.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

#### EgonOlsen

• Posts: 12065
##### Re: create a pyramide pointing some location
« Reply #5 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...

#### raft

• Posts: 1991
##### Re: create a pyramide pointing some location
« Reply #6 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

#### EgonOlsen

• Posts: 12065
##### Re: create a pyramide pointing some location
« Reply #7 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?

#### raft

• Posts: 1991
##### Re: create a pyramide pointing some location
« Reply #8 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 ?

#### raft

• Posts: 1991
##### Re: create a pyramide pointing some location
« Reply #9 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.

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); }}`

#### EgonOlsen

• Posts: 12065
##### Re: create a pyramide pointing some location
« Reply #10 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

#### raft

• Posts: 1991
##### Re: create a pyramide pointing some location
« Reply #11 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

#### EgonOlsen

• Posts: 12065
##### Re: create a pyramide pointing some location
« Reply #12 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?

#### raft

• Posts: 1991
##### Re: create a pyramide pointing some location
« Reply #13 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