Creating Custom Convex Hull & Mesh in Unity - c#

I'm currently trying to implement a complex search field into a unity project I'm working on, where a user has the ability to spawn points into a scene. My goal is to create a custom shape for that user based on the points they created, and then I'd like to detect whether or not other objects are inside that shape, similar to the detection of a point inside a complex hull (still shaky on the theory behind that, but an example can be found here). If possible, I'd also like the shape to update itself if the points are later moved, giving it an almost elastic, stretchy feel.
So far, every tutorial or resource I've found online does the exact same basic example, where a script assigns new verts, UVs and triangles to a custom mesh to make a plane using two triangles, but this is frustratingly simple, and decidedly unhelpful when I simply don't know what the final shape will look like, or what triangles to actually draw even when the user has as little as five points in the scene.
As of right now, the closest visual representation I could come up with has a List keep track of the user's points, and a script that just draws a bunch of pseudo-triangles using LineRenderers to connect every point, even ones that aren't exterior faces, by iterating through the List multiple times. While this looks close to what I want, it isn't actually useful in any way, as I don't know how to 'fill' those faces, and I'm still relatively lost when it comes to whether or not an object is inside that hull, like the red sphere shown in the example below.
I can also destroy and redraw those lines repeatedly during the Update() method, which allows me to grab a point and move it around, resulting in the shape dynamically changing, but this results in an undesirable flashing effect that I'd sooner avoid for now.
As this is such a broad question, I've also included the method I'm using to draw these lines below, which parents a bunch of lines shaped like triangles to an empty game object for easy destruction and recreation:
void drawHull()
{
if (!GameObject.Find("hullHold"))
{
hullHold = new GameObject();
hullHold.name = "hullHold";
}
foreach(GameObject point in points)
{
for (int i = points.IndexOf(point); i < points.Count - 2; i++)
{
lineEdge = Instantiate(lineReference);
lineEdge.name = "Triangle" + i;
lineEdge.GetComponent<LineRenderer>().startColor = Color.black;
lineEdge.GetComponent<LineRenderer>().endColor = Color.black;
lineEdge.GetComponent<LineRenderer>().positionCount = 3;
lineEdge.GetComponent<LineRenderer>().SetPosition(0, points[points.IndexOf(point)].transform.position);
lineEdge.GetComponent<LineRenderer>().SetPosition(1, points[i + 1].transform.position);
lineEdge.GetComponent<LineRenderer>().SetPosition(2, points[i + 2].transform.position);
lineEdge.GetComponent<LineRenderer>().loop = true;
lineEdge.SetActive(true);
lineEdge.transform.SetParent(hullHold.transform);
}
}
}
If anyone has encountered a similar problem somewhere else that I simply couldn't find, please let me know! Anything from more knowledge on creating a custom mesh to a more in depth and beginner-friendly explanation on determining if a point is inside a convex hull would be quite helpful. If it's at all relevant, I am working in VR and running version 2018.2.6f1 to ensure that the Oculus rift package and Unity play nice, but I haven't been having any issues working in an environment a few months behind.
Thanks!

You do mention assinging verts and tris to a mesh - this is the 'right' way to do it in unity, as it ties in with highly optimized MeshRenderer, and also I believe Colliders are able to use meshes where given the shapes like that, so you should be able to just plug into PhysX and query it for colliders overlaping with your mesh. Doing it by hand, aka iterating through faces and establishing actual bounds of your object is actually pretty hard to do effectively

Related

How do I determine if i just calculated the normal in the correct direction?

