How to rotate BoundingBox - c#

here is my code for displaying bounding box
Vector3[] corners = box.GetCorners();
for (int i = 0; i < 8; i++)
{
verts[i].Position = Vector3.Transform(corners[i],modelMatrix);
verts[i].Color = Color.White;
}
vbo.SetData(verts);
ibo.SetData(indices);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
effect.World = Matrix.Identity;
effect.View = view;
effect.Projection = projection;
pass.Apply();
ContentLoader.SetBuffers(ibo, vbo);
}
I'd like to achieve same result using BoundingBox class.
I tried to do it like this,but it doesn't work
for (int i = 0; i < boundingBoxes.Count; i++)
{
Vector3 min = Vector3.Transform(boundingBoxes[i].Min, modelMatrix);
Vector3 max = Vector3.Transform(boundingBoxes[i].Max, modelMatrix);
boundingBoxes[i] = new BoundingBox(min, max);
}
the code above works if there is no rotation.With rotation things get messed up.Any idea why and how to fix it?

You can not rotate a BoundingBox object in Xna. The built in collision detection methods of the BoundingBox class will always be calculated from min & max for a box in axis alignment only. By transforming min & max, you are not rotating the box, you are only changing the x,y,z dimensions of the axis aligned box.
You might be better off studying up on "oriented bounding boxes". You would draw an oriented box by using the corners as verts and choosing 'LineList' as your PrimitiveType instead of 'TriangleList' in the 'DrawIndexedPrimitives' method. Collision detection for an oriented box is different & more complex than for an axis aligned box.

Related

Why is the radius of my circle too large (Unity using Line Renderer)?

I am trying to draw a circle in Unity using Line Renderer but I'm having a few problems.
A circle is being drawn but its radius is larger than it should be. (the yellow sphere is the radius it should be and the black circle is what is being drawn)
Example: When trying to draw a circle with a radius of 10.0f, the circle drawn will have a radius of something larger than 10.0f.
The circle doesn't fully connect. There are a couple points in the circle where something went wrong. (these areas are circled in the picture)
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public static class GameObjectEx
{
public static void DrawCircle(this GameObject container, float radius, float lineWidth)
{
var segments = 360;
LineRenderer line = container.GetComponent<LineRenderer>();
line.material = new Material(Shader.Find("Sprites/Default"));
line.startColor = Color.black;
line.endColor = Color.black;
line.useWorldSpace = false;
line.startWidth = lineWidth;
line.endWidth = lineWidth;
line.positionCount = segments + 1;
var pointCount = segments + 1;
var points = new Vector3[pointCount];
for (int i = 0; i < pointCount; i++)
{
var rad = Mathf.Deg2Rad * i;
points[i] = new Vector3(Mathf.Sin(rad) * radius, 0f, Mathf.Cos(rad) * radius);
}
line.SetPositions(points);
}
}
I've tried following a few different tutorials for drawing a circle with Line Renderer and the code I posted is the closest I've gotten to something that works. I'm pretty sure problem #1 is being caused by "var rad" but I haven't been able to figure it out. For problem #2, I've tried increasing the value of segments but the two broken parts are still present and unchanged.

BoundingBox of VISIBLE part of GameObject regarding a given camera

I want to find the 2D bounding box (BB) of the visible part of an Game-object in Unity3D.**
Thanks to having no reputation i cant post images, so here are links to Imgur:
Starting Point: Image
Showing the initial scene camera. For example i want to get the BB of the wheels of the passing car.
Goal: Image
Showing the quite small BB i want to get in an efficient way. The method used is very costly and i want to avoid it. Its works on a segmented version of the input picture, looking similar to this: Image.
Current Approach:
Image
This uses the bounds of all GameObjects (GO) tagged as wheels and calls a function similar like this:
Rect GetBoundingBox(GameObject go, Camera camera, float margin = 0f)
{
Rect rect = new Rect(-1f, -1f, -1f, -1f);
Vector3[] v; // Vertices
// Object is behind camera
if (camera.WorldToScreenPoint(go.GetComponentInChildren<Renderer>().bounds.center).z < 0)
return rect;
// get first mesh filter
v = go.GetComponentInChildren<MeshFilter>().mesh.vertices;
// maybe the game object hast no mesh yet... and is empty
if (v.Length < 1 || v == null)
return rect;
for (int i = 0; i < v.Length; i++)
{
//World space
v[i] = go.transform.TransformPoint(v[i]);
//GUI space
v[i] = camera.WorldToScreenPoint(v[i]);
v[i].y = Screen.height - v[i].y;
}
Vector3 min = v[0];
Vector3 max = v[0];
for (int i = 1; i < v.Length; i++)
{
min = Vector3.Min(min, v[i]);
max = Vector3.Max(max, v[i]);
}
//Construct a rect of the min and max positions and apply some margin
rect = Rect.MinMaxRect(min.x, min.y, max.x, max.y);
// apply optional margin
rect.xMin -= margin;
rect.xMax += margin;
rect.yMin -= margin;
rect.yMax += margin;
return rect;
}
Two problems appear.
Its getting all BB even if the GO is not visible by the camera.
Even if its visible, the boundaries are as large as the GO it self, not as the visible part.
I am very happy about every hint in a good direction!!
For interested people the background is the development of an application to generate/simulate labeled training data for an deep learning project.

