How To Extrude a Flat 2D Mesh, Giving it Depth - c#

I have a set of co-planar, connected triangles, i.e., a 2D mesh. Now I need to extrude it out a few units in the z-axis. The mesh is defined by a set of vertices which the renderer makes sense of by matching up against an array of triangles.
Example Mesh:
Vertices: (0,0,0), (10,0,0), (10,10,0), (0,10,0) <-- (x,y,z)
Triangles: (1, 2, 3) & (3, 4, 1) <-- numbers here reference the position of a vertex above.
So here we have a 2D square. Now I need to add more vertices and triangles to that list to make an extruded shape. Triangles must be in clockwise direction, otherwise they're backface-culled.
Is there a simple algorithm for this? Thank you.

Assuming you want to extrude by a distance z, you need to follow these steps:
0) let n be the original number of vertices (4 in your example)
1) For each vertex in your vertex array, add (0,0,z) to it, and add the result to your vertex array, for a total of 2*n vertices. So, for your example, you will add the vertices (0,0,z), (10,0,z), (10,10,z), (0,10,z) to your vertex array, for a total of 2*4=8 vertices.
2) Create a list of boundary (as opposed to internal) edges for your original mesh. To do this, create a list of all triangle edges (3 edges going in clockwise order for each triangle). Then remove pairs of equal but opposite edges (these are the internal edges). For your example, you will start with 6 edges, and end up with 4 edges after removing the edge pair (3,1) and (1,3).
3) for each triangle (a,b,c) in your triangle list, create a corresponding triangle (a+n,b+n,c+n). These will be the extruded faces
4) Finally, you want to create the sides of your extruded shape. For each edge (a,b) in the boundary edge list you created in step 2, add the triangles (a,b,b+n) and (b+n,a+n,a)
That's it. Assuming no typos on my part, and no typos on your part, you should now have your desired mesh.

Related

Simple OpenTK Raycasting

Alright, I don't know if you can quite consider it ray casting, but I am basically trying to find which tile on my 2d grid is being hovered over so I can place an object there.
The solution should only pick up the grid and not the buildings on the grid. Building highlighting will be based on if any of the tiles the building occupies is being hovered over.
A great example of what I am trying to achieve is a Factorio like building system.
Edit:
The grid is a 2d array which contains all the tile info. The tiles in world are each 2 triangles (Made from a vertex array and index array). The camera is a perspective camera (If Factorio uses Orthographic, I could switch to it if it made things simpler).
Edit 2:
The array contains a class called TileInformation which has a couple of things related to what the tile contains and such. The tiles are 1x1 in size and the array is 256x256. (There will be multiple grid pieces which can be individually updated.) All tiles are in a grid with positions represented as int's (Coordinate system is positive and negative.)
Your question is still not clear enough, but I'll make a few assumptions and hope that they meet your situation.
First, we need a picking ray that represents the 2D mouse position in 3D space. For this, we first transform the mouse position from pixel coordinates into normalized device coordinates between -1 and 1:
mouseNDCX = 2 * mousePixelX / viewportWidth - 1
mouseNDCY = 1 - 2 * mousePixelY / viewportHeight
Then, we find the ray. For this, we need the view-projection matrix of your camera. Then:
mouseNear = inverse(viewProjection) * (mouseNDCX, mouseNDCY, 0, 1)
mouseFar = inverse(viewProjection) * (mouseNDCX, mouseNDCY, 1, 1)
This will give you two positions on the picking ray. One on the z-near plane and one on the z-far plane. Do not forget to do the perspective divide:
mouseNear = (1 / mouseNear.w) * mouseNear
mouseFar = (1 / mouseFar.w) * mouseFar
The next step is calculating the intersection point with the grid. This is where your question is heavily underspecified. I assume that the grid lies on a plane that is parallel to one of the principal planes. In the following, this will be the xy-plane. If you have a different plane, you need to replace the corresponding components. I will further assume that the grid is located at height z.
Now, we want to find the intersection, i.e.:
((1 - t) * mouseNear + t * mouseFar).z = z
<=> mouseNear.z + t * (mouseFar.z - mouseNear.z) = z
<=> t = (z - mouseNear.z) / (mouseFar.z - mouseNear.z)
This lets us calculate the intersection point:
intersection = (1 - t) * mouseNear + t * mouseFar
This intersection point lies on the plane of the grid. Finally, we need to find the tile index. For this, we only need to consider the x- and y-components. Assuming that your grid origin is at o and that the tiles have size s, then the tile indices are:
i = floor((intersection.x - o.x) / s)
j = floor((intersection.y - o.y) / s)

Draw segments of circle on xna

How do I draw a circle sector (as in a slice of pizza shape) in xna?
I'd like to use one as a timer indicator, so would like to be able change its angle dynamically.
In an ideal world I'm looking for something like this:
Drawsector (float startAngle, float endAngle, ... )
Does such a thing exist?
And if it does - how would I go about drawing a more graphically involved one (as opposed to just block colour)
No. XNA only provides an API for drawing primitive elements called surprisingly primitives.
All is not lost because drawing a circle can be viewed as simply drawing a series of very short interconnected line segments, small enough that you can't tell they are lines, but not too small so as to be inefficient.
In XNA you would draw a PrimitiveType.LineStrip.
MSDN:
The data is ordered as a sequence of line segments; each line segment is described by one new vertex and the last vertex from the previous line seqment. The count may be any positive integer.
e.g. (from MSDN)
GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
PrimitiveType.LineStrip,
primitiveList,
0, // vertex buffer offset to add to each element of the index buffer
8, // number of vertices to draw
lineStripIndices,
0, // first index element to read
7 // number of primitives to draw
);
You would need to create your own function to determine the vertices that match the arc you want to draw. You should save that into a permanent index and vertice buffer rather than performing a DrawSector() all the time in your game loop.
Tell me more
Drawing 3D Primitives using Lists or Strips

