How I can rotate pc.VEC3 of the entity?

hello guys,

I am trying to figure out if I can rotate pc.VEC 3 of the entity. If the entity is in front like normal, the screenToWorld works good. Here is some pictures:

As you can see, when i throw forward or to sides, the ball corectlly follow the x positions.

But if I tween the ground with the camera to left or right side, when I throw the ball, that shoot in wrong way.
Here is pictures:
SIde Left:

Side right:

As you can see now, the ball follow wrong direction of X position. Here is the code:

BallMovement.prototype.onMouseMove = function(event){
  
    
    // console.log("Y: ",event.y, "X: ", event.x);
    if(this.isMousePressed ) {
    var context = this;
    var canTeleport = true;

    var cameraEntity = this.app.root.findByName('Camera');    
        
        this.pos = new pc.Vec3();
        this.pos2 = new pc.Vec3();
        this.pos3 = new pc.Vec3();
        
  //this.counterMouse();
  
 
   
    
        
    
         if(CameraCollision.changePositions ==1 && this.isBallClicked && canTeleport) {
             
                   var depth = 7.1;
                   cameraEntity.camera.screenToWorld(event.x , event.y ,depth, this.pos);
         
        
                   this.ball.setLocalPosition(this.pos.x, this.pos.y, this.ball.getLocalPosition().z);

         }

        
        else if(CameraCollision.changePositions == 2 && this.isBallClicked && canTeleport) {
            
               var depth2 = 7.1;
           
               cameraEntity.camera.screenToWorld(event.x  , event.y,depth2, this.pos2);
      
       
              this.ball.setLocalPosition(this.pos2.x   , this.pos2.y  , this.ball.getLocalPosition().z);

        }

         else if(CameraCollision.changePositions ==3 && this.isBallClicked && canTeleport) {
              var depth3 =7.1;
             
            cameraEntity.camera.screenToWorld(event.x  , event.y ,depth3, this.pos3);
       
             this.ball.setLocalPosition(this.pos3.x , this.pos3.y  , this.ball.getLocalPosition().z);
          

        }
        this.screenCheckY = event.y;
        

    }
   
        
};

I tried to rotate the ball after teleport, but not working. Also i tried multiply and divide the event.x on change position 2, which is right possition, and change possition 3, which is left possition. Like there:

  
        else if(CameraCollision.changePositions == 2 && this.isBallClicked && canTeleport) {
            var depth2 = 7.1;
           
           cameraEntity.camera.screenToWorld(event.x /1.2  , event.y,depth2, this.pos2);
      
         
              this.ball.setLocalPosition(this.pos2.x   , this.pos2.y  , this.ball.getLocalPosition().z);

 }

        
         else if(CameraCollision.changePositions ==3 && this.isBallClicked && canTeleport) {
              var depth3 =7.1;
             
            cameraEntity.camera.screenToWorld(event.x *1.1  , event.y ,depth3, this.pos3);
       
             this.ball.setLocalPosition(this.pos3.x , this.pos3.y  , this.ball.getLocalPosition().z);
              
            }

Its working, but just on one resolution, and I need to fix it and change this numbers on every resolution, which is not good and not working correctly.

I think, that i need rotate the Balls pc.Vec3, but I dont know if is there some option for that.

If you have some solution for that, please share with me.
Thank you.

Hi @RogerDat,

You did your best to describe your problem, much appreciated. Though still it’s a complex problem, I am finding it difficult to follow up out of context.

Is it possible to share a sample project that reproduces the issue to play with?

2 Likes

I Can create a Sample project. But i Can Also give you acess to this project for a little bit to look for the problem, cause its just like a prototype of the game. But my code is maybe little bit amateur, cause i am new in playcanvas and coding as Well. But what you preffer? Sample project or access to this project?

Big thanks for you guys for helping users.

Sample project would be best

2 Likes

OK i create sample project with that issue.

Here is the link:

https://playcanvas.com/project/850799/overview/sample-ball

How do you reproduce the issue?

Problem is, that if you throw the ball forward in first, default position, its will throw forward which is good. But when the position will tween to sides, if you throw the ball forward to hoop, the ball will be throw to side, not directly front. So ball must follow the arrow of the mouse, the X position, but on sides thats not working correctly.

How do you move to the side?

Moving to side is from tween. Specifically i am tweening ground and camera after randomly setting number from 1 to 3 , where 1 IS default position (front), and 2 is right side and 3 is leftside. i am tweening position and rotation of the ground and camera. Than the ball will teleported to positions from 1 to 3.

