max123

World/local/ray

Recommended Posts

Hey, it's me and my bloody Rays again!

I went through a bunch of Babylon's classes, but just can't wrap my head around World vs Local vs BoundingBoxes vs Rays.
It looks like PickWithRay (and Mesh.intersects(Ray)) only work if meshes' positions are not changed! 

Here's the PG: http://www.babylonjs-playground.com/#1C86DD

Line 40 returns "true" even though the target mesh is outside Ray's path. It just hurts my brain!

Share this post


Link to post
Share on other sites

Hi Max,
as i see " Mesh.intersects " works in local-space. If you want to use this function you have to tranform the ray yourself.

You could do this with:
ray = BABYLON.Ray.Transform( ray, boxTarget.getWorldMatrix().clone().invert() );

But, maybe there is a better way to solve your problem. What are you trying to do?

Cheers,
Klaas

Share this post


Link to post
Share on other sites

Thanks dude!
I understand that primary function of Ray in babylon is for culling, but then maybe it would be more useful to hide its current implementation and instead create a Ray class that works in global space, which is way more useful in everyday scenarios? @Deltakosh, what do you think? You've implemented the multiple pick with ray after all :)

I'd do it myself (and change the way the current scene.pickWithRay works as I find the predicate thingy a bit clunky) and return an array of Picks ordered on pick-first basis or an empty array if no mesh is picked and do a PR... But my woeful lack of knowledge of trig precludes me from doing so.

 

 

Share this post


Link to post
Share on other sites

@Deltakosh, I think a lot of users will appreciate a little how-to of making the Ray work in World space. No matter what I try, it just doesn't work! 

Here's another little PG: http://www.babylonjs-playground.com/#ZHDBJ

And here's the code relevant to that PG:

box = BABYLON.Mesh.CreateBox("box1", .5, scene);
box.scaling.z = 3;
box.position.x = 3;

boxTarget = BABYLON.Mesh.CreateBox("box2", 1, scene);
boxTarget.scaling.x = 3;
boxTarget.position.x = 4;
boxTarget.position.z = 4;
boxTarget.computeWorldMatrix(true);

// If you comment this line out, the pickInfo will return .hit=true
box.lookAt(boxTarget.position);

var len = 10;

var rotVect = box._rotationQuaternion? box._rotationQuaternion.toEulerAngles(): box.rotation;
var rotationmatrix = BABYLON.Matrix.RotationYawPitchRoll(rotVect.y, rotVect.x, rotVect.z);
var vv = BABYLON.Vector3.TransformNormal( new BABYLON.Vector3(0, 0, len), rotationmatrix);

ray = new BABYLON.Ray(box.position, vv, len);
ray = BABYLON.Ray.Transform( ray, boxTarget.getWorldMatrix().clone().invert() );
           

var pi = boxTarget.intersects(ray, true);
console.log(pi.hit);

 

Share this post


Link to post
Share on other sites

@adam, one more thing: can you add multi-pick as well? I followed the same path as you did, but didn't have time to mess with gulp/PR/build as I don't use Visual Studio and the tuts on PRs/contributing do mention that you have to have VS.


Here's my PG: http://www.babylonjs-playground.com/#22C2OS#1
I've commented the part with multi-pick, lines 9-31.

Thanks again!

Share this post


Link to post
Share on other sites

Oh, nearly forgot: have a look at Ray.update() and Ray.show() - update is useful for reusing the drawn line :)

 R.prototype.show = function(scene, color) {
            var ps = [this.origin, this.origin.add(this.direction.scale(this.length))];
            this.rayLine = BABYLON.Mesh.CreateLines("rayLine", ps, scene, true);
            this.rayLine.color = color || new BABYLON.Color3(1,0,0);
        };

        R.prototype.update = function() {
            if (this.rayLine) this.rayLine = BABYLON.Mesh.CreateLines(null, [this.origin, this.origin.add(this.direction.scale(this.length))], null, null, this.rayLine);
        };

 

Share this post


Link to post
Share on other sites

@adam The mesh.getDirection() method is interesting on your last PG.

Is it a new feature of the version 2.5 ?

I see that it comes from a method with normals.

 

Is it the same result with my function local ?

function local(argMesh, argVec){

    var matrix = argMesh.getWorldMatrix();
    var vector = BABYLON.Vector3.TransformCoordinates(argVec, matrix);
    return vector;

}// local()

 

But i tried my local function with a forward vector on a dot product and it didnt give me the good result.

But this one gave me the good result :

var frontv = new BABYLON.Vector3( -Math.sin(box1.rotation.y), 0, -Math.cos(box1.rotation.y)  );

 

here is the complete process :

    var frontv = new BABYLON.Vector3( -Math.sin(box1.rotation.y), 0, -Math.cos(box1.rotation.y)  );
    frontv = frontv.normalize();
        
    var headingv = box2.position.subtract(box1.position);
    headingv = headingv.normalize();  
        
    var dotp = BABYLON.Vector3.Dot(headingv, frontv);

 

Share this post


Link to post
Share on other sites
23 minutes ago, getzel said:

Is it a new feature of the version 2.5 ?

yes

23 minutes ago, getzel said:

Is it the same result with my function local ?

function local(argMesh, argVec){

    var matrix = argMesh.getWorldMatrix();
    var vector = BABYLON.Vector3.TransformCoordinates(argVec, matrix);
    return vector;

}// local()

This function looks like it takes a local coordinate and makes it a world coordinate.

The getDirection function takes a local direction and rotates it to a world direction.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.