The hidden surface removal is not working as expected - c#

I am using SharpGL library.
The following source code draws several hundred solid spheres at various locations -
// Initialization routine.
void setup()
{
gl.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.Enable(OpenGL.GL_DEPTH_TEST); // Enable depth testing.
// Turn on OpenGL lighting.
gl.Enable(OpenGL.GL_LIGHTING);
// Light property vectors.
float []lightAmb = { 0.0f, 0.0f, 0.0f, 1.0f };
float[]lightDifAndSpec0 = { 1.0f, 1.0f, 1.0f, 1.0f };
float[]lightDifAndSpec1 = { 0.0f, 1.0f, 0.0f, 1.0f };
float[]globAmb = { 0.2f, 0.2f, 0.2f, 1.0f };
// Light0 properties.
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, lightAmb);
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, lightDifAndSpec0);
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_SPECULAR, lightDifAndSpec0);
// Light1 properties.
gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_AMBIENT, lightAmb);
gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_DIFFUSE, lightDifAndSpec1);
gl.Light(OpenGL.GL_LIGHT1, OpenGL.GL_SPECULAR, lightDifAndSpec1);
gl.Enable(OpenGL.GL_LIGHT0); // Enable particular light source.
gl.Enable(OpenGL.GL_LIGHT1); // Enable particular light source.
gl.LightModel(OpenGL.GL_LIGHT_MODEL_AMBIENT, globAmb); // Global ambient light.
gl.LightModel(OpenGL.GL_LIGHT_MODEL_LOCAL_VIEWER, OpenGL.GL_TRUE); // Enable local viewpoint
// Cull back faces.
gl.Enable(OpenGL.GL_CULL_FACE);
gl.CullFace(OpenGL.GL_BACK);
}
//http://www.java2s.com/example/java/javax.media.opengl/opengl-method-to-draw-a-sphere-in-opengl.html
void drawSphere(Point3d c, double r, int n)
{
int i, j;
double theta1, theta2, theta3;
Point3d e = new Point3d();
Point3d p = new Point3d();
if (c == null)
{
c = new Point3d(0, 0, 0);
}//from w ww .j ava2 s . c o m
double twoPi = Math.PI * 2;
double piD2 = Math.PI / 2;
if (r < 0)
r = -r;
if (n < 0)
n = -n;
if (n < 4 || r <= 0)
{
gl.Begin(OpenGL.GL_POINTS);
gl.Vertex(c.X, c.Y, c.Z);
gl.End();
return;
}
for (j = 0; j < n / 2; j++)
{
theta1 = j * twoPi / n - piD2;
theta2 = (j + 1) * twoPi / n - piD2;
gl.Begin(OpenGL.GL_QUAD_STRIP);
// gl.glBegin(GL.GL_TRIANGLE_STRIP);
for (i = 0; i <= n; i++)
{
theta3 = i * twoPi / n;
e.X = Math.Cos(theta2) * Math.Cos(theta3);
e.Y = Math.Sin(theta2);
e.Z = Math.Cos(theta2) * Math.Sin(theta3);
p.X = c.X + r * e.X;
p.Y = c.Y + r * e.Y;
p.Z = c.Z + r * e.Z;
gl.Normal(e.X, e.Y, e.Z);
gl.TexCoord(i / (double)n, 2 * (j + 1) / (double)n);
gl.Vertex(p.X, p.Y, p.Z);
e.X = Math.Cos(theta1) * Math.Cos(theta3);
e.Y = Math.Sin(theta1);
e.Z = Math.Cos(theta1) * Math.Sin(theta3);
p.X = c.X + r * e.X;
p.Y = c.Y + r * e.Y;
p.Z = c.Z + r * e.Z;
gl.Normal(e.X, e.Y, e.Z);
gl.TexCoord(i / (double)n, 2 * j / (double)n);
gl.Vertex(p.X, p.Y, p.Z);
}
gl.End();
}
}
/// <summary>
/// Handles the OpenGLDraw event of the openGLControl control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RenderEventArgs"/> instance containing the event data.</param>
private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e)
{
// Get the OpenGL object.
gl = openGLControl.OpenGL;
// Clear the color and depth buffer.
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
// Load the identity matrix.
gl.LoadIdentity();
// Rotate around the Y axis.
////gl.Rotate(rotation, 0.0f, 1.0f, 0.0f);
foreach (var item in atomsList)
{
// Point3d coord = item.Coordinate;
drawSphere(item.Coordinate, 0.75f, 20);
}
// Nudge the rotation.
rotation += 30.0f;
}
My aim is to draw something like this --
However, my output is something like the following --
Probably, the hidden surface removal is not working as expected.
How can I obtain my expected output?