To explain the context, I procedurally generate buildings on unity in C#. I create a mesh and fill in the vertices and triangles, then I calculate the normals of the different points. I have several hundreds of buildings that are generated, but some faces are not in the right direction, the normals point inwards instead of outwards.
The normals are good
The normals are bad
To calculate the normals I create a Plane with the different vertex that make up the triangle, and then I retrieve the normal of the Plane. I also tested the cross product that gives the same result.
Plane plane = new Plane(v1, v2, v3);
normals.Add(plane.normal);
How i generate Triangle ?
Ex: I make a for loop on the points at the base of the building.
vectors.Add(v1);
vectors.Add(v2);
vectors.Add(v3); //v3 = v1+height
vectors.Add(v4); //v4 = v2+height
// index values
int idx1, idx2, idx3, idx4;
idx4 = vectors.Count - 1;
idx3 = vectors.Count - 2;
idx2 = vectors.Count - 3;
idx1 = vectors.Count - 4;
// Triangle 1
indices.Add(idx1);
indices.Add(idx3);
indices.Add(idx2);
...
mesh.triangles = indices.ToArray();
So my question is: How to determine if the normal is in the right direction (inside or outside)? If I can determine that, I can then flip the normal and normally it will work.
I do not totally understand your question, but for simple shapes a simple algorithm is ..
just take the "center" of the object (the CG is fine) and make a vector from there to your vertex or triangle. That direction is "outside". If you're pointing over 90° away from that, you're pointing in to the guts of the object
the next more complicated approach ...
move along your normal say "one meter". call that point "test point". you should now be "outside" your building, correct?
now you just need to check if testPoint is inside or outside your 3D shape.
in short, to determine if you are inside or outside a 3D object, you just cast a ray and count how many times you intersect with the walls. if odd, you're inside, if even you're outside.
You can google hundreds of discussions on this on the www, example https://stackoverflow.com/a/63572837/294884
Note that there are many, many variations on this, and many problems too. In some cases you start from "just inside" your normal (ie go backwards a little); sometimes it's better to start from the middle of the object (if such a thing is knowable); sometimes there are issues about how the ray casting system works in edge cases (like "right on" the surface, which is what your vertex is)
the first solution seems to me to be the right one
It may be. Sometimes it is useless. It depends on the nature of your shapes.
I wanted to avoid having to do raycast ..
Can assure you - you will have to constantly raycast during any construction process! If you wish to "avoid" casting, set the idea aside. You will be casting until you are sick of it :)
I wanted to avoid having to do raycast to limit the generation time
The good news is this is totally incorrect. Casting is extremely trivial and a very minor burden compared to everything going on in a 3D scene. When you play any 3D scene, casts are being made 100s and 1000s of times each frame.
but if I have two buildings that are close to each other, the ray will find the wall but from the second building so I couldn't determine the normal is "inside" or "outside", right?
TBC in the simple system I described. You would certainly ONLY cast against that same building that you are working on! So that's the way to go.
But indeed, unrelated to what you're asking about. Say you're in a "city". You can indeed cast through "all walls" and the parity (ie: odd or even) will let you know if you are indoors or out. This has problems though, relating to edges, corners etc. But in some case it is relevant to that problem.
As mentioned on this answer https://stackoverflow.com/a/63593282/294884 ultimately you can investigate convex hulls and more. It's a big topic!
Note that often when you build dynamic buildings/shapes, you havce a data structure of each "wall" and indeed it knows which side is in and which side out. When you do that first, it's then easy to draw the triangles the correct way. It's a big topic!

How to randomly place objects as player move around in an infinity map without overlap?