As in, what key/button do I have to press in the game to move to the side?

No. Its miss understanding. You throw the ball and than after ball reach position y -5 then randomly ground tween to 2 orb3 (which is right and left side) or stay in 1 position, which si in front. Its working for you? Cause It seems like something doesnt work.

I see the issue:

 this.entity.rigidbody.applyImpulse(this.pos.x, pc.math.random(6.8,7), - 5);

The game is always apply an impulse in the world Z axis so it always flys in the same direction in world space.

It needs to be changed so that the impulse is done in the direction of the camera local Z axis, not the world.

Here is the corrected code:

BallMovement.prototype.onMouseUp = function (event) {
    //this.ball.setLocalPosition(0, 0.712, -3.919);
    this.entity.rigidbody.type = pc.BODYTYPE_DYNAMIC;

    this.isMousePressed = false;

    var cameraEntity = this.app.root.findByName('Camera');
    var impulse = cameraEntity.forward.clone();

    // Flatten the forward vector so that it is on the XZ  world plane
    // and normalize it so it is of unit size
    impulse.y = 0;
    impulse.normalize();

    // Times it by 5 to fire it forward as it was before
    impulse.mulScalar(5);

    // Give it a random Y impulse as it was before
    impulse.y = pc.math.random(6.8, 7);

    this.shotBall();
    this.entity.rigidbody.applyImpulse(impulse);
};

Example project: https://playcanvas.com/editor/scene/1273697

To do the left/right adjustment is a bit tricker as you can’t use screenToWorld x value as you are at the moment because you are getting world space coordinations rather than screen space.

What you will need to do is to get the mouse position on the screen, how far it is from middle and use that value instead.

Or do a screenToWorld but the Z distance would be as far as the ball is from the camera along the XZ place and get the distance from the screenToWorld position to the ball.

Hello, i am little bit Late but anyway,

How Can I get mouse position from the screen? I think that i have to use mousemove event, or on mouseend event? When I click end on the screen, than i consoling event.x and event.y right? And than how Can i transform this numbers to impulse?

Hi @RogerDat,

Check this example on how to convert a mouse click on world coordinates, to be used for positioning an entity:

https://developer.playcanvas.com/en/tutorials/point-and-click-movement/

1 Like

Hello,

Sorry, but i really dont know how to figure it out.
I think, that in correct code, which yaustar gives me, i am setting Z position depends on camera, and its working well. I need to set X position depends on camera also? Like in my code in sample project, i am using screenToWorld in ray cast, also in Mouse move. But I dont know really how to put, or convert, this screen X to world X, or on second option I have to find out distance between camera and ball along the XZ place. But I am really dont know how to do that. If you can tell me this more specifically or give me some more help, I will be really thankfull.

Thanks.

Hello,

I figure it out, how can I get distance between camera and ball in RayCast function.

Here is the code:

BallMovement.prototype.doRaycast = function (screenX, screenY) {
    // The pc.Vec3 to raycast from (the position of the camera)
     
  
    
    var from = this.camera.getPosition();

    // The pc.Vec3 to raycast to (the click position projected onto the camera's far clip plane)
    var to = this.camera.camera.screenToWorld(screenX, screenY, this.camera.camera.farClip, BallMovement.ray);
    
    var r = new pc.Vec3();

    var ballPosition = this.entity.getLocalPosition();

    r.sub2(from,ballPosition);

    console.log('R is' + r);


    // Raycast between the two points and return the closest hit result
    var result = this.app.systems.rigidbody.raycastFirst(from, to);
          
    // If there was a hit, store the entity
    if (result && this.allowRaycast) {
        var hitEntity = result.entity;
       
        if(hitEntity.name === 'Ball'){
           
        
            this.isBallClicked = true;
            this.ball.rigidbody.type = pc.BODYTYPE_KINEMATIC;
           
        }
    }  
    
     
};

And R output is like [1.5111753940582275, 1.155427634716034, 3.2431135773658752]. It depends on where is the ball, on tween Position 1,2, or 3.
But how is next step? How can I calculate this into impulse?

I wouldn’t be using raycasting at all for this TBH.

I would base the impulse depending on the gesture in screen space. The starting point of the gesture is known in screen space (X, Y). From that, it is straightforward to know how far it has moved on the X and Y axis of the screen.

I would probably normalise the difference using the screen dimensions.

Using the X and Y movement of the finger on the screen, I would base impulse on that.