The winding order of your primitives appears to be clockwise. The default winding order is counterclockwise (see Face Culling). Change the winding order that defines front-facing polygons:
gl.Enable(OpenGL.GL_CULL_FACE);
gl.CullFace(OpenGL.GL_BACK);
gl.FrontFace(OpenGL.GL_CW);

Related

Unable to draw spheres with arbitrary color

I am using SharpGL.
I am trying to draw three overlapped spheres with three different colors like the following -
However, I am getting output like the following -
In other words, the gl.Color() is having no effect on the drawn object.
How can I fix this?
Source Code:
public static class OpenGLhelper
{
public static void Init(OpenGL gl)
{
float[] mat_specular = { 1.0f, 1.0f, 1.0f, 1.0f };
float[] mat_shininess = { 50.0f };
float[] light_position = { 0.5f, 0.5f, 0.750f, 0.0f };
gl.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.ShadeModel(OpenGL.GL_SMOOTH);
gl.Material(OpenGL.GL_FRONT, OpenGL.GL_SPECULAR, mat_specular);
gl.Material(OpenGL.GL_FRONT, OpenGL.GL_SHININESS, mat_shininess);
gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, light_position);
gl.Enable(OpenGL.GL_LIGHTING);
gl.Enable(OpenGL.GL_LIGHT0);
gl.Enable(OpenGL.GL_DEPTH_TEST);
//// Cull back faces.
gl.Enable(OpenGL.GL_CULL_FACE);
gl.CullFace(OpenGL.GL_BACK);
gl.FrontFace(OpenGL.GL_CW);
}
private static void drawSphere(OpenGL gl, Point3d c, Rgb color, double r, int n)
{
int i, j;
double theta1, theta2, theta3;
Point3d e = new Point3d();
Point3d p = new Point3d();
if (c == null)
{
c = new Point3d(0, 0, 0);
}
double twoPi = Math.PI * 2;
double piD2 = Math.PI / 2;
if (r < 0)
r = -r;
if (n < 0)
n = -n;
if (n < 4 || r <= 0)
{
gl.Begin(OpenGL.GL_POINTS);
gl.Color(color.Red, color.Green, color.Blue);
gl.Vertex(c.X, c.Y, c.Z);
gl.End();
return;
}
for (j = 0; j < n / 2; j++)
{
theta1 = j * twoPi / n - piD2;
theta2 = (j + 1) * twoPi / n - piD2;
gl.Begin(OpenGL.GL_QUAD_STRIP);
for (i = 0; i <= n; i++)
{
theta3 = i * twoPi / n;
e.X = Math.Cos(theta2) * Math.Cos(theta3);
e.Y = Math.Sin(theta2);
e.Z = Math.Cos(theta2) * Math.Sin(theta3);
p.X = c.X + r * e.X;
p.Y = c.Y + r * e.Y;
p.Z = c.Z + r * e.Z;
gl.Normal(e.X, e.Y, e.Z);
gl.TexCoord(i / (double)n, 2 * (j + 1) / (double)n);
gl.Color(color.Red, color.Green, color.Blue);
gl.Vertex(p.X, p.Y, p.Z);
e.X = Math.Cos(theta1) * Math.Cos(theta3);
e.Y = Math.Sin(theta1);
e.Z = Math.Cos(theta1) * Math.Sin(theta3);
p.X = c.X + r * e.X;
p.Y = c.Y + r * e.Y;
p.Z = c.Z + r * e.Z;
gl.Normal(e.X, e.Y, e.Z);
gl.TexCoord(i / (double)n, 2 * j / (double)n);
gl.Color(color.Red, color.Green, color.Blue);
gl.Vertex(p.X, p.Y, p.Z);
}
gl.End();
}
}
public static void Display(OpenGL gl)
{
gl.Clear(OpenGL . GL_COLOR_BUFFER_BIT | OpenGL . GL_DEPTH_BUFFER_BIT);
drawSphere(gl, new Point3d(0, 0, 0), new Rgb(1, 0, 0), 0.5, 20);
drawSphere(gl, new Point3d(0, 0.5, 0), new Rgb(0, 1, 0), 0.5, 20);
drawSphere(gl, new Point3d(0, -0.5, 0), new Rgb(0, 0, 1), 0.5, 20);
gl.Flush();
}
public static void Reshape(OpenGL gl, int width, int height)
{
}
}
public partial class SharpGLForm : Form
{
private float rotation = 0.0f;
public SharpGLForm()
{
InitializeComponent();
OpenGL gl = openGLControl1.OpenGL;
OpenGLhelper.Init(gl);
}
private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e)
{
OpenGL gl = openGLControl1.OpenGL;
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
gl.LoadIdentity();
gl.Translate(0.0f, 0.0f, -4.0f); // Move into the screen
gl.Rotate(rotation, 0.0f, 1.0f, 0.0f);
OpenGLhelper.Display(gl);
rotation += 3.0f;
}
}
When lighting (GL_LIGHTING) is enabled, the render color is defined by the material parameters (glMaterial). If you want to define the color with glColor, you must enable GL_COLOR_MATERIAL
and to set the color material parameters (glColorMaterial):
gl.Enable(OpenGL.GL_LIGHTING);
gl.Enable(OpenGL.GL_COLOR_MATERIAL);
gl.ColorMaterial(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_AMBIENT_AND_DIFFUSE);
Alternatively set the material color with GL.Material. e.g.:
float[] ambient_diffuse_color = { 1.0f, 0.0f, 0.0f, 1.0f }; // RED
GL.Material(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_AMBIENT_AND_DIFFUSE,
ambient_diffuse_color);