Get world position of a pixel from texture2d/sprite

I'm setting up an automatic system to be able to attach a sprite and it will gather all its colours and the world position of each sprite. A list/class of all the colours used has been set up but how would get the position of all these sprites?
I have already tried doing this mathematically like getting the complete size of the sprite and then working out the size of each pixel and then working out the position from that. But this seems flawed due to the position of the sprite possibly changing.
Sprite ColouredSpriteTexture = ColoredSprite.GetComponent<SpriteRenderer>().sprite;
Texture2D ColouredTexture = ColouredSpriteTexture.texture;
float XsizeF = ColoredSprite.transform.localScale.x;
int Xsize = (int)XsizeF;
float YsizeF = ColoredSprite.transform.localScale.y;
int Ysize = (int)YsizeF;
List<Color> TempList = new List<Color>();
//Could spawn pixels by getting x and y size and dividing them by 100 50/100 = 0.50f
//if the tile has a color then spawn pixel if not 0.50 += 0.50
//TODO test if this logic will work
float PixelSize = XsizeF / 100;
float currentPos = PixelSize;
for (int x = 0; x < Xsize; x++)
{
for (int y = 0; y < Ysize; y++)
{
int listAmount = TempList.Count;
Color ColoredTex = ColouredTexture.GetPixel(x, y);
float TextureAlpha = ColoredTex.a;
if (!TempList.Contains(ColoredTex) && TextureAlpha != 0)
{
TempList.Add(ColoredTex);
ColorByNumber tempColor = new ColorByNumber();
tempColor.Color = ColoredTex;
tempColor.ColorNumber = listAmount;
ColorOptions.Add(tempColor);
}
if(TextureAlpha == 1)
{
GameObject ColorPixel = Instantiate(PixelPrefab);
ColorPixel.transform.localScale = new Vector3(XsizeF, YsizeF, 0);
ColorPixel.transform.SetParent(this.transform);
ColorPixel.name = "Pixel (" + x.ToString() + "," + y.ToString() + ")";
}
}
}
All I would need is somehow each pixel returning its position so I can store this data and be able to spawn anything on top of this pixel.
I haven't had a chance to test this math yet so there may be some mistakes in it:
Every graphical image in Unity has a PPU, this and the object scale are going to be a huge factor. For argument sake I am going to clearly define these for 1 object.
Image dimensions : 128x128
PPU: 64
Scale: 1,1,1
Object Bounds: would
come from the renderer, which I am unsure if that bounds already
takes in account the scale(Most likely) however in the case you
cannot use that you can calculate the ObjectBoundsWidth or height
just by dividing the width or height of the texture by the PPU.
This should give you bounds of the texture in world space.
We are also going to make an assumption that we are only working on the X and Y axis and ignore the Z axis, if you want to use Z instead of Y then just make the necessary changes to be Z Scale and Z position and Z Bounds.
World position of a pixel located at 2,10. Per the documentation the pixel coordinates start at the lower left this means 0,0 is the bottom left corner, and 2,10 is 2 pixels left and 10 pixels up.
EDIT:
So I plugged all of this into a google sheet and determined the previous algorithm I provided was wrong here is the correct one in a pseudo code format
// This function takes in either the x or y, and the width or height of
// the bounds, then the x or y position of the object attached to.
// It also assumes the pivot is the center of the sprite.
float CalculateWorldPosOfPixelCoordinate(int coord, float boundsSize, float position, float scale)
{
float PixelInWorldSpace = 1.0f / PPU;
float startPos= position - (boundsSize* 0.5f * scale);
return startPos + (PixelInWorldSpace * coord) * scale;
}
This is using objectBounds we determined ourselves that is why we are multiply by scale.
this would give use a world position of: -0.97, -0.84
The algorithm i believe is the same for Y, just replace the coord with the Y position, and the bounds with the height instead of the width.
Like I said this could be wrong as I havent had a chance to test it, this also does not account for rotation either.

Bullet Physics Convex hulls with cubes

