Unity change vertex normals on collision - c#

I want to change the floor's vertex normals' direction as the ball is rolling on the floor. I just need some direction on how to achieve this.
So far this is the direction that I'm heading:
Make a copy of all the vertex normals of the floor on start.
On collision get the contact point and raycast/spherecast/boxcast to get the affected vertices. (Set variable offset to control how much vertices I want to be affected by the casting)
Find normals related to the vertices.
Rotate the affected normals parrallel to the ball's closest surface point.
As ball moves away from affected's floor's vertices, slowly return the floor normals back to original direction. (Set a variable to control the movement speed of the normal's rotating back to original direction)
I just need help figuring out which type of casting to use and how to rotate the normals parallel to the ball's surface. This is for a mobile platform so performance is a must.
Thanks in advance.

Here's how you'd go about modifying the normals:
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vertices = mesh.vertices;
Vector3[] normals = mesh.normals;
You'd want to use the vertices list to figure out which indexes to modify (presumably also needing to convert from local space to world space). You could then raycast from the worldspace coordinate to the ball's center,1 and use the raycasthit.normal to figure out what the angle to the ball is.
Some clever vector math from there to figure out the new normal for your plane:
Find the vector perpendicular between hit.normal and Vector3.Up: this vector will be parallel to the plane. If the two vectors are parallel, dump out: your normal is unchanged (or should be returned to its original value, which will be the same vector as the raycast to find the sphere).
Find the vector perpendicular to that vector and hit.normal: this vector will be your new normal.
1 Actually, you'll want to know how far down from the ball's center you should target, otherwise, you'll get the most extreme offsets as the ball moves farther away from the plane. So you want the ball's position on X and Z, but a fixed offset up from the plane for Y. This won't be too difficult to calculate.

I would try something like:
Create a texture for the normals. Each pixel is a normal of a vertex(like a grid). Calculate the correspoding coord between the 3d ball and the position of the normal in the texture and draw a ball/circle/sprite on it (like a sprite) each frame. Then you could use a compute shader to revert them slowy to the default up vector.

Related

Off-center rotate object in Unity

I have a laser turret in Unity3D, which I'd like to turn towards the enemies. The turret consists of a "leg" and a "head" (selected on the picture 1). The head can pan and tilt around a spherical joint.
I do the following:
Vector3 targetDir = collision.gameObject.transform.position - turretHead.transform.position;
float step = turnSpeed * Time.deltaTime;
Vector3 newDir = Vector3.RotateTowards(turretHead.transform.forward, targetDir, step, 0.0f);
turretHead.transform.rotation = Quaternion.LookRotation(newDir);
The problem is that since the pivot of the head is not aligned with the laser beam, the turret turns into the almost right direction, but it shoots above the target. (It would hit perfectly, if the laser would come out of the red axis of the pivot.)
Is there a builtin method or some trick to achieve the correct functionality other then doing the calculation myself?
Okay, here's the quick and easy way to do this. It's probably "better" to do it with proper trig, but this should give you the result you want pretty quick:
If you don't already have a transform aligned with the barrel, then create an empty GameObject and line it up (make sure it's a child of the turret so they move together). Add a reference to your script for it's transform.
Then, in your first line, calculate from the new Barrel transform instead of the turretHead transform. Leave everything else the same. This way it calculates from the turret barrel, but moves the turret head.
Now, this approach isn't perfect. If the pivot center is too offset from the barrel transform, then it would be less accurate over large moves, or when aiming at something close by, because the expected position when aiming would be different than the initial position due to the rotation pivot being elsewhere. But this can be solved with iteration, as the calculation would become more accurate the closer it is to it's desired goal.

Calculate degrees from a 2D heading vector

I am trying to add sprites to a game I am currently working on. I have sprites for north, south, west & east directions. I've already found how to get a direction from degrees, the problem is that I can't seem to calculate the right amount of degrees (0° to 360°) from a normalized velocity vector, called heading. Check figure 1 below for my velocity vector, my heading vector is a normalized clone of this vector.
What I want to achieve is that:
A property degrees: returns the right amount of degrees, based on a current heading/velocity vector.
A method receiving degrees as parameter, which in turn can return a direction which I can use when drawing my sprite.
Figure 1: my 2D velocity vector
My code for calculating the heading vector:
Vector2D heading = Velocity.Clone.Normalize();
I am also not sure if using a heading vector is necessary, so if it's possible or preferred to use the velocity vector, please tell me and include this in your answer.

Get an object's start and end position in world space

I have a plane whose scale is set to 1,1,1. I am willing to get its start position and end position. That what is the position at start of the object in world space and what is the end position.
One easy way to do this job is to place object in start and end of the plane and get object positions but i want to do it through the floor Only.
I just tried this code but its not bringin position in world space.
Debug.Log(floor.GetComponent<MeshRenderer>().bounds.min);
Debug.Log(floor.GetComponent<MeshRenderer>().bounds.max);
Debug.Log(floor.GetComponent<MeshRenderer>().bounds.center);
Debug.Log(floor.GetComponent<MeshRenderer>().bounds.extents);
Renderer.bounds will only match size of the plane if plane transform is aligned with the world. In other world it will only work if there isn't any rotation.
Another approach to get corners of the plane would be to look into the mesh vertices directly. This would require finding vertices on the corners first. Forget that.
Create 2 new game objects and place them on the corners of your plane
Parent two corner objects to plane object
Each corners transform.position will now give you world space position regardless of position, rotation or scale of the parent plane object.

How to determine if an object is between two other objects in XNA

I have a screen filled with circles. One circle is the player, one is the enemy, and the others are obstacles. I want the enemy to be able to calculate if there is an obstacle in the path of a straight line from the player to the enemy, so it can adjust accordingly (it is taking place in space, so it is a straight line for jumping from asteroid to asteroid).
Right now, I just turn a random direction when the AI is stuck on an asteroid.
A simple solution could be find the Vector2 between player and enemy (using Vector2.Subtract), and then divide it into smaller vectors or reduce it to a delta that you choose. This can be done normalizing the distance vector and multipling it by a fixed number.
Then simply add that delta to the enemy position and check if the new position collides with an objects (maybe using Rectangle.Contains method), and do this until you reach the player.

Get rotation of a 3D triangle

I have three Vector3 points in 3D space. I need to copy the rotation (the tangent?) of this triangle to the orientation of a 3D model. How can I calculate the triangles Vector3 tangent or create a rotation matrix out of those points?
Finding the angle of a triangle is described here: Find the normal angle of the face of a triangle in 3D, given the co-ordinates of its vertices
Suppose you find the normal and call it N'. It should be trivial for you to write the normal of the "unrotated" triangle, N, eg <1, 0, 0>. It should also be trivial to figure out how to rotate from N to N' and you can create a rotation matrix for it with Matrix.CreateFromAxisAngle in XNA. This matrix should rotate everything like you want.

Categories

Resources