I drew a line parallel to the Z axis in sharpgl. I set the camera above the Z axis, so I thought I would see 1 point, but I don't see it. Later I want to draw a large number of these lines side by side, now I'm trying on one.
Camera settings:
gl.Ortho (0, 1595, 0, 1000, -30, 80);
gl.LookAt(0.0f, 0.0f, 90.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
Line Drawing:
gl.LineWidth (100.0f);
gl.Begin (OpenGL.GL_LINES);
gl.Color (0, 0, 0);
gl.Vertex (600, 600, 30);
gl.Vertex (600, 600, 50);
gl.End ();
gl.Flush ();
When I draw a line at a different angle, you can see it:
gl.Vertex (180, 15, 20);
gl.Vertex (800, 800, 20);
When I draw only a point, I also see it:
gl.PointSize (100.0f);
gl.Begin (OpenGL.GL_POINTS);
gl.Color (0, 0, 0);
gl.Vertex (800, 800, 20);
gl.End ();
I need to see the line. Do I need to add a point to the beginning and end of a line, or is it just something to set the line to be visible?
Related
I have a class called Cube in which I render a basic cube to the screen. I've got it working as far as rendering a basic cube of any scale at origin 0, 0, 0. However, if I want to move the cube, scale any of its axes, or rotate the cube; I have no idea where to begin since I have to achieve this within a Vertex object.
struct Vertex {
Vector3 Position;
Vector3 Normal;
Vector2 TextureUV;
Color Color;
}
To render a cube of size 1000000 I simply fill the Position properties with that value (with regards to negative and positive values to generate the faces).
new Vertex(new Vector3(-1000000, -1000000, -1000000), new Vector3(-1, -1, -1), Color.White);
Cube has four properties:
Position (Vector3).
Scale (Vector3).
Rotation (Vector3).
Color (SharpDX.Color).
My question is, as I am specifying Vertex locations, how can I calculate the new position when rotation and position are applied?
I attempted basic subtraction and addition which simply scales the cube differently and the origin remains at 0, 0, 0 (please don't mind the shorthand).
new Vertex(new Vector3(P.X - S.X, P.Y - S.Y, P.Z - S.Z), new Vector3(1, 1, 1), Color.White);
The above isn't the exact code as it is on a different computer currently.
If you need additional details, please let me know and I will clarify.
The Question
How can I set the position of the vertices based on the supplied position, scale, and rotation vectors?
Test Case
The following test cases are for position only and are to show you how I will test the answers given.
// Renders at origin.
Cube myCube = new Cube(new Vector3(0, 0, 0), new Vector3(100, 100, 100), Color.White);
// Renders to the left.
Cube myCubeLeft = new Cube(new Vector3(-250, 0, 0), new Vector3(100, 100, 100), Color.White);
// Renders to the right.
Cube myCubeRight = new Cube(new Vector3(250, 0, 0), new Vector3(100, 100, 100), Color.White);
// Renders above.
Cube myCubeUp = new Cube(new Vector3(0, -250, 0), new Vector3(100, 100, 100), Color.White);
// Renders below.
Cube myCubeDown = new Cube(new Vector3(0, 250, 0), new Vector3(100, 100, 100), Color.White);
I will add rotation and scaling test cases later if needed.
I am drawing two wireframe spheres that I would like to follow the player around. When the player moves the two gizmos follow, however, when I rotate only one of the gizmos rotates.
The broken gizmo code looks like this, it should have an offset of 45:
void OnDrawGizmosSelected() {
Gizmos.color = new Color(1, 0, 0);
Gizmos.matrix = Matrix4x4.TRS(transform.position, Quaternion.Euler(transform.rotation.x, transform.rotation.y + 45, transform.rotation.z), Vector3.one);
Gizmos.DrawWireSphere(Vector3.zero, 5f);
}
For reference here is the whole block with both gizmos:
void OnDrawGizmosSelected() {
Gizmos.color = new Color(1, 0, 0);
// This one works
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
Gizmos.DrawWireSphere(Vector3.zero, 5f);
// This one does not work
Gizmos.matrix = Matrix4x4.TRS(transform.position, Quaternion.Euler(transform.rotation.x, transform.rotation.y + 45, transform.rotation.z), Vector3.one);
Gizmos.DrawWireSphere(Vector3.zero, 5f);
}
Default with no rotation (How I want it to stay when rotating)
Rotation around the Y Axis
Quaternion has 4 components, x,y,z and w.
Just putting x,y and z into Quaternion.Euler will not give you the expected results.
Instead, use transform.rotation.eulerAngles
void OnDrawGizmosSelected()
{
Gizmos.color = new Color(1, 0, 0);
// This one works
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
Gizmos.DrawWireSphere(Vector3.zero, 5f);
// This one works now :)
Gizmos.matrix = Matrix4x4.TRS(transform.position, Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y + 45, transform.rotation.eulerAngles.z), Vector3.one);
Gizmos.DrawWireSphere(Vector3.zero, 5f);
}
EDIT:
Okay, that fixes the Y value, but X and Z are still broken. They move but not in the proper direction.
Then try
// This works even better
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one) * Matrix4x4.Rotate(Quaternion.Euler(0, 45, 0));
I'm having trouble setting up my camera in 3D space.
Here's my code:
private void SetupViewPort()
{
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, 1000,0,1000, 0, 1);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
Vector3d eyePos = new Vector3d(0, 0, 1);
Vector3d point = new Vector3d(500, 500, 0.01);
Vector3d up = new Vector3d(0, 0 , 1);
Matrix4d mat = Matrix4d.LookAt(eyePos, point, up);
//mat.Invert();
GL.LoadMatrix(ref mat);
}
I'm expecting to see shapes that I've drawn onto the 2D plane. But I get a blank screen every time.
Here's the code where my shapes are drawn:
private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded)
return;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest);
GL.DepthMask(true);
GL.ClearDepth(1.0);
GL.Color3(Color.Yellow);
GL.Begin(PrimitiveType.Triangles);
GL.Vertex2(0, 0);
GL.Vertex2(0, 600);
GL.Vertex2(600, 600);
GL.Vertex2(100, 100);
GL.Vertex2(50, 70);
GL.Vertex2(200, 100);
GL.End();
glControl1.SwapBuffers();
}
An orthonormal projection matrix and a lookAt view matrix don't play well together. Since you are drawing 2D just leave the lookAt matrix out and use the identity matrix.
I'm trying to make a cooldown visual for my game when actions are used. I want the button that I have that is the action to be filled with a grayish semi-transparent color that "unwinds" clockwise (if that makes sense). Games like World of Warcraft do this where the time it takes for the cooldown is the time the angle of the unwinding takes. You can see an example here. In this picture the cooldown is more than 1/2 way finished.
http://www.vbforums.com/attachment.php?attachmentid=101705&stc=1&d=1372575930
I'm playing around with arc drawing but this doesn't give me what I'm after.
if (globalCD)
{
Pen p = new Pen(Color.FromArgb(125, 255, 0, 0), 10);
//e.Graphics.DrawLine(p, new Point(0, 0), new Point(10, 10));
e.Graphics.DrawArc(p, new Rectangle(0, 0, 64, 64), 270, 270);
}
In general, the Graphics class has a FillX method for each DrawX method. In this case the result is sufficiently different that the names actually change a bit, but you likely want the FillPie method.
if (globalCD)
{
Pen p = new Pen(Color.FromArgb(125, 255, 0, 0), 10);
//e.Graphics.DrawLine(p, new Point(0, 0), new Point(10, 10));
e.Graphics.FillPie(p, new Rectangle(0, 0, 64, 64), 270, 270);
}
I'm trying to draw a triangle using this code in XNA:
VertexPositionColor[] vertices = new VertexPositionColor[3];
vertices[0].Position = new Vector3(-0.5f, -0.5f, 0f);
vertices[0].Color = Color.Red;
vertices[1].Position = new Vector3(0, 0.5f, 0f);
vertices[1].Color = Color.Green;
vertices[2].Position = new Vector3(0.5f, -0.5f, 0f);
vertices[2].Color = Color.Yellow;
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleList, vertices, 0, 1);
However, as soon as I run it, application closes, and InvalidOperationException is thrown. It's WP7 application. Am I missing something? Thanks for your help in advance.
The documentation says that DrawUserPrimitives throws InvalidOperationException when:
A valid vertex shader and pixel shader was not set before calling DrawUserPrimitives. Both a valid vertex shader and pixel shader (or valid effect) must be set on the device before any draw operations may be performed.
(It also says it will throw if your vertices are invalid - but they look ok to me.)
You need to set an Effect on the graphics device. Specifically you need to call EffectPass.Apply before you call DrawUserPrimitives. An easy way to start is with BasicEffect. Here is some code, suitable to put in the Draw method, to illustrate this:
// These three lines are required if you use SpriteBatch, to reset the states that it sets
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
// Transform your model to place it somewhere in the world
basicEffect.World = Matrix.CreateRotationZ(MathHelper.PiOver4) * Matrix.CreateTranslation(0.5f, 0, 0); // for sake of example
//basicEffect.World = Matrix.Identity; // Use this to leave your model at the origin
// Transform the entire world around (effectively: place the camera)
basicEffect.View = Matrix.CreateLookAt(new Vector3(0, 0, -3), Vector3.Zero, Vector3.Up);
// Specify how 3D points are projected/transformed onto the 2D screen
basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45),
(float)GraphicsDevice.Viewport.Width / (float)GraphicsDevice.Viewport.Height, 1.0f, 100.0f);
// Tell BasicEffect to make use of your vertex colors
basicEffect.VertexColorEnabled = true;
// I'm setting this so that *both* sides of your triangle are drawn
// (so it won't be back-face culled if you move it, or the camera around behind it)
GraphicsDevice.RasterizerState = RasterizerState.CullNone;
// Render with a BasicEffect that was created in LoadContent
// (BasicEffect only has one pass - but effects in general can have many rendering passes)
foreach(EffectPass pass in basicEffect.CurrentTechnique.Passes)
{
// This is the all-important line that sets the effect, and all of its settings, on the graphics device
pass.Apply();
// Here's your code:
VertexPositionColor[] vertices = new VertexPositionColor[3];
vertices[0].Position = new Vector3(-0.5f, -0.5f, 0f);
vertices[0].Color = Color.Red;
vertices[1].Position = new Vector3(0, 0.5f, 0f);
vertices[1].Color = Color.Green;
vertices[2].Position = new Vector3(0.5f, -0.5f, 0f);
vertices[2].Color = Color.Yellow;
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleList, vertices, 0, 1);
}
That exception (InvalidOperationException) is typically thrown when a component finds it's in an unexpected state. So in your case, make sure GraphicsDevice does not need some other properties set before you invoke DrawUserPrimitives.