How to find The Rotation of a 3d Triangle

I need a function so that, when given the Vector3 for a, b and c, will give me a new Vector3, the rotation of the Triangle. Pretty much, for point d, if I want to move it out, adjacent to the triangle, I just have to multiply the distance I want to move it by the Vector3 rotation, and add the old position to get the new Location.
The vector you want is called the unit normal vector. "Unit" means the length is 1 (so that you can just multiply by distance), and "normal" is the name of the vector that's perpendicular to a surface.
To get it, take the cross-product of any two edges of your triangle, and normalize the result. Look at this question for details on how to do this mathematically.
Note: "Normalizing" a vector means to keep the direction the same, but change the length to 1. It doesn't directly relate to a "normal vector".

Indexes for triangles of dodecahedron centered at the origin

Wikipedia says that dodecahedron at the origin has vertices with this coordinates(x,y,z):
(±1, ±1, ±1)
(0, ±1/φ, ±φ)
(±1/φ, ±φ, 0)
(±φ, 0, ±1/φ)
where φ is golden ratio (φ = (1 + √5) / 2 ≈ 1.618 )
Let's say that I'll have this vertexes in vertexBuffer - which will be an array of Point3D.
I need prepare indexes of triangles for indexBuffer(which is an array of int). Dodecahedron has 12 faces, each face is pentagon and I will create each face from 3 triangles this way:
first triangle: a,e,b
second triangle: b,e,d
third triangle: d,c,b
For easier polyhedron I can draw it and then mark vertices and then easily get the indexes, but in this case it's not good way, cause after this Icosahedron, which has 20 faces, is waiting for me :/
So my question is: Is there any easier way how to get indexes for this vertices according requirements specified above?
Note:
I should also mentioned, that I couldn't use openGL or DirectX. We should practise 3D graphics without this libraries.
The first set of 8 vertices defines a cube.
The 3x4 remaining points come in 6 pairs that lie outside each of the 6 faces of the cube.
Each set of six points (four vertices of the cube face and the corresponding two points further away from the origin) form a pattern that repeats six times. You can get 6 triangles from each set.
An icosahedron is actually simpler: it has only 20 triangles instead of 36. It has a similar pattern, which you can see on its Wikipedia page.

Diagnosing backface culling issues

The setup: I'm using a cubemap projection to create a planet out of blocks. A cubemap projection is quite simple: take the vector from the center of a cube to any point on that cube, normalize it, then multiply that by the radius of a sphere and you have your coordinate's new position. Here's a quick illustration in 2D:
[link]
Now, as I said, I've created this so that it's made of blocks. So in practice, I divide my cube into equal square subdivisions (like a rubik's cube). I use a custom coordinate: (Face, X, Y, Shell). Face refers to which face on the cube the point is on. X and Y refer to its position on the face. Shell refers to its 'height'. In practice this translates into the radius of the sphere I project the point onto. If I haven't explained it well, hopefully an image will help:
[link]
--That's a planet generated with an entirely random heightmap, with backface culling turned off. Anyways, now that you have the idea of what I'm working with--
My problem is that I cannot get backface culling to work predictably. My current system works as follows:
Calculate the center of the block
Get the normal of the vertices on each triangle of the block by taking the cross product of two sides of the triangle
Get the vector from the center of the triangle (the average of the triangle's vertices) to the center of the block, normalize it.
Take the dot product of the normal of the triangle and the normal to the center of the block
If the dot product is >= 0, flip the first and last indices of the triangle
Here's that in code:
public bool CheckIndices(Quad q, Vector3 centerOfBlock)
{
Vector3[] vertices = new Vector3[3];
for (int v = 0; v < 3; v++)
vertices[v] = q.Corners[indices[v]].Position;
Vector3 center = (vertices[0] + vertices[1] + vertices[2]) / 3f;
Vector3 normal = Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]);
Vector3 position = center - centerOfBlock;
position.Normalize();
normal.Normalize();
float dotProduct = Vector3.Dot(position, normal);
if (dotProduct >= 0)
{
int swap = indices[0];
indices[0] = indices[2];
indices[2] = swap;
return false;
}
return true;
}
I use a Quad class to hold triangles and some other data. Triangles store an int[3] for indices which correspond to the vertices stored in Quad.
However, when I use this method, at least half of the faces are drawn in the wrong direction. I have noticed two patterns in the problem:
Faces which point outward from the center of the planet are always correct
Faces which point inward toward the center of the planet are always incorrect
This led me to believe that my calculated center of the block was incorrect and in fact somewhere between the block and the center of the planet. However, changing my calculations for the center of the block was ineffective.
I have used two different methods to calculate the center of the block. The first was to find the projected position of a coordinate which had +.5 X, +.5 Y, and +.5 Shell (Z) from the block's position. Because I define block position using the bottom-left-back corner, this new coordinate would naturally be in the center of the block. The other method I use is to calculate the real position of each corner of the block and then average these vectors. This method seemed pretty foolproof to me, yet it did not succeed.
For this reason I am beginning to doubt the code I pasted above which determines if a triangle must be flipped. I do not remember all of the reasoning behind some of the logic, specifically behind the >= 0 statement. I just need another pair of eyes: is something wrong here?
The problem was that I was being too general in my cubemap projection when I got the position of an arbitrary point on a cube. Compare the GetCorrectedCubePosition method here to the same method here to see the improvements made. The methods for clockwise index order checking I noted in my post should are still unknown in effectiveness, as I won't be using them anymore. Using a correct projection means I can hard-define my vertices as clockwise in the generation methods themselves instead of having to guess.

Categories

Resources