XNA SpriteBatch.Draw 3D Vectors HLSL - c#

you all know the layerDepth value of the spriteBatch.draw() call. I'm using 3D vectors for my 2D game. Is it possible to get the layerDepth as the z value within the vertex shader? Or can I call the draw function with 3d vectors?
I need the depth of a sprite for postprocessing.

Yes, the layerDepth is passed as the Z position of each vertex.
Normally there is a range limit of between 0 and 1 for this parameter. Although I think this is only due to position near/far planes of the SpriteBatch default projection matrix. So it might not apply to you - I don't think the values are clamped or anything.

Related

Does Unity move object by the magnitude(length) of vector value?

Most of you may know that moving object diagonally is faster than moving object horizontally or vertically. You can watch a short youtube tutorial here. If an object is set at (0,0) then using this code.transformation.postition += new Vector3(x, y, 0f).Assume moving object on 2D plane. When looking the object position at 2D grid(cartesian plane), for value x=1, y=0, it move one position right, for value x=0, y=1, it move one position up and for value x=1, y=1 it move one right and one up. When look at the following image, the line drawing diagonally is obviously longer than others. I read about vector, the magnitude of vector, Pythagorean theorem. Assume an object move one unit every frame. Then after 1 frame passed all objects will be moved 1 unit exactly. But when calculate in magnitude[length] of vector the units are different. I mean 1 in X or Y and around 1.4 in diagonal. Aren't object moving from point to point? Does Unity move object in vector's magnitude value and set the point on X and Y plane? How do object actually move?
Unity is a frame-based engine. So Unity calculates the positions where objects are in a frame, and when it comes to calculating the next frame, the positions are calculated there as well. One could assume that the object has moved between these frames and conclude that, for example, a projectile must have hit a thin object between the two frames.
If you want to move an object consistently in any direction, first clamp the direction with normalized and then add a custom magnitude.

Unity change vertex normals on collision

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.

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.

How to translate a sprite and a vertex geometry by the same distance?

I'm trying to build up a 2.5 engine with XNA. Basically, I want to display a 2D sprites (the main hero and other monsters) in a 3D background. The game will be a platform.
Now, using a translation matrix on a sprite doesn't yield the same result of translate a vertex geometry in world space.
I mean, if I apply
Matrix.CreateTranslation(new Vector3(viewportWidth / 2, viewportHeight / 2, 0));
the sprite will be translate at the middle of screen (starting from the display upper left origin). But, if I apply the same transform to a cube in world space, it will translate very far. This doesn't suprising me, but I wonder of to translate a sprite and a 3D object by the same distance, ignoring all the project/unproject coord stuffs.
Thanks!
There are traditionally three matrices: World, View and Project.
BasicEffect, and most other 3D Effects, simply have those matrices. You use Project to define how points are projected from the 3D world onto the 2D viewport ((-1,-1) in the bottom-left of the viewport to (1,1) in the top-right). You set View to move your camera around in world space. And you use World to move your models around in world space.
SpriteBatch is a bit different. It has an implicit Project matrix that causes your world space to match the viewport's client space ((0,0) in the top-left and (width,height) in the bottom-right). You can pass a transformMatrix matrix to Begin which you can generally think of like the View matrix. And then the parameters you pass to Draw (position, rotation, scale, etc) work like the World matrix would.
If you need to do "weird" things to your World or Project matrices in SpriteBatch, you can just build those transforms into your transformMatrix. It may just involve some maths to "undo" the built-in transformations.
In XNA 4 you can also use an Effect (like BasicEffect) directly in SpriteBatch, which you can provide with arbitrary matrices (details).

Is there a 3D equivalant to clamp in XNA?

I'm building a 3D game but i only plan on using a 2D perspective thus not taking the z axis into the equasion,
i want to be able to limit the movement of one of my models so it doesn't move out of the unmoving field of view,
when i was designing 2D it was simple just use clamp, but i cant seem to figurebout how to do this in 3d
any help would be much appreciated
Regards
Just use Vector3.Clamp(Vector3 value1, Vector3 min, Vector3 max) and use the constructor on Vector3 that takes a Vector2 and an int (for z value).
If you simply want to do the same thing as a 2D clamp would - Vector3.Clamp set the Y (usually 'UP') component of the two bounding vectors you pass to be 0.
I'm slightly confused on the question however, it seems that maybe what you are after is a form of collision detection with the view frustum This article may help with that if your model can fit into a bounding sphere relativity nicely.
You will need to for test collision vs all the planes which define the view space. If its a perspective camera your using, you'll need to get the Frustum Planes, otherwise if its an orthographic camera they are the planes that make the bounding box of the view space (a cuboid which is orientated the same way as the camera).
So you want in pseudocode:
if (object.position+movementVec is in view of camera)
object.position+=movementVec;

Categories

Resources