I trying to make a game where player only move forward in an infinity map, and the path (just thing of them like points, the path is only the visual) is procedurally generated. I want those path to have different length (something like the tree of life, but only branches of the selected path are generated).
This is how I generate branches without overlap:
List<Vector3> everyPos; //predetermined position
public void Spawn(int amount)
{
List<Vector3> possiblePos = new List<Vector3>(everyPos);
for (int i = 0; i < amount; i++)
{
int index = Random(0, possiblePos.Count); //Find a random position
SpawnObjectAt(currentPosition+possiblePos[index]));//Create a point there
possiblePos.RemoveAt(index); //Remove that position from the list
}
}
The problem is , look at this image(I can't embed image yet):
Red is where player start, green is possible spawn position in the first move.
If there are 2 point spawned at 1 and 2, player choose point1, then the possible position in the second time will be a point in the black zone, which include point2, so if I keep continue there will eventually overlap.
How can I avoid this? I'm making a mobile game so I don't want to cache every single point. Any help would be really appreciated! Thanks!
This is a small web game that have somewhat similar mechanic to what I trying to achieve: newgrounds.com/portal/view/592325/
This is an attempt here to answer, but honestly, you need to provide more information.
Depending on the language you are writing in, you can handle this differently. You may need dynamic allocation, but for now lets assume, since your idea is quite small, that you can just do one large array predefined before compile time.
I assume you know how to make an array, so create one with say, 500 length to start. If you want to 'generate' a link like they did in that game, you simply need a random function, (there is a built in library in pretty much every language I think) and you need to do a little math.
Whatever language you use will surely have a built in graphics library, or you can use a popular easy to use one. I'll just draw a picture to make this clear.
There are a number of ways you can do this mathematically as shown in the image, using angles for example, the simplest way, however, is just to follow the boxes.
If you have worked with graphics before, you know what a vector is, if not, you will need to learn. The 9 vectors presented in this image (0,1) (1,0) (1,1) etc. can be created as vector objects, or even stored as individual ints.
To make your nodes 'move' into another path, you can simply do a rand 1-9 and then correlated the result to one of 9 possible vectors, and then add them to your position vector. It is easiest to do this in array and just use the rand int as the index. In most c derived languages you do that like this:
positionVector += changeVectorArray[rand(1,9)];
You then increment your position vector by one of the 9 vectors as shown above.
The simplest way of making the 'path' is to copy the position before you add the change vector, and then store all of the changes sequentially in another 'path' array.
To show the path on screen, simply draw a line between the first and second, second and third, third and forth elements of your path array. This formula (of joining lines) is discrete mathematics if I'm not mistaken, and you can do much more complicated path shapes if you want, but you get the gist.
That should at least start you off. Without more info I can't really help you.
I could go off on a tangent describe a bunch of different ways you can make this happen differently but its probably easier if you just ask for specifics.
EDIT>>>
Continuing with this answer, yes, looking at it now, the nodes can definitely overlap. To solve this problem you could use collision detection, every time you generate a new 'position', before adding it and drawing the line you have to loop through your array like this:
boolean copy = true;
for(int i = 0; i < getLength(pathArray); i++){
if( newVector == pathArray[i]){
copy=false;
}
}
Then of course, if copy still is true, copy the new position int the pathArray. NOTE: this whole solution is sloppy as hell, and as your array gets larger, your program is going to take longer and longer to search through that loop. This may not also guarantee that the path goes in one direction, but it is likely. And note that the lines will still be able to overlap each other, even though the position vectors can't be on top of one another.
All this considered, I think it will work, the optimization is up to you. I would suggest that there is probably a much more efficient solution using a discrete formula. You can also use such a formula to make the path go in particular directions and do other more complicated things.
You could also quite easily apply constraints on your random rolls if you want to make the path go in a particular direction. But there are so many ways of doing this I can't begin to explain. You could google path-finding algorithms for that.
Good luck.

Rotating a polygon is not working in C#

I'm trying to rotate a polygon in windows forms using C# and below is code written .
Please tell me what wrong in the code, there is no output on windows form.
Before and after rotation polygons not visible.
public void RotatePolygon(PaintEventArgs e)
{
pp[0] = new Point(624, 414);
pp[1] = new Point(614, 416);
pp[2] = new Point(626, 404);
e.Graphics.DrawPolygon(myPen2, pp);
System.Drawing.Drawing2D.Matrix myMatrix1 = new System.Drawing.Drawing2D.Matrix();
myMatrix.Rotate(45, MatrixOrder.Append);
myMatrix.TransformPoints(pp);
e.Graphics.Transform = myMatrix1;
e.Graphics.DrawPolygon(myPen, pp);
}
Thanks
You code does not compile if left unmodified. There are two matrices used - one declared in your method (myMatrix1) attached to the graphics object and one declared outside your method (myMatrix without the 1) used to explicitly transform the point array.
I tried the code with the required changes and it works flawless - I used myMatrix1 for both transformations and the effective rotation angle was, as expected, twice the one specified. So I guess you are using two transformation that cancel if the transformed points end where they began.
There could be this problems:
[1] your pens have no color/thickness (where do you define them?)
[2] your polygone is to big, so you only see the inside of it but not the border. --> Test Graphics.FillPolygon-Methode so you will see if [2] is right
You're both transforming the points and changing the transform matrix for the Graphics object - you need to do one or the other.
You also need to think about the fact that the rotate is going to be happing about (0,0) rather than about some part of the object - you may well need a translate in there too.
Bear in mind that TransformPoints just manipulates some numbers in an array - which you can easily inspect with the debugger - this will be a more effective technique than displaying an invisible object and wondering where it went.
Starting with a much smaller rotation angle (10 deg, perhaps?) may also help with the problem of losing the object - it will be easier to work out what's happening if you haven't moved so far.

How to implement Pentago AI algorithm

i'm trying to develop Pentago-game in c#.
right now i'm having 2 players mode which working just fine.
the problem is, that i want One player mode (against computer), but unfortunately, all implements of minimax / negamax are for one thing calculated for each "Move" (placing marble, moving game-piece).
butin Pentago, every player need to do two things (place marble, and rotate one of the inner-boards)
I didn't figure out how to implement both rotate part & placing the marble, and i would love someone to guide me with this.
if you're not familiar with the game, here's a link to the game.
if anyone want's, i can upload my code somewhere if that's relevant.
thank you very much in advance
If a single legal moves consists of two sub-moves, then your "move" for game algorithm purposes is simply a tuple where the first item is the marble placement and the second item is the board rotation e.g.:
var marbleMove = new MarbleMove(fromRow, fromCol, toRow, toCol);
var boardRotation = new BoardRotation(subBoard, rotationDirection);
var move = new Tuple<MarblMove, BoardRotation>(marbleMove, boardRotation);
Typically a game playing algorithm will require you to enumerate all possible moves for a given position. In this case, you must enumerate all possible pairs of sub-moves. With this list in hand you can move on to using standing computer game playing approaches.
Rick suggested tuples above, but you might want to actually just have each player make two independent moves, so it remains their turn twice in a row. This can make move ordering easier, but may complicate your search algorithm, depending on which one you are using.
In an algorithm like UCT (which is likely to outperform minimax for simple implementations) breaking into two moves can be more efficient because the algorithm can first figure out what moves placements are good, and then figure out what rotation is best. (Googling UCT doesn't give much. The original research paper isn't very insightful, but this page might be better: http://senseis.xmp.net/?UCT)

Opinions on platform game actor/background collision resolving

Imagine the following scenario: I have a level whose physical structure is built up from a collection of bounding rectangles, combined with prerendered bitmap backgrounds. My actors, including the player character, all have their own bounding rectangle. If an actor manages to get stuck inside a level block, partially or otherwise, it'll need to be shifted out again, so that it is flush against the block.
The untested technique I thought up during bio break is as follows:
If an actor's box is found to intersect a level box, determine where the centerpoints of each rect are. If the actor's center is higher than the level box's, move the actor so that the bottom of the actor's rect is flush with the top of the level's rect, and vice versa if it's lower. Then do a similar thing horizontally.
Opinions on that? Suggestions on better methods?
Actually, the bounding rects are XNA BoundingBoxes with their Z spanning from -1 to 1, but it's still 2D gameplay.
Have you read the N Tutorials? They're a wonderful introduction, complete with little demos, of Separating Axis Theorem based collision detection and simple projection response. (They're actually used in the N game to great effect.) The tutorials cover more than you need, but they're very general (extensible to many other shapes), and start to touch on issues with fast-moving objects and other response techniques.
Even if you do decide to go with something simpler than a SAT implementation, this may give you a lot of good ideas.
(When you're done with that and if you want your mind blown, try looking into some of the presentations from the Game Developers Conference physics tutorial day, including realtimecollisiondetection.net publications, the essentialmath.com tutorial slides, both of those books, and/or other stuff linked from those sites. I'd highly recommend the GDC session itself, too. While we still don't need or particularly want fancy GJK on swept hulls on the handheld game platforms we work with, some of the simpler concepts such as "configuration spaces" and Minkowski sums and differences have greatly influenced how I think about physics and collision detection and how we implement it.)
What the "real" physics engines do is find the minimum penetration vector. That is - the smallest vector that represents how far inside each other the two objects penetrate.
For an AABB (axis-aligned bounding box) this is really easy to calculate.
(Consider making your own 2D AABB structure, it will be smaller and therefore better for performance.)
Once you have your minimum penetration vector, you can perform collision response. And the easiest response is to simply separate the two objects by that vector (or separate the one object if the other is static).
Here is a good reference, by the makers of N on how to do this for convex polygons and circles. You should be able to simplify this down for AABBs.
A lot depends on the details. A complete solution could take into account velocities or other issues. But treating this simply...
You don't want to always resolve vertically first. Imagine an actor nudges horizontally into a block. If you resolve vertically first then the actor will pop up above that block, when a small horizontal movement would have sufficed.
Find what the vertical and horizontal movements would need to be to "get out of collision", and then apply the one with the smallest absolute value.
Then repeat a few times, in case the movement puts the actor into another block. But don't repeat forever, because the actor could be wedged somewhere that never resolves.
Maybe if your last movement still leaves you in collision, you could just average the last two movements and leave it there.
Another possible approach is, rather than waiting for a collision and then shifting out, check for possible collisions before you move objects and, if there is going to be a collision, move the player only up to the edge of the block.
I.e., contrast how Adventure does collisions with walls: http://www.youtube.com/watch?v=I6-zN_eaRd8
to how most NES games do collisions with walls.

Categories

Resources