I am currently working on a tennis game in 3D with unity. When the user hits the ball, say at x=0,y=5,z=0 with velocity at certain position, say z=10, what's the ball x and y coordinate after reaching z=10?
To obtain the ball's velocity, you have to use the ball's RigidBody.
If your script is attached as a component of your ball, you would access it through rigidbody.velocity.magnitude.
Although Heilo's approach would work perfectly, i stress the idea of getting a direct velocity measure, e.g. Distance/Time, time being the frame during an Update in the Update() method.
This is actually very simple to do...
Just get the distance it's traveled between two update functions like so:
var previousPosition : Vector3;
function Update() {
//Get the difference/distance between the previous position and the current position
var velocity = Vector3.Distance(previousPosition, transform.position);
}
Because im doing this over a single frame, there is no need to compute extra math to get the velocity. However, if you wish to do it over second, you'll need to get the FPS for the game and do some math with that.. So i suggest that unless you want to use this direct route, use what Heilo suggests.
Related
I'm currently attempting to create a first-person space flight camera.
First, allow me to define what I mean by that.
Notice that I am currently using Row-Major matrices in my math library (meaning, the basis vectors in my 4x4 matrices are laid out in rows, and the affine translation part is in the fourth row). Hopefully this helps clarify the order in which I multiply my matrices.
What I have so Far
So far, I have successfully implemented a simple first-person camera view. The code for this is as follows:
fn fps_camera(&mut self) -> beagle_math::Mat4 {
let pitch_matrix = beagle_math::Mat4::rotate_x(self.pitch_in_radians);
let yaw_matrix = beagle_math::Mat4::rotate_y(self.yaw_in_radians);
let view_matrix = yaw_matrix.get_transposed().mul(&pitch_matrix.get_transposed());
let translate_matrix = beagle_math::Mat4::translate(&self.position.mul(-1.0));
translate_matrix.mul(&view_matrix)
}
This works as expected. I am able to walk around and look around with the mouse.
What I am Attempting to do
However, an obvious limitation of this implementation is that since pitch and yaw is always defined relative to a global "up" direction, the moment I pitch more than 90 degrees, getting the world to essentially being upside-down, my yaw movement is inverted.
What I would like to attempt to implement is what could be seen more as a first-person "space flight" camera. That is, no matter what your current orientation is, pitching up and down with the mouse will always translate into up and down in the game, relative to your current orientation. And yawing left and right with your mouse will always translate into a left and right direction, relative to your current orientation.
Unfortunately, this problem has got me stuck for days now. Bear with me, as I am new to the field of linear algebra and matrix transformations. So I must be misunderstanding or overlooking something fundamental. What I've implemented so far might thus look... stupid and naive :) Probably because it is.
What I've Tried so far
The way that I always end up coming back to thinking about this problem is to basically redefine the world's orientation every frame. That is, in a frame, you translate, pitch, and yaw the world coordinate space using your view matrix. You then somehow redefine this orientation as being the new default or zero-rotation. By doing this, you can then, in your next frame apply new pitch and yaw rotations based on this new default orientation, which (by my thinking, anyways), would mean that mouse movement will always translate directly to up, down, left, and right, no matter how you are oriented, because you are basically always redefining the world coordinate space in terms relative to what your previous orientation was, as opposed to the simple first-person camera, which always starts from the same initial coordinate space.
The latest code I have which attempts to implement my idea is as follows:
fn space_camera(&mut self) -> beagle_math::Mat4 {
let previous_pitch_matrix = beagle_math::Mat4::rotate_x(self.previous_pitch);
let previous_yaw_matrix = beagle_math::Mat4::rotate_y(self.previous_yaw);
let previous_view_matrix = previous_yaw_matrix.get_transposed().mul(&previous_pitch_matrix.get_transposed());
let pitch_matrix = beagle_math::Mat4::rotate_x(self.pitch_in_radians);
let yaw_matrix = beagle_math::Mat4::rotate_y(self.yaw_in_radians);
let view_matrix = yaw_matrix.get_transposed().mul(&pitch_matrix.get_transposed());
let translate_matrix = beagle_math::Mat4::translate(&self.position.mul(-1.0));
// SAVES
self.previous_pitch += self.pitch_in_radians;
self.previous_yaw += self.yaw_in_radians;
// RESETS
self.pitch_in_radians = 0.0;
self.yaw_in_radians = 0.0;
translate_matrix.mul(&(previous_view_matrix.mul(&view_matrix)))
}
This, however, does nothing to solve the issue. It actually gives the exact same result and problem as the fps camera.
My thinking behind this code is basically: Always keep track of an accumulated pitch and yaw (in the code that is the previous_pitch and previous_yaw) based on deltas each frame. The deltas are pitch_in_radians and pitch_in_yaw, as they are always reset each frame.
I then start off by constructing a view matrix that would represent how the world was orientated previously, that is the previous_view_matrix. I then construct a new view matrix based on the deltas of this frame, that is the view_matrix.
I then attempt to do a view matrix that does this:
Translate the world in the opposite direction of what represents the camera's current position. Nothing is different here from the FPS camera.
Orient that world according to what my orientation has been so far (using the previous_view_matrix. What I would want this to represent is the default starting point for the deltas of my current frame's movement.
Apply the deltas of the current frame using the current view matrix, represented by view_matrix
My hope was that in step 3, the previous orientation would be seen as a starting point for a new rotation. That if the world was upside-down in the previous orientation, the view_matrix would apply a yaw in terms of the camera's "up", which would then avoid the problem of inverted controls.
I must surely be either attacking the problem from the wrong angle, or misunderstanding essential parts of matrix multiplication with rotations.
Can anyone help pin-point where I'm going wrong?
[EDIT] - Rolling even when you only pitch and yaw the camera
For anyone just stumbling upon this, I fixed it by a combination of the marked answer and Locke's answer (ultimately, in the example given in my question, I also messed up the matrix multiplication order).
Additionally, when you get your camera right, you may stumble upon the odd side-effect that holding the camera stationary, and just pitching and yawing it about (such as moving your mouse around in a circle), will result in your world slowly rolling as well.
This is not a mistake, this is how rotations work in 3D. Kevin added a comment in his answer that explains it, and additionally, I also found this GameDev Stack Exchange answer explaining it in further detail.
The problem is that two numbers, pitch and yaw, provide insufficient degrees of freedom to represent consistent free rotation behavior in space without any “horizon”. Two numbers can represent a look-direction vector but they cannot represent the third component of camera orientation, called roll (rotation about the “depth” axis of the screen). As a consequence, no matter how you implement the controls, you will find that in some orientations the camera rolls strangely, because the effect of trying to do the math with this information is that every frame the roll is picked/reconstructed based on the pitch and yaw.
The minimal solution to this is to add a roll component to your camera state. However, this approach (“Euler angles”) is both tricky to compute with and has numerical stability issues (“gimbal lock”).
Instead, you should represent your camera/player orientation as a quaternion, a mathematical structure that is good for representing arbitrary rotations. Quaternions are used somewhat like rotation matrices, but have fewer components; you'll multiply quaternions by quaternions to apply player input, and convert quaternions to matrices to render with.
It is very common for general purpose game engines to use quaternions for describing objects' rotations. I haven't personally written quaternion camera code (yet!) but I'm sure the internet contains many examples and longer explanations you can work from.
It looks like a lot of the difficulty you are having is due to trying to normalize the transformation to apply the new translation. It seems like this is probably a large part of what is tripping you up. I would suggest changing how you store your position and rotation. Instead, try letting your view matrix define your position.
/// Apply rotation based on the change in mouse position
pub fn on_mouse_move(&mut self, dx: f32, dy: f32) {
// I think this is correct, but it might need tweaking
let rotation_matrix = Mat4::rotate_xy(-y, x);
self.apply_movement(&rotation_matrix, &Vec3::zero())
}
/// Append axis-aligned movement relative to the camera and rotation
pub fn apply_movement(&mut self, rotation: &Mat4<f32>, translation: &Vec3<f32>) {
// Create transformation matrix for translation
let translation = Mat4::translate(translation);
// Append translation and rotation to existing view matrix
self.view_matrix = self.view_matrix * translation * rotation;
}
/// You can get the position from the last column [x, y, z, w] of your view matrix.
pub fn translation(&self) -> Vec3<f32> {
self.view_matrix.column(3).into()
}
I made a couple assumptions about the library:
Mat4 implements Mul<Self> so you do not need to call x.mul(y) explicitly and can instead use x * y. Same goes for Sub.
There exists a Mat4::rotate_xy function. If there isn't one, it would be equivalent to Mat4::rotate_xyz(delta_pitch, delta_yaw, 0.0) or Mat4::rotate_x(delta_pitch) * Mat4::rotate_y(delta_yaw).
I'm somewhat eyeballing the equations so hopefully this is correct. The main idea is to take the delta from the previous inputs and create matrices from that which can then be added on top of the previous view_matrix. If you attempt to take the difference after creating transformation matrices it will only be more work for you (and your processor).
As a side note I see you are using self.position.mul(-1.0). This tells me that your projection matrix is probably backwards. You likely want to adjust your projection matrix by scaling it by a factor of -1 in the z axis.
how to rotate the yellow cube towards the car ? I have a spinning camera, I think this is the case
Are you trying to do with with code? I remind you StackOverflow is for programming. For other game related things there is gamedev.stackexchange.com.
If you are doing this with code - and given that I don't know how the scene tree looks like - I suggest using look_at. Something like this (code for the Camera):
look_at(car.global_transform.origin, car.global_transform.basis.y)
There car is a reference to the car. I can't tell you how to get one without looking at the scene tree, beyond that you can probably use get_node. So car.global_transform.origin is the position of the car in global coordinates. And car.global_transform.basis.y is the direction towards the up of the car.
The method look_at needs an up vector because there are infinite ways to look at a given point (rotate around the view line). Thus, we do not want an up vector that matches the view line. For example, Vector3.UP won't work if the camera is looking directly up or directly down.
And if you just want to rotate this in the designer. You can use the gizmo you see when you select it. You can drag the blue ring until it is aligned correctly.
The de facto standard for this gizmos is that x is red, y is green, and z is blue (this is true in Godot, Blender, and plenty of other software). So the blue ring rotates around the z axis. You can also find that rotation in the inspector panel, look for rotation degrees for the z under transform.
I remind you that if you place the Camera as a child node of another Spatial, it will keep its position and orientation relative to it. So placing the Camera as child of your player character (e.g. a KinematicBody) is often good enough for the early stages of development, as that guarantees that the Camera follows the player character. No coding necessary. You may want a more elaborate Camera control later, which would require some code.
Since you mention "spinning camera", perhaps you want a Camera that orbits around a point. The easier way to do this is to add an auxiliary Spatial for the point the Camera rotates around. Let us call it Pivot, and rotate that. For clarity, I'm suggesting a setup like this:
PlayerCharacter
└ Pivot
└ Camera
Here the Pivot follows the player character. And the Camera follows the Pivot. So moving the player character moves the Camera, and rotating the Pivot makes the Camera orbit. This is just lacking some code to make the Pivot rotate. For example something like this (code for Pivot):
global_transform.rotate_y(Input.get_axis("camera_left", "camera_right"))
Where "camera_left" and "camera_right" are actions configured in the Input Map (in Project settings). Which reminds me, you can set actions from code with Input.action_press, so there could be code somewhere else (e.g. _input) writing these actions from mouse movement.
Camera Control does not have to be hard.
I 'program' simple hyper casual mobile games in my free time using a sudo programming language software called construct 3, as I am still learning actual languages and can't yet use them well enough to make games.
Essentially I am writing my own super simple bouncing ball physics engine. I have up to 3 balls in this little pinball game of mine at any time. I have given each ball an x velocity and y velocity instance variable.
Here is my question: how do the x and y velocities change when the ball bounces off of a surface with any angle? I know that if the floor is flat and it hits that, x stays the same and y flips it's polarity. I know the opposite happens with hitting a wall. But I have no idea how to calculate any other angle besides the 4 main axes. I'm sure it is a simple trig function. Oh, and dumb your answer down to the most simple sudo-code response you can make.
For any collision of an object against a flat surface of an angle alpha, your object will bounce back with an angle -alpha. Also, your have what's called a conservation of momentum, which means if your surface doesn't move and does not absorb anything, the total velocity of your object will not change either.
That being said, "all you need to do" is to parameter both the angle of your surface to the horizontal and the angle of your object incoming to your surface, so you can easily register an angle alpha. This way, you will be able to get a -alpha angle between your object and the surface after the collision in the frame of your surface, and you will then need to go back to the "horizontal frame" by simply adding the angle of your surface.
As far as your implementation should go, this is what I suggest:
Start with a function horizontalToAngularFrame that will takes one or more parameter depending if you're in 2D or 3D, so you can define the angle
Code another function AngularFrameToHorizontal with the same number of parameter
When an object enters in collision, just treat is as you would treat an object in the horizontal frame, and use the 2 previously coded functions to bring the angles back to your horizontal frame
I am building a Star Fox like game. The player needs to control a ship in order to move trough gaps in the walls. Here are my problems:
I need to somehow detect collision with wall (if any)
How do I make the wall (Rect) slowly get bigger until it reaches a point?
Full code
If the solution can be done with classes, that would be great!
Here's the documentation for the pygame.Rect class: https://www.pygame.org/docs/ref/rect.html#pygame.Rect.inflate
To detect collision, the pygame.Rect class has methods to detect collision between Rects. There are a few there, so you could use collidelist() to check if the player's ship's Rect collides with any of the wall Rects.
The class also has two methods inflate() and inflate_ip which can be used to increase the size of any Rects.
Can you change the perspective in POV-Ray, so that convergence between parallel lines does not look so steep?
E.g. change this angle (the convergence of the checkered floor into the distance) here
To an angle like this
I want it to seem like you're looking at something nearby, so with a smaller angle of convergence in parallel lines.
To illustrate it more: instead of a view like this
Use a view like this
Move the camera backwards and zoom in (by making the angle smaller):
camera {
perspective
location <0,0,-15> // move this backwards
sky y
up y
angle 30 // make this smaller
right (image_width/image_height)*x
look_at <0,0,0>
}
You can go to the extreme by using an orthographic "camera":
camera {
orthographic
location <0,0,-15> // Move backwards, no matter how far
sky y
up y * h // where h = hight you want to cover
right x * w // where w = width you want to cover
look_at <0,0,0>
}
The other extreme is the fish-eye lens.
You need to reduce the field of view of your camera's view frustum. The larger the field of view, the more stuff you're trying to squeeze into the output of your camera's render and so they parallel lines will converge faster. So in your first example with a cube, the camera will be more focused on the cube and the areas just immediately around it, than the whole environment.
The other option is to make your far plane much closer to your near plane, so you don't see many things that are far off. So in you first image example, you'll only see the first four or five grids instead.