I would like to check for collison between a sprite and a 3D Model.
After doing some searching I ended up with this code
BoundingBox handBox = new BoundingBox(new Vector3(handX, handY, 0), new Vector3(handX, handY, 0));
foreach (ModelMesh myModelMeshes in model.Meshes)
if (myModelMeshes.BoundingSphere.Intersects(handBox))
return true;
return false;
Here two values that should return false and not true
But the problem is that it's always true. Am I missing something obvious?
Related
I'm just new to stagexl, I know these are very basic questions, but I couldn't find an answer real quick, so I thought it would be nice to have this answered for anybody in the same position as I am.
How do I create a line from x to y in stagexl ?
And how do I create a circle with center x and radius y ?
You have to use the Shape display object. To draw a circle you just need to write this code:
var shape = new Shape();
shape.graphics.beginPath();
shape.graphics.circle(100, 100, 50);
shape.graphics.closePath();
shape.graphics.fillColor(Color.Red);
stage.addChild(shape);
To draw a line you have to do this:
var shape = new Shape();
shape.graphics.beginPath();
shape.graphics.moveTo(50, 50);
shape.graphics.lineTo(250, 150);
shape.graphics.closePath();
shape.graphics.strokeColor(Color.Red);
stage.addChild(shape);
You can learn more about it here:
http://www.stagexl.org/docs/wiki-articles.html?article=graphics
Please keep in mind that vector shapes are currently only supported with the Canvas2D renderer in StageXL. We are currently working on the WebGL renderer implementation too. You can use Shapes with the WebGL renderer too, if you use the applyCache method on the Shape. This will draw the Shape to a texture which can be used in WebGL too. This is also a much faster way to draw vector graphics.
Here is a full example, that you can also clone from gist if you want to try it out: https://gist.github.com/kasperpeulen/5cd660b5088311c64872
I'm not really sure if I do the WebGL example correct though, it seems like the WebGL graphic is blurry if I do it in this way.
import 'dart:html' as html;
import 'package:stagexl/stagexl.dart';
main() {
initWebGL();
initCanvas2D();
}
initWebGL() {
Stage stage = new Stage(html.querySelector('#WebGL'));
new RenderLoop().addStage(stage);
stage.addChild(circle(new Point(100, 100), 50));
stage.addChild(line(new Point(50, 50), new Point(250, 150)));
stage.applyCache(0,0,stage.sourceWidth,stage.sourceHeight);
}
initCanvas2D() {
Stage stage = new Stage(html.querySelector('#Canvas2D'),
options: new StageOptions()..renderEngine = RenderEngine.Canvas2D);
new RenderLoop().addStage(stage);
stage.addChild(circle(new Point(100, 100), 50));
stage.addChild(line(new Point(50, 50), new Point(250, 150)));
}
Shape line(Point from, Point to, {color: Color.Black}) {
return new Shape()
..graphics.beginPath()
..graphics.moveTo(from.x, from.y)
..graphics.lineTo(to.x, to.y)
..graphics.closePath()
..graphics.strokeColor(color);
}
Shape circle(Point<num> point, num radius, {color: Color.Black}) {
return new Shape()
..graphics.beginPath()
..graphics.circle(point.x, point.y, radius)
..graphics.closePath()
..graphics.fillColor(color);
}
I want to use class BoundingBox in XNA 4.0 to check collision between cube with cube or cube with sphere? I know about BoundingSphere but I don't know use to BoundingBox. Have any good sample about this! Thanks!
You make boundingboxes like this:
Vector3 CenterOfBox = new Vector3(10,10,10);
int Width = 10;
int Height = 10;
BoundingBox BoundingBox1 = new BoundingBox(CenterOfBox - new Vector(Width/2,Height/2,Width/2),CenterOfBox + new Vector(Width/2,Height/2,Width/2));
More info: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.boundingbox.boundingbox.aspx
Lets say you have BoundingBox1 and BoundingBox2
Then you can check if they intersect with:
if(BoundingBox1.Intersect(BoundingBox2))
{
//They hit
}
else
{
//They don't hit
}
You can also pass a BoundingSphere in the Intersect function
More info: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.boundingbox.intersects.aspx
So I have this Panel class. It's a little like a Window where you can resize, close, add buttons, sliders, etc. Much like the status screen in Morrowind if any of you remember. The behavior I want is that when a sprite is outside of the panel's bounds it doesn't get drawn and if it's partially outside only the part inside gets drawn.
So what it does right now is first get a rectangle that represents the bounds of the panel, and a rectangle for the sprite, it finds the rectangle of intersection between the two then translates that intersection to the local coordinates of the sprite rectangle and uses that for the source rectangle. It works and as clever as I feel the code is I can't shake the feeling that there's a better way to do this. Also, with this set up I cannot utilize a global transformation matrix for my 2D camera, everything in the "world" must be passed a camera argument to draw. Anyway, here's the code I have:
for the Intersection:
public static Rectangle? Intersection(Rectangle rectangle1, Rectangle rectangle2)
{
if (rectangle1.Intersects(rectangle2))
{
if (rectangle1.Contains(rectangle2))
{
return rectangle2;
}
else if (rectangle2.Contains(rectangle1))
{
return rectangle1;
}
else
{
int x = Math.Max(rectangle1.Left, rectangle2.Left);
int y = Math.Max(rectangle1.Top, rectangle2.Top);
int height = Math.Min(rectangle1.Bottom, rectangle2.Bottom) - Math.Max(rectangle1.Top, rectangle2.Top);
int width = Math.Min(rectangle1.Right, rectangle2.Right) - Math.Max(rectangle1.Left, rectangle2.Left);
return new Rectangle(x, y, width, height);
}
}
else
{
return null;
}
}
and for actually drawing on the panel:
public void DrawOnPanel(IDraw sprite, SpriteBatch spriteBatch)
{
Rectangle panelRectangle = new Rectangle(
(int)_position.X,
(int)_position.Y,
_width,
_height);
Rectangle drawRectangle = new Rectangle();
drawRectangle.X = (int)sprite.Position.X;
drawRectangle.Y = (int)sprite.Position.Y;
drawRectangle.Width = sprite.Width;
drawRectangle.Height = sprite.Height;
if (panelRectangle.Contains(drawRectangle))
{
sprite.Draw(
spriteBatch,
drawRectangle,
null);
}
else if (Intersection(panelRectangle, drawRectangle) == null)
{
return;
}
else if (Intersection(panelRectangle, drawRectangle).HasValue)
{
Rectangle intersection = Intersection(panelRectangle, drawRectangle).Value;
if (Intersection(panelRectangle, drawRectangle) == drawRectangle)
{
sprite.Draw(spriteBatch, intersection, intersection);
}
else
{
sprite.Draw(
spriteBatch,
intersection,
new Rectangle(
intersection.X - drawRectangle.X,
intersection.Y - drawRectangle.Y,
intersection.Width,
intersection.Height));
}
}
}
So I guess my question is, is there a better way to do this?
Update: Just found out about the ScissorRectangle property. This seems like a decent way to do this; it requires a RasterizerState object to be made and passed into the spritebatch.Begin overload that accepts it. Seems like this might be the best bet though. There's also the Viewport which I can apparently change around. Thoughts? :)
There are several ways to limit drawing to a portion of the screen. If the area is rectangular (which seems to be the case here), you could set the viewport (see GraphicsDevice) to the panel's surface.
For non-rectangular areas, you can use the stencil buffer or use some tricks with the depth buffer. Draw the shape of the surface in the stencil buffer or the depth buffer, set your render state to draw only pixels located in the shape you just rendered in the stencil/depth buffer, finally render your sprites.
One way of doing this is simple per-pixel collision. Although this is a bad idea if the sprites are large or numerous, this can be a very easy and fast way to get the job done with small sprites. First, do a bounding circle or bounding square collision check against the panel to see if you even need to do per-pixel detection.
Then, create a contains method that checks if the position, scale, and rotation of the sprite put it so far inside the panel that it must be totally enclosed by the panel, so you don't need per-pixel collision in that case. This can be done pretty easily by just creating a bounding square that has the width and height of the length of the sprite's diagonal, and checking for collision with that.
Finally, if both of these fail, we must do per-pixel collision. Go through and check against every pixel in the sprite to see if it is within the bounds of the panel. If it isn't set the alpha value of the pixel to 0.
Thats it.
I am pulling my hair out over this mouse picking thing. I do not know if the problem lies in my Ray calculation or my BoundingSpheres, anyway here's the code for my ray calculations:
public Ray CalculateRay(InputManager input)
{
Vector3 nearSource = new Vector3(input.CurrentMousePosition, 0f);
Vector3 farSource = new Vector3(input.CurrentMousePosition, 1f);
Vector3 nearPoint = Engine.Device.Viewport.Unproject(nearSource, _projectionMatrix,
_viewMatrix, Matrix.Identity);
Vector3 farPoint = Engine.Device.Viewport.Unproject(farSource,
_projectionMatrix, _viewMatrix, Matrix.Identity);
Vector3 direction = farPoint - nearPoint;
direction.Normalize();
return new Ray(nearPoint, direction);
}
and for the intersection check:
public bool RayIntersectsModel()
{
foreach (ModelMesh mesh in _model.Meshes)
{
BoundingSphere sphere = mesh.BoundingSphere;
sphere.Center = _position;
Ray ray = Engine.Camera.CalculateRay(Engine.Input);
if (sphere.Intersects(ray) != null)
{
return true;
}
}
return false;
}
It's not like it isn't working at all but it seems to be very inaccurate... or something. The models are just spheres, very simple. Any help or insight would be greatly appreciated!
Thanks!
Well, when I was transforming my bounding sphere I was first applying the world matrix then the bone transforms. This seems to put the bounding sphere in the wrong place. Switching it to first applying the bone transforms THEN the world matrix did it.
So I have a XNA application set up. The camera is in first person mode, and the user can move around using the keyboard and reposition the camera target with the mouse. I have been able to load 3D models fine, and they appear on screen no problem. Whenever I try to draw any primitive (textured or not), it does not show up anywhere on the screen, no matter how I position the camera.
In Initialize(), I have:
quad = new Quad(Vector3.Zero, Vector3.UnitZ, Vector3.Up, 2, 2);
quadVertexDecl = new VertexDeclaration(this.GraphicsDevice, VertexPositionNormalTexture.VertexElements);
In LoadContent(), I have:
quadTexture = Content.Load<Texture2D>(#"Textures\brickWall");
quadEffect = new BasicEffect(this.GraphicsDevice, null);
quadEffect.AmbientLightColor = new Vector3(0.8f, 0.8f, 0.8f);
quadEffect.LightingEnabled = true;
quadEffect.World = Matrix.Identity;
quadEffect.View = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
quadEffect.Projection = this.Projection;
quadEffect.TextureEnabled = true;
quadEffect.Texture = quadTexture;
And in Draw() I have:
this.GraphicsDevice.VertexDeclaration = quadVertexDecl;
quadEffect.Begin();
foreach (EffectPass pass in quadEffect.CurrentTechnique.Passes)
{
pass.Begin();
GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(
PrimitiveType.TriangleList,
quad.Vertices, 0, 4,
quad.Indexes, 0, 2);
pass.End();
}
quadEffect.End();
I think I'm doing something wrong in the quadEffect properties, but I'm not quite sure what.
I can't run this code on the computer here at work as I don't have game studio installed. But for reference, check out the 3D audio sample on the creator's club website. They have a "QuadDrawer" in that project which demonstrates how to draw a textured quad in any position in the world. It's a pretty nice solution for what it seems you want to do :-)
http://creators.xna.com/en-US/sample/3daudio