create a pyramide pointing some location

Started by raft, December 26, 2009, 06:51:21 PM

Previous topic - Next topic

raft

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 ?

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

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

#2
ah definetely pyramid points upwards initially. thanks :) i forgot using jPCT  ::)

here is the corrected code:
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)


raft

// 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

EgonOlsen

Do you have a screen shot? I don't really get the problem from the description alone... ???

raft

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

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:


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

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

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.


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

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

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

Looks like as if your direction and up vectors are not really perpendicular...

BTW: What are you using to create your screen captures?

raft

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 :)

EgonOlsen

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.