I'm developing a game engine in c# and am using BulletSharp for physics. It's working well except with cubes:
http://i.stack.imgur.com/EPfrw.png
(The Axis-Aligned Bounding box is the transparent red, the model is the white)
At rest, the stand on their edges. Because I'm loading from Collada models, I am creating a ConvexHullShape() and adding the data as a vector cloud. While using BoxShape() would be more efficient (and work correctly), I cannot as it is not guaranteed that all models are cubes. I cannot figure out why they rest on vertices and not on the flat edges. Is my implementation of ConvexHullShape wrong or do I need to use a different type of shape (for the physics to work correctly)?
public RigidBody AddDynamicGeometry(ColladaGeometry geometry, Matrix4 transform)
{
List<Vector3> points = new List<Vector3>();
foreach (Triangle tri in geometry.triangles)
{
points.Add(tri.vertices[0]);
points.Add(tri.vertices[1]);
points.Add(tri.vertices[2]);
}
CollisionShape shape = new ConvexHullShape(points);
shape.UserObject = geometry;
collisionShapes.Add(shape);
RigidBody body = CreateRigidBody(geometry.triangles.Count * 10, transform, shape);
return body;
}
public RigidBody CreateRigidBody(float mass, Matrix4 startTransform, CollisionShape shape)
{
bool isDynamic = (mass != 0.0f);
Vector3 localInertia = Vector3.Zero;
if (isDynamic)
shape.CalculateLocalInertia(mass, out localInertia);
DefaultMotionState myMotionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
RigidBody body = new RigidBody(rbInfo);
physics_world.AddRigidBody(body);
return body;
}
ConvexHullShape expects the center of mass (COM) to be (0,0,0), but the cube is offset from the center, making it tilt towards the corner.
You can find the correct COM with ConvexTriangleMeshShape.CalculatePrincipalAxisTransform. Then you could subtract the COM from each vertex to bring the COM back to 0. However, it's easier to create a CompoundShape with a local center for the cube.
// Create a ConvexTriangleMeshShape from the points
const int indexStride = 3 * sizeof(int);
const int vertexStride = 12;
int vertexCount = points.Count;
int indexCount = vertexCount / 3;
TriangleIndexVertexArray vertexArray = new TriangleIndexVertexArray();
IndexedMesh mesh = new IndexedMesh();
mesh.Allocate(vertexCount, vertexStride, indexCount, indexStride);
Vector3Array vdata = mesh.Vertices;
IntArray idata = mesh.TriangleIndices;
for (int i = 0; i < vertexCount; i++)
{
vdata[i] = points[i];
idata[i] = i;
}
vertexArray.AddIndexedMesh(mesh);
ConvexTriangleMeshShape shape = new ConvexTriangleMeshShape(vertexArray, true);
// Calculate center of mass
Matrix center = Matrix.Identity;
Vector3 inertia;
float volume;
shape.CalculatePrincipalAxisTransform(ref center, out inertia, out volume);
// Create a CompoundShape with COM offset
CompoundShape compound = new CompoundShape();
compound.AddChildShape(Matrix.Invert(center), shape);
Note: ConvexTriangleMeshShape.CalculatePrincipalAxisTransform works in SVN trunk, but not in BulletSharp 2.82. There will be a bugfix release soon.

Why my Images flickers in my xna project?

I have some problems on the display of my model with texture.
Everything works perfectly, however, I use a loop to repeat the texture to represent a floor 20 X 20 on the screen. My texture is repeated correctly. But I do not understand why all my textures generate a flicker ...
I noticed that images are superimposed on each other. I'm sure I checked my loop is coded correctly.
see screenshot:
my code (loop function generation ground):
//Function draw - ground land
private void draw_groundLand(Vector3 position_model_origin)
{
//example generation mode 4x4 cubes
int[,,] MatriceWorldCube = new int[1,2,2];
MatriceWorldCube[0, 0, 0] = 1;
MatriceWorldCube[0, 0, 1] = 1;
MatriceWorldCube[0, 1, 0] = 2;
MatriceWorldCube[0, 1, 1] = 1;
int height = MatriceWorldCube.GetLength(0);
int width = MatriceWorldCube.GetLength(1);
int length = MatriceWorldCube.GetLength(2);
Vector3 pos_reference = position_model_origin;
for (int thickness = 0; thickness < height; thickness ++)
{
for (int column = 0; column < width; column ++)
{
for (int line = 0; line < length ; line ++)
{
// Copy any parent transforms.
Matrix[] transforms = new Matrix[model_ground_land1.Bones.Count];
model_ground_land1.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model. A model can have multiple meshes, so loop.
foreach (ModelMesh mesh in model_ground_land1.Meshes)
{
// This is where the mesh orientation is set, as well
// as our camera and projection.
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = transforms[mesh.ParentBone.Index] *
Matrix.CreateRotationY(cubeGroundLand1_modelRotation) * Matrix.CreateTranslation(position_model_origin);
effect.View = View;
effect.Projection = Projection;
}
// Draw the mesh, using the effects set above.
mesh.Draw();
}
position_model_origin.X = (float)(line +1);
}
position_model_origin.X = pos_reference.X;
position_model_origin.Z = (float)(column +1);
}
position_model_origin.Z = pos_reference.Z;
position_model_origin.Y = (float)(thickness+1);
}
position_model_origin.Y = pos_reference.Y;
position_model_origin = pos_reference;
}
Thank you in advance for your help. I lose patience (over a whole weekend ^ ^)
It's Z-fighting. Z-buffer precision falling with distance so far objects have more "flickers" GPU can't figure out which polygon is on top because tail of the z-buffer value isn't precise enough to distinguish 2 almost equal values.
You have 6 ways to fix it:
Move geometry or do not display part that is below.
Use something like polygon offset in OpenGL
Use CPU z-sorting instead of z-buffer.
Use only one object with 2 textures instead of 2 objects + some shaders (i don't know what exactly you are trying to achieve)
Use larger z-buffer.
Move clip planes closer to each other it will increase precision.

Categories

Resources