Jump to content

World/local/ray


max123
 Share

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!

Link to comment
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

Link to comment
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.

 

 

Link to comment
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);

 

Link to comment
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!

Link to comment
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);
        };

 

Link to comment
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);

 

Link to comment
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.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...