Unity: detect click event on UIVertex

I am drawing lines on a canvas using the 'UIVertex' struct and I would like to be able to detect click events on the lines I have drawn.
Here is how I draw lines (largely inspired from this tutorial => https://www.youtube.com/watch?v=--LB7URk60A):
void DrawVerticesForPoint(Vector2 point, float angle, VertexHelper vh)
{
vertex = UIVertex.simpleVert;
//vertex.color = Color.red;
vertex.position = Quaternion.Euler(0, 0, angle) * new Vector3(-thickness / 2, 0);
vertex.position += new Vector3(unitWidth * point.x, unitHeight * point.y);
vh.AddVert(vertex);
vertex.position = Quaternion.Euler(0, 0, angle) * new Vector3(thickness / 2, 0);
vertex.position += new Vector3(unitWidth * point.x, unitHeight * point.y);
vh.AddVert(vertex);
}
Any idea?
Here is the solution I have found thanks to this post:
public bool PointIsOnLine(Vector3 point, UILineRenderer line)
{
Vector3 point1 = line.points[0];
Vector3 point2 = line.points[1];
var dirNorm = (point2 - point1).normalized;
var t = Vector2.Dot(point - point1, dirNorm);
var tClamped = Mathf.Clamp(t, 0, (point2 - point1).magnitude);
var closestPoint = point1 + dirNorm * tClamped;
var dist = Vector2.Distance(point, closestPoint);
if(dist < line.thickness / 2)
{
return true;
}
return false;
}
The UILineRenderer class is the class I have which represents my lines.
line.points[0] and line.points[1] contain the coordinates of the two points which determine the line length and position. line.thickness is the... thickness of the line :O

OpenTK Oblique Frustum (Lens Shift)

I am very new to OpenGL and am using the latest version of OpenTK with C#.
My camera class currently does the following,
public Matrix4 GetProjectionMatrix()
{
return Matrix4.CreatePerspectiveFieldOfView(_fov, AspectRatio, 0.01f, 100f);
}
public Matrix4 GetViewMatrix()
{
Vector3 lookAt = new Vector3(myObject.Pos.X, myObject.Pos.Y, myObject.Pos.Z);
return Matrix4.LookAt(Position, lookAt, _up);
}
I have a slightly weird use case, where my game window will be long, something like a 4:12 ratio, and it will present a long object. From my reading, online the best way to present this the way I want is to do a lense shift (Oblique Frustum).
I've seen articles online on how to do this, namely:
http://www.terathon.com/code/oblique.html
https://docs.unity3d.com/Manual/ObliqueFrustum.html
But I am having trouble translating this to OpenTk.
Was wondering if anyone on here has done something similar to this in OpenTK.
EDIT:
This kind of worked, but not quite what I was looking for :(
private float sgn(float a)
{
if (a > 0.0F) return (1.0F);
if (a < 0.0F) return (-1.0F);
return (0.0F);
}
public Matrix4 CreatePerspectiveFieldOfView(Matrix4 projectionMatrix)
{
Vector4 clipPlane = new Vector4(0.0f, 0.7f, 1.0f , 1.0f);
Vector4 q = new Vector4
{
X = (sgn(clipPlane.X) + projectionMatrix.M13) / projectionMatrix.M11,
Y = (sgn(clipPlane.Y) + projectionMatrix.M23) / projectionMatrix.M22,
Z = -1.0f,
W = (1.0F + projectionMatrix.M33) / projectionMatrix.M34
};
Vector4 c = clipPlane * (2.0F / Vector4.Dot(clipPlane, q));
projectionMatrix.M31 = c.X;
projectionMatrix.M32 = c.Y;
projectionMatrix.M33 = c.Z + 1.0f;
projectionMatrix.M34 = c.W;
return projectionMatrix;
}
EDIT 2:
Basically what I am looking to do, is bring the look at point closer to the edge of the frustum like so:
There are some obvious issues. OpenGL matrices are column major order. Hence, i is the column and j is the row for the Mij properties of Matrix4:
In the following columns are from the top to the bottom and rows are form the left to the right, because that is the representation of the fields of the matrix in memory and how a matrix "looks" in the debuger:
row1 row2 row3 row4 indices
column1 (M11, M12, M13, M14) ( 0, 1, 2, 3)
column2 (M21, M22, M23, M24) ( 4, 5, 6, 7)
column3 (M31, M32, M33, M34) ( 8, 9, 10, 11)
column4 (M41, M42, M43, M44) (12, 13, 14, 15)
Thus
q.x = (sgn(clipPlane.x) + matrix[8]) / matrix[0];
q.y = (sgn(clipPlane.y) + matrix[9]) / matrix[5];
q.z = -1.0F;
q.w = (1.0F + matrix[10]) / matrix[14];
has to be translated to:
Vector4 q = new Vector4
{
X = (sgn(clipPlane.X) + projectionMatrix.M31) / projectionMatrix.M11,
Y = (sgn(clipPlane.Y) + projectionMatrix.M32) / projectionMatrix.M22,
Z = -1.0f,
W = (1.0f + projectionMatrix.M33) / projectionMatrix.M43
};
and
```cpp
matrix[2] = c.x;
matrix[6] = c.y;
matrix[10] = c.z + 1.0F;
matrix[14] = c.w;
has to be
projectionMatrix.M13 = c.X;
projectionMatrix.M23 = c.Y;
projectionMatrix.M33 = c.Z + 1.0f;
projectionMatrix.M43 = c.W;
If you want an asymmetric perspective projection, then consider to to create the perojection matrix by Matrix4.CreatePerspectiveOffCenter.
public Matrix4 GetProjectionMatrix()
{
var offset_x = -0.0f;
var offset_y = -0.005f; // just for instance
var tan_fov_2 = Math.Tan(_fov / 2.0);
var near = 0.01f;
var far = 100.0f;
var left = -near * AspectRatio * tan_fov_2 + offset_x;
var right = near * AspectRatio * tan_fov_2 + offset_x;
var bottom = -near * tan_fov_2 + offset_y;
var top = near * tan_fov_2 + offset_y;
return Matrix4.CreatePerspectiveOffCenter(left, right, bottom, top, near, far);
}

how to draw Cube using OpenTK & OpenGL in C#

I'm in crisis about draw Cube, as the title says.
I tried the graphic only in Unity. But I was done. Using OpenTK and OpenGL in C#.
It was successful to draw the sphere by inputting the value.
Draw the values of the array as you type.
Ex) 2by2 Array =>
oo
oo
this is my code about draw Sphere
void DrawSphere()
{
OpenTK.Graphics.OpenGL.GL.Enable(OpenTK.Graphics.OpenGL.EnableCap.Lighting);
OpenTK.Graphics.OpenGL.GL.Enable(OpenTK.Graphics.OpenGL.EnableCap.Light0);
OpenTK.Graphics.OpenGL.GL.Enable(OpenTK.Graphics.OpenGL.EnableCap.Normalize);
OpenTK.Graphics.OpenGL.GL.Enable(OpenTK.Graphics.OpenGL.EnableCap.ColorMaterial);
//OpenTK.Graphics.OpenGL.GL.Enable(OpenTK.Graphics.OpenGL.EnableCap.Texture2D);
OpenTK.Graphics.OpenGL.GL.ShadeModel(OpenTK.Graphics.OpenGL.ShadingModel.Smooth);
// Draw green sphere
OpenTK.Graphics.OpenGL.GL.Color3(0.8f, 0.8f, 255.0f);
//textureid = LoadTex("dd.png");
float x, y, z;
y = 0.0F;
x = 0.0F;
x = (((Properties.Settings.Default.simulRow * camera.rowGap) - camera.rowGap) / 2) * -1.0F;
for (int i = 0; i < Properties.Settings.Default.simulRow; i++)
{
z = (((Properties.Settings.Default.simulCol * camera.colGap) - camera.colGap) / 2) * -1.0F;
for (int j = 0; j < Properties.Settings.Default.simulCol; j++)
{
//y = ballImage[i, j].height / camera.calibrate_div;
y = (camera.calibrate_div / 2.0f) - Math.Abs(ballImage[i, j].current_height);
//System.Diagnostics.Debug.WriteLine(ballImage[0, 0].current_height);
OpenTK.Graphics.OpenGL.GL.PushMatrix();
OpenTK.Graphics.OpenGL.GL.Translate(x, y, z);
//OpenTK.Graphics.OpenGL.GL.BindTexture(OpenTK.Graphics.OpenGL.TextureTarget.Texture2D, textureid);
//OpenTK.Graphics.Glu.QuadricTexture(esfera, true);
OpenTK.Graphics.OpenGL.GL.Rotate(90, 1.0f, 0.0f, 0.0f);
//OpenTK.Graphics.OpenGL.GL.Rotate(0.0f, 1.0f, 1.0f, 1.0f);
OpenTK.Graphics.Glu.Sphere(esfera, 1.0f, 24, 24);
//OpenTK.Graphics.Glu.Tex(esfera, 1.0f, 24, 24);
OpenTK.Graphics.OpenGL.GL.PopMatrix();
if (i == 5 && j == 5)
{
// OpenTK.Graphics.Glu.Sphere(esfera, 100.0f, 24, 24);
}
z += camera.rowGap;
}
x += camera.colGap;
}
}

XNA Loading Models

I am pretty new to the 3D side of XNA and am converting a 2D game.
Its basically designed as a grid and I am drawing with the code below. This works but is a bit laggy, am I doing this completely wrong? Presumably there shouldn't be much lag at this point when we are only talking about a few small models.
protected override void Draw(GameTime gameTime)
{
fpsTimer += gameTime.ElapsedGameTime;
fpsCount++;
if (fpsTimer >= TimeSpan.FromSeconds(1))
{ fpsTimer = TimeSpan.FromSeconds(0); fps = fpsCount; fpsCount = 0; }
GraphicsDevice.Clear(Color.CornflowerBlue);
projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 1.0f, 1000.0f);
world = Matrix.CreateTranslation(new Vector3(0, 0, 0));
view = Matrix.CreateLookAt(new Vector3(xPos, yPos, zHeight), new Vector3(xPos, yPos + zRotation, 0), new Vector3(0, 5, 0));
// DRAW OBJECTS ON MAP
drawMap(view, world, projection);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
spriteBatch.DrawString(font, "" + fps, new Vector2(100, 100), Color.Black);
spriteBatch.End();
base.Draw(gameTime);
}
private void drawMap(Matrix view, Matrix world, Matrix projection)
{
GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
int scale = Globals.scale;
int screenWidthScale = Globals.screenwidth / scale;
int screenHeightScale = Globals.screenheight / scale;
int mapXtile = Convert.ToInt32(xPos/2);
int mapYtile = Convert.ToInt32(yPos/2);
for (int i = Convert.ToInt32(xPos/2) - 30; i < Convert.ToInt32(xPos/2) + 30; i++)
{
for (int a = Convert.ToInt32(yPos/2); a < Convert.ToInt32(yPos/2) + 50; a++)
{
if (mapXtile > 0 && mapYtile > 0 && mapXtile < Globals.mapsizex && mapYtile < Globals.mapsizey)
{
int currentTile = Globals.levelArray[mapXtile, mapYtile].TyleType;
// DRAW TREES
if (currentTile == tyleType.tree)
{
if (Globals.levelArray[mapXtile, mapYtile].typeModifier == 1)
{
Matrix worldMatrix = Matrix.CreateScale(0.8f, 0.8f, 0.8f) * Matrix.CreateRotationX(1.5f) * Matrix.CreateTranslation(new Vector3(i * 2 + 0.2f, a * 2 - 0.4f, -0.1f));
tree.Draw(worldMatrix, view, projection);
}
if (Globals.levelArray[mapXtile, mapYtile].typeModifier == 2)
{
Matrix worldMatrix = Matrix.CreateScale(0.8f, 0.8f, 0.8f) * Matrix.CreateRotationX(1.5f) * Matrix.CreateTranslation(new Vector3(i * 2+0.2f, a * 2-0.4f, -0.1f));
tree2.Draw(worldMatrix, view, projection);
}
}
}
mapYtile = mapYtile + 1;
//mapYtile++;
}
mapXtile = mapXtile + 1;
mapYtile = Convert.ToInt32(yPos / 2);
}
}

Categories