I have a window form with xna included in a control, right now I have two models in one area of the screen. The thing is I need to rotate both models at the same time, I can rotate one object wich is a tank and the other is the skybox(landscape) rendered in a box.
The tank move with data provided by a serial port which is in real time, the tanks move perfectly, but I can't rotate the map.
(the ground should be moving along with the tank).
http://i61.tinypic.com/2efqrvc.jpg
I use this code to render the landscape:
private void SkyBoxRender()
{
RasterizerState originalRasterizerState = GraphicsDevice.RasterizerState;
RasterizerState rasterizerState = new RasterizerState();
rasterizerState.CullMode = CullMode.None;
GraphicsDevice.RasterizerState = rasterizerState;
aspectRatio = GraphicsDevice.Viewport.AspectRatio;
orientacion = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(-85.0f), MathHelper.ToRadians(TiempoReal.rollPitch[1]), MathHelper.ToRadians(TiempoReal.rollPitch[0]));
cameraPositionSkyBox = distance * new Vector3((float)Math.Sin(angle), 0, (float)Math.Cos(angle));
foreach (EffectPass pass in skyBoxEffect.CurrentTechnique.Passes)
{
pass.Apply();
foreach (ModelMesh mesh in skyBox.Meshes)
{
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect = skyBoxEffect;
part.Effect.Parameters["World"].SetValue(Matrix.CreateScale(50.0f) * Matrix.CreateTranslation(cameraPositionSkyBox));
part.Effect.Parameters["View"].SetValue(view);
part.Effect.Parameters["Projection"].SetValue(Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f));
part.Effect.Parameters["SkyBoxTexture"].SetValue(skyBoxTexture);
part.Effect.Parameters["CameraPosition"].SetValue(cameraPositionSkyBox);
}
mesh.Draw();
}
}
GraphicsDevice.RasterizerState = originalRasterizerState;
}
I think the problem is in the line part.Effect.Parameters["World"].SetValue.....
I don't know what to put there to make the map rotate using all the axis.
I rotate the tank using this code:
orientacion = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(-85.0f),
MathHelper.ToRadians(floatAngle1), MathHelper.ToRadians(floatAngle2));
If you look at the second line you can notice that I use angles to rotate the tank (it have to be in that way...), so any idea or suggestion?
Update:
Solved, how?
in the SkyBoxRender Method I added the following:
orientacionCamara = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(0.0f), MathHelper.ToRadians(floatAngle1), MathHelper.ToRadians(floatAngle2));
then I archived to move the camera in the map using this:
part.Effect.Parameters["View"].SetValue(Matrix.CreateLookAt(yourCameraPosition) * orientacionCamara);
Now to move the camera at the same time with the same angles like the model I rotate the model, not the camera in this time.
private void BeginRender3D()
{
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
Matrix[] transforms = new Matrix[modelo.Bones.Count];
modelo.CopyAbsoluteBoneTransformsTo(transforms);
**orientacion** = Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(-85.0f), MathHelper.ToRadians(floatAngle1), MathHelper.ToRadians(floatAngle2);
foreach (ModelMesh mesh in modelo.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
effect.World = transforms[mesh.ParentBone.Index] * **orientacion**; //* orientacion
effect.View = Matrix.CreateLookAt(camaraPosicion, Vector3.Zero, Vector3.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);
}
mesh.Draw();
}
fps++;
}
I hope It can help to anyone, thanks for the suggestion guys.
You could rotate the map by the orientation by multiplying the world parameter in the skyboxeffect by "orientacion". Still, you would have to make sure it rotates around the tanks position, by changing the whole line to this:
part.Effect.Parameters["World"].SetValue(Matrix.CreateScale(50.0f) * matrix.createtranslation(TankPosition) * orientacion * Matrix.CreateTranslation(cameraPositionSkyBox - TankPosition));
assuming "TankPosition" would be the position of your tank.
I'm not sure what you're trying to achieve, but if you're trying to simulate rotating a camera round the tank, I would just rotate the camera around the tank, by setting
view = matrix.CreatePerspectiveFieldOfView()
Read up on it here: http://msdn.microsoft.com/en-us/library/bb195667.aspx
Related
Currently in my game i want trying to move my object towards both x axis and y axis.As I also wanted to put it into center ,I have put a camera.Here is my Camera code-
public class Camera
{
public Matrix transform;
public Viewport view;
public Vector2 origin;
Vector2 baseScreenSize = new Vector2(1136, 720);
float horScaling ;
float verScaling ;
Vector3 screenScalingFactor ;
public Camera(Viewport newView)
{
view = newView;
horScaling = view.Width / baseScreenSize.X;
verScaling = view.Height / baseScreenSize.Y;
screenScalingFactor = new Vector3(horScaling, verScaling, 1);
}
public void update(GameTime gt, ball pl)
{
origin = new Vector2(pl.Position.X + (pl.ballRectangle.Width / 2) - 400, 0);
transform = Matrix.CreateScale(1,1,0) *
Matrix.CreateTranslation(new Vector3(-origin.X, -origin.Y, 0));
}
}
and in Game1.cs file as usual in begin statement i am putting this-
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, cm.transform*globalTransformation);
ba.Draw(spriteBatch, Color.White);
spriteBatch.End();
Here ba is the object of ball,its just have moving x and y functionalities.
In a separate begin,end statement ,I am drawing rest all of the objects-
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null, globalTransformation);
spriteBatch.Draw(mainMenu, new Vector2(0, 0), Color.White);
spriteBatch.Draw(mainMenu1, new Vector2(450, 100), Color.White);
spriteBatch.End();
Here Have applied globaltransformation to acheive independent screen resolution(similar codes like in Camera.cs).
Rest of the objects are working as expected,But intersections of camera object and rest of the objects is not working as expected.
I guess this is due to resolution independency is not applied to Camera object(I am not sure).I have tried lot of codes after searching internet,but none of them is working as expected.
In a simple words-I want to clone this game-
https://play.google.com/store/apps/details?id=com.BitDimensions.BlockyJump
If you see main player is moving along x and y axis,but due to camera its in constant position,but the obstacles are not in camera,How to acheive the intersection between obejct which is in camera draw and objects which are not in camera in this case
Request all to help,I am stuck here from long time...
Never thought this will be this much of easy...Searched all over internet,in
most of the codes they were saying we need to inverse the camera transform.
But this is not the case.As from beginning I was saying my problem is intersection between camera object and non camera object,here is the answer-
First of all we need to find the positions of camera object to form a world space rectangle
Vector2 hj = Vector2.Transform(ba.Position, cm.transform);
Rectangle leftRectangleT1 =
new Rectangle((int)hj.X, (int)hj.Y, ba.tex.Width, ba.tex.Height);
Here ba is the camera object,we need to transform it to camera transform like above codes.
To get transform of ba in case pixel intersection,here is the codes-
Matrix ballTransform = Matrix.CreateTranslation(new Vector3(hj.X, hj.Y, 0.0f));
Thats it you have ball rectangle which is camera object to intersect with real world objects(non camera objects)
I don't understand your question per say, but from what I gathered, you want the camera to follow the target's position, and you also want independent screen resolutions?
Well, for the independent screen resolution, simply create a screen resolution handler that renders the scene to a RenderTarget2D as defined by your sizes. Then draw that to the screen.
For the camera movement. Try adjusting the camera's position to follow the target's position with an offset and slerp interpolation to prevent stuttering and smooth action.
void Update(float gameTime) {
Vector3 camTransform = Camera.Position + cameraTarget;
Vector3 newCameraPosition = Vector3.Slerp(cameraPosition, camTransform, 0.2f);
Camera.Position = newCameraPosition;
}
For your intersection problem try something along this
private bool intersects(rectangle1, rectangle2) {
return rectangle1.x >= rectangle2.x &&
rectangle1.y >= rectangle2.y &&
rectangle1.y <= rectangle2.y + rectangle2.h &&
rectangle1.x <= rectangle2.x + rectangle2.w;
}
private void checkIntersections(gameObjects[]) {
foreach (var obj in gameobjects) {
if (intersects(obj.rectangle, camera.rectangle){
handleIntersections(camera, obj);
}
}
}
In Unity, I'm trying to make my sprite go offscreen to the left and have it appear offscreen on the right or vice versa. I have my sprite move left or right (depending on user input) constantly for my gameplay by the way.
I take into account that the sprite needs to be fully offscreen before having it appear on the right side.
Here's my current code:
void Start ()
{
minXValueWorld = Camera.main.ScreenToWorldPoint(new Vector3(0,0,0)).x;
maxXValueWorld = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, 0, 0)).x;
playerSize = this.GetComponent<Renderer>().bounds.size;
}
void Move()
{
if (inputLeft)
{
this.transform.position -= new Vector3(speed * Time.deltaTime, 0, 0);
}
else
{
this.transform.position += new Vector3(speed * Time.deltaTime, 0, 0);
}
}
void OffscreenCheck()
{
Vector3 screenPos = Camera.main.WorldToScreenPoint(this.transform.position);
Vector3 maxWorldXWithPlayerSize = Camera.main.WorldToScreenPoint(new Vector3(maxXValueWorld,0,0) + playerSize/2);
Vector3 minWorldWithPlayerSize = Camera.main.WorldToScreenPoint(new Vector3(minXValueWorld,0,0) - playerSize/2);
if (screenPos.x < minWorldWithPlayerSize.x)
{
this.transform.position = new Vector3(maxWorldXWithPlayerSize.x, this.transform.position.y, this.transform.position.z);
}
if (screenPos.x > maxWorldXWithPlayerSize.x)
{
this.transform.position = new Vector3(minWorldWithPlayerSize.x, this.transform.position.y, this.transform.position.z);
}
}
Then the Move and OffscreenCheck are called in the Update function in order.
The problem with this code is that once my sprite goes fully offscreen on the left, it appears on the right offscreen, but it does not move left anymore.
Instead, it just teleports to the left or right offscreen positions. I do not see it move left or right across the screen anymore because of this.
I'm pretty sure that my code logic is just off. Does anyone know how to fix this issue?
Thanks
I think the following should work:
void OffscreenCheck()
{
Vector3 screenPos = Camera.main.WorldToScreenPoint(this.transform.position);
Vector3 maxWorldWithPlayerSize = new Vector3(maxXValueWorld + playerSize/2,0,0);
Vector3 minWorldWithPlayerSize = new Vector3(minXValueWorld - playerSize/2,0,0);
Vector3 maxScreenWithPlayerSize = Camera.main.WorldToScreenPoint(maxWorldWithPlayerSize);
Vector3 minScreenWithPlayerSize = Camera.main.WorldToScreenPoint(minWorldWithPlayerSize);
if (screenPos.x < minScreenWithPlayerSize.x)
{
this.transform.position = new Vector3(
maxWorldWithPlayerSize.x,
this.transform.position.y,
this.transform.position.z);
}
if (screenPos.x > maxScreenWithPlayerSize.x)
{
this.transform.position = new Vector3(
minWorldWithPlayerSize.x,
this.transform.position.y,
this.transform.position.z);
}
}
The above is a good illustration of why to be careful about how you name your variables. When I first looked at your code, I failed to connect the fact that while the variables had the word "World" in them, they were actually in screen coordinates. So I didn't notice the faulty assignment of the position, in which you used screen coordinates to assign an X coordinate in world coordinates.
In the above, I have separated the world and screen coordinate vectors into individual local variables. The screen coordinates are used for the off-screen comparison itself, while the world coordinates are used for actually moving the sprite to where you want.
Again, lacking a complete code example I'm not able to actually test the above and verify that it solves your problem. But I think it will.
I have an object in my game that has a few meshes and when I try to rotate either of the meshes either way, it only rotates it around world axis, and not its local axis. I have a rotation = Matrix.Identity in a class constructor. Every mesh has this class attached to it. Then this class also contains methods:
...
public Matrix Transform{ get; set; }
public void Rotate(Vector3 newRot)
{
rotation = Matrix.Identity;
rotation *= Matrix.CreateFromAxisAngle(rotation.Up, MathHelper.ToRadians(newRot.X));
rotation *= Matrix.CreateFromAxisAngle(rotation.Right, MathHelper.ToRadians(newRot.Y));
rotation *= Matrix.CreateFromAxisAngle(rotation.Forward, MathHelper.ToRadians(newRot.Z));
CreateMatrix();
}
private void CreateMatrix()
{
Transform = Matrix.CreateScale(scale) * rotation * Matrix.CreateTranslation(Position);
}
...
And now the Draw() method:
foreach (MeshProperties mesh in model.meshes)
{
foreach (BasicEffect effect in mesh.Mesh.Effects)//Where Mesh is a ModelMesh that this class contains information about
{
effect.View = cam.view;
effect.Projection = cam.projection;
effect.World = mesh.Transform;
effect.EnableDefaultLighting();
}
mesh.Mesh.Draw();
}
EDIT:
I am afraid either I screwed somewhere up, or your tehnique does not work, this is what I did. Whenever I move the whole object(Parent), I set its Vector3 Position; to that new value. I also set every MeshProperties Vector3 Position; to that value. And then inside CreateMatrix() of MeshProperties I did like so:
...
Transform = RotationMatrix * Matrix.CreateScale(x, y, z) * RotationMatrix * Matrix.CreateTranslation(Position) * Matrix.CreateTranslation(Parent.Position);
...
Where:
public void Rotate(Vector3 newRot)
{
Rotation = newRot;
RotationMatrix = Matrix.CreateFromAxisAngle(Transform.Up, MathHelper.ToRadians(Rotation.X)) *
Matrix.CreateFromAxisAngle(Transform.Forward, MathHelper.ToRadians(Rotation.Z)) *
Matrix.CreateFromAxisAngle(Transform.Right, MathHelper.ToRadians(Rotation.Y));
}
And Rotation is Vector3.
RotationMatrix and Transform are both set to Matrix.Identity in the constructor.
The problem is if I try to rotate around for example Y axis, he should rotate in a circle while "standing still". But he moves around while rotating.
I'm not entirely certain this is what you want. I'm assuming here you have an object, with some meshes and positions offset from the position and orientation of the main object position and you want to rotate the child object around its local axis relative to the parent.
Matrix.CreateTranslation(-Parent.Position) * //Move mesh back...
Matric.CreateTranslation(-Mesh.PositionOffset) * //...to object space
Matrix.CreateFromAxisAngle(Mesh.LocalAxis, AngleToRotateBy) * //Now rotate around your axis
Matrix.CreateTranslation(Mesh.PositionOffset) * //Move the mesh...
Matrix.CreateTranslation(Parent.Position); //...back to world space
Of course you usually store a transform matrix which transforms a mesh from object space to world space in one step, and you'd also store the inverse. You also store the mesh in object coordinates all the time and only move it into world coordinate for rendering. This would simplify things a little:
Matrix.CreateFromAxisAngle(Mesh.LocalAxis, AngleToRotateBy) * //We're already in object space, so just rotate
ObjectToWorldTransform *
Matrix.CreateTranslation(Parent.Position);
I think you could simply set Mesh.Transform in your example to this and be all set.
I hope this is what you were looking for!
The problem was that, when I was exporting model as .FBX the pivot point wasnt in model centre. Thus making the model move while rotating.
Am I doing the following right?
Well obviously not cause otherwise I wont be posting a question here, but I'm trying to do a Quaternion rotation of a model around another model.
Lets say I have a box model that has a vector3 position and a float rotation angle.
I also have a frustum shaped model that is pointing towards the box model, with its position lets say 50 units from the box model. The frustum also has a vector3 position and a Quaternion rotation.
In scenario 1, the box and frustum are "unrotated". This is all fine and well.
In scenario 2, I rotate the box only and I want the frustum to rotate with it (kinda like a chase camera) with the frustum always pointing directly at the box and at the same distance from the box as in the unrotated distance. Obviously if I just rotate the model and the frustum by using Matrix.CreateRotationY() for both the box and the frustum, the frustum is slightly offset to the side.
So I thought a Quaternion rotation of the frustum around the box would be best?
To this end I have tried the following, with no luck. It draws my models on the screen, but it also draws what looks like a giant box to the screen and no matter how far away I move the camera the box is always in the way
For the purpose of testing, I have 3 boxes and their 3 associated frustums
In my Game1 class I initialize the box[0] with positions and rotations
boxObject[0].Position = new Vector3(10, 10, 10);
boxObject[1].Position = new Vector3(10, 10, 10);
boxObject[2].Position = new Vector3(10, 10, 10);
boxObject[0].Rotation = 0.0f;
boxObject[1].Rotation = 45.0f;
boxObject[2].Rotation = -45.0f;
So all 3 boxes drawn at the same position but at different angles.
Then to do the frustums, I initiate their position:
float f = 50.0f;
frustumObject[0].Position = new Vector3(boxObject[0].Position.X,
boxObject[0].Position.Y, boxObject[0].Position.Z + f);
frustumObject[1].Position = new Vector3(boxObject[1].Position.X,
boxObject[1].Position.Y, boxObject[1].Position.Z + f);
frustumObject[2].Position = new Vector3(boxObject[2].Position.X,
boxObject[2].Position.Y, boxObject[2].Position.Z + f);
And then try and rotate around their associated box model:
frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
boxObject[0].Position.Y, boxObject[0].Position.Z + f, 0);
frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
boxObject[0].Position.Y, boxObject[0].Position.Z + f, 45);
frustumObject[0].ModelRotation = new Quaternion(boxObject[0].Position.X,
boxObject[0].Position.Y, boxObject[0].Position.Z + f, -45);
And finally, to draw the models, I Draw() them in my GameModel class which also has:
public Model CameraModel { get; set; }
public Vector3 Position { get; set; }
public float Rotation { get; set; }
public Quaternion ModelRotation { get; set; }
public void Draw(Matrix view, Matrix projection)
{
transforms = new Matrix[CameraModel.Bones.Count];
CameraModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model
foreach (ModelMesh myMesh in CameraModel.Meshes)
{
foreach (BasicEffect myEffect in myMesh.Effects)
{
// IS THIS CORRECT?????
myEffect.World = transforms[myMesh.ParentBone.Index] *
Matrix.CreateRotationY(Rotation) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(Position);
myEffect.View = view;
myEffect.Projection = projection;
myEffect.EnableDefaultLighting();
myEffect.SpecularColor = new Vector3(0.25f);
myEffect.SpecularPower = 16;
}
myMesh.Draw();
}
}
Can anyone spot where I am going wrong? Is it because I am doing 2 types of rotations n the Draw()?
myEffect.World = transforms[myMesh.ParentBone.Index] *
Matrix.CreateRotationY(Rotation) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(Position);
From a quick glance, it would be best to create your Quaternions using a static create method such as Quaternion.CreateFromAxisAngle(Vector3. UnitY, rotation). The values of X,Y,Z and W of a Quaternion do not relate to position in any way. The handy static methods take care of the tricky math.
In your situation it appears as though you want to keep the frustum pointing at the same side of the box as the box rotates, therefore rotating the frustum about the box. This requires a slightly different approach to the translation done in your draw method.
In order to rotate an object about another, you first need to translate the object so that the centre of the desired rotation is at the origin. Then rotate the object and translate it back by the same amount as the first step.
So in you situation, something like this should do it (untested example code to follow);
// Construct the objects
boxObject.Position = new Vector3(10, 10, 10);
boxObject.Rotation = 45.0f;
frustumObject.Position = new Vector3(0, 0, 50f); // Note: this will be relative to the box (makes the math a bit simpler)
frustumObject.TargetPosition = boxObject.Position;
frustumObject.ModelRotation = Quaternion.CreateFromAxisAngle(Vector3. UnitY, boxObject.Rotation); // Note: this rotation angle may need to be in radians.
// Box Draw()
// Draw the box at its position, rotated about its centre.
myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(Position) * Matrix.CreateRotationY(Rotation);
// Frustum Draw()
// Draw the frustum facing the box and rotated about the boxes centre.
myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(Position) * Matrix.CreateFromQuaternion(ModelRotation) * Matrix.CreateTranslation(TargetPosition);
Assumptions:
The box rotates about its own centre
The frustum stays facing the box and rotates around the boxes centre
Hope this helps.
i just try draw a simple 3d model(many model (.fbx) tested) with basicEffect in xna 4.0 , and there is no other object like 2d spritebatchs or text or ...
but it does not shown correctly , i searched it and did some solution but no one work
like set
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
although i did not draw anything else ! and what is funny i already work with 3d model without problem !
here is my draw code and a result screenshot
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
graphics.GraphicsDevice.BlendState = BlendState.Opaque;
graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
foreach (ModelMesh mesh in m_Model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
BasicEffect effect = (BasicEffect)meshPart.Effect;
effect.View = Matrix.CreateLookAt(new Vector3(0, 100, 1000), Vector3.Zero, Vector3.Up);
effect.World = bones[mesh.ParentBone.Index] * (Matrix.CreateWorld(Vector3.Zero, Vector3.Right, Vector3.Up));
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.0001f, 1000000f);
effect.EnableDefaultLighting();
}
mesh.Draw();
}
base.Draw(gameTime);
}
ty for your time
The near clip value in your projection Matrix is most likely causing this. Try setting it to 1.0f instead of 0.0001f. If that doesn't solve the problem completely, bring the far clip down to something like 10000f.
edit - noticing that your camera is over 1000 units away from your model, you can even set the near clip to 5f or 10f to gain depth read precision if needed.
Its the problem of depth buffer, you are using the spritebrite to draw something which changes your default depth buffer off.
Make it on before drawing 3d model mesh.
After calling SpriteBatch.End(), add this code:
device.DepthStencilState = DepthStencilState.Default;