dimanche 1 mars 2015

OpenTK. Trouble with mirror reflection

I have some problems with rendering of mirror reflection in OpenTK. I need to see reflection of objects only from one side from my mirror, but my program also gives reflection from another side and it hides the first one. Could you help me?



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using OpenTK;
using OpenTK.Graphics.OpenGL;
using graph = OpenTK.Graphics;

namespace cursach
{
struct MyPoint
{
public double x, y, z;

public MyPoint(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
};

public partial class Form1 : Form
{
bool loaded = false;

private const int MAX_ANGLE = 120;
private const int MIN_ANGLE = 0;
private const int INTERMEDIATE_ANGLE = 30;
private const double MIRROR_SHELF_OFFSET = 5;
private const double MAX_MIRROR_SHELF_OFFSET = 15;
private const double MIN_MIRROR_SHELF_OFFSET = 0;

private static double x0 = 0;
private static double y0 = 0;
private static double z0 = 0;
private static double width = 40; //ширина
private static double height = width; //высота
private static double weight = width; //толщина

private const float lightPosX = 40;
private const float lightPosY = 40;
private const float lightPosZ = 40;
private static int xAngle = 0;
private static int yAngle = 0;
private static int zAngle = 0;

private int lDoorAngle = 0, rDoorAngle = 0;
private double totalShelfOffset = 0;
private float[] ambientLight = { 1f, 1f, 1f, 1f };
private float[] lightColor = { 1.0f, 1.0f, 1.0f, 1.0f };
private float[] lightPos = { lightPosX, lightPosY, lightPosZ, 1.0f };

private static MyPoint p1 = new MyPoint(x0 - width / 2, y0 + 2*height / 2, z0 - weight / 2);
private static MyPoint p2 = new MyPoint(x0 + width / 2, y0 + 2*height / 2, z0 - weight / 2);
private static MyPoint p3 = new MyPoint(x0 + width / 2, y0 - height / 2, z0 - weight / 2);
private static MyPoint p4 = new MyPoint(x0 - width / 2, y0 - height / 2, z0 - weight / 2);

private static MyPoint p5 = new MyPoint(x0 - width / 2, y0 + 2*height / 2, z0 + weight / 2);
private static MyPoint p6 = new MyPoint(x0 - width / 2, y0 - height / 2, z0 + weight / 2);
private static MyPoint p7 = new MyPoint(x0 + width / 2, y0 + 2*height / 2, z0 + weight / 2);
private static MyPoint p8 = new MyPoint(x0 + width / 2, y0 - height / 2, z0 + weight / 2);

private static MyPoint p9 = new MyPoint(x0, y0 + height / 2, z0 + weight / 2);
private static MyPoint p10 = new MyPoint(x0, y0, z0 + weight / 2);
private static MyPoint p11 = new MyPoint(x0, y0 - height / 2, z0 + weight / 2);
private static MyPoint p12 = new MyPoint(x0 - width / 2, y0, z0 + weight / 2);
private static MyPoint p13 = new MyPoint(x0 + width / 2, y0, z0 + weight / 2);

private static MyPoint p14 = new MyPoint(x0 - width / 2, y0 + height / 6, z0 - weight / 2);
private static MyPoint p15 = new MyPoint(x0 + width / 2, y0 + height / 6, z0 - weight / 2);
private static MyPoint p16 = new MyPoint(x0 + width / 2, y0 + height / 6, z0 + weight / 2);
private static MyPoint p17 = new MyPoint(x0 - width / 2, y0 + height / 6, z0 + weight / 2);

private MyPoint[] downWall = { p4, p6, p8, p3, p4 };
private MyPoint[] upWall = { p1, p2, p7, p5, p1 };

private MyPoint[] mirror = { p14, p17, p16, p15, p14 };

private MyPoint[] leftWall = { p1, p5, p6, p4 };
private MyPoint[] rightWall = { p2, p7, p8, p3 };
private MyPoint[] backWall = { p1, p2, p3, p4 };

private MyPoint[] leftDoor = { p5, p6, p11, p9 };
private MyPoint[] rightDoor = { p9, p7, p8, p11 };

public Form1()
{
InitializeComponent();
}

private void glControl1_KeyDown(object sender, KeyEventArgs e)
{
if (!loaded) return;

if (e.KeyCode == Keys.X)
{
GL.MatrixMode(MatrixMode.Modelview);
GL.Rotate(15, 1, 0, 0);
xAngle += 15;
if (xAngle >= 360) xAngle = 0;
textBox1.Text = xAngle.ToString();
}
if (e.KeyCode == Keys.Y)
{
GL.MatrixMode(MatrixMode.Modelview);
GL.Rotate(15, 0, 1, 0);
yAngle += 15;
if (yAngle >= 360) yAngle = 0;
textBox2.Text = yAngle.ToString();
}
if (e.KeyCode == Keys.Z)
{
GL.MatrixMode(MatrixMode.Modelview);
GL.Rotate(15, 0, 0, 1);
zAngle += 15;
if (zAngle >= 360) zAngle = 0;
textBox3.Text = zAngle.ToString();
}

glControl1.Invalidate();
}

private void glControl1_Load(object sender, EventArgs e)
{
loaded = true;

GL.ClearColor(Color.SkyBlue);
initRendering();

Matrix4 p = Matrix4.CreatePerspectiveFieldOfView((float)(80 * Math.PI / 180), 1, 20, 500);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref p);

Matrix4 modelview = Matrix4.LookAt(70, 70, 70, 0, 0, 0, 0, 1, 0);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref modelview);

/*GL.MatrixMode(MatrixMode.Modelview);
GL.Rotate(180, 1, 0, 0);*/
}

private void glControl1_Paint(object sender, PaintEventArgs e)
{
if (!loaded)
return;

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

drawScene();

/*axes*/
GL.Color3(Color.Black);
GL.Begin(BeginMode.Lines);
GL.Vertex3(0, 0, 0);
GL.Vertex3(70, 0, 0);
GL.Vertex3(0, 0, 0);
GL.Vertex3(0, 70, 0);
GL.Vertex3(0, 0, 0);
GL.Vertex3(0, 0, 70);
GL.End();

glControl1.SwapBuffers();
}

void initRendering()
{
GL.ShadeModel(ShadingModel.Flat);

GL.ClearDepth(1.0f);
GL.ClearStencil(0);

GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);

GL.Enable(EnableCap.AutoNormal);
// Setup the drawing area and shading mode
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();


GL.Enable(EnableCap.PointSmooth);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();

GL.Enable(EnableCap.Lighting);
GL.LightModel(LightModelParameter.LightModelAmbient, ambientLight);
GL.Enable(EnableCap.Normalize);
GL.Enable(EnableCap.ColorMaterial);
}

public class CustomOpenGLControl : GLControl
{
public CustomOpenGLControl()
: base(new OpenTK.Graphics.GraphicsMode(32, 24, 8))
{

}
}

private void drawFrame()
{
GL.Color3(Color.Red);
GL.Begin(BeginMode.Quads);
GL.Normal3(0.0f, -1.0f, 0.0f);
for (int i = 0; i < upWall.Length; i++)
{
GL.Vertex3(upWall[i].x, upWall[i].y, upWall[i].z);
}
GL.End();

GL.Color3(Color.Yellow);
GL.Begin(BeginMode.Quads);
GL.Normal3(0.0f, -1.0f, 0.0f);
for (int i = 0; i < downWall.Length; i++)
{
GL.Vertex3(downWall[i].x, downWall[i].y, downWall[i].z);
}
GL.End();

GL.Color3(Color.Green);
GL.Begin(BeginMode.Quads);
GL.Normal3(0.0f, 0.0f, -1.0f);
for (int i = 0; i < backWall.Length; i++)
{
GL.Vertex3(backWall[i].x, backWall[i].y, backWall[i].z);
}
GL.End();

GL.Color3(Color.Blue);
GL.Begin(BeginMode.Quads);
GL.Normal3(-1.0f, 0.0f, 0.0f);
for (int i = 0; i < rightWall.Length; i++)
{
GL.Vertex3(rightWall[i].x, rightWall[i].y, rightWall[i].z);
}
GL.End();

GL.Color3(Color.Orange);
GL.Begin(BeginMode.Quads);
GL.Normal3(1.0f, 0.0f, 0.0f);
for (int i = 0; i < leftWall.Length; i++)
{
GL.Vertex3(leftWall[i].x, leftWall[i].y, leftWall[i].z);
}
GL.End();
}

private void drawMirror()
{
GL.PushMatrix();

GL.Begin(BeginMode.Quads);
GL.Normal3(0.0f, -1.0f, 0.0f);
for (int i = 0; i < mirror.Length; i++)
{
GL.Vertex3(mirror[i].x, mirror[i].y, mirror[i].z);
}
GL.End();

GL.PopMatrix();
}

private void drawScene()
{
GL.Clear(ClearBufferMask.AccumBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit | ClearBufferMask.ColorBufferBit);
double[] eqr = { 0f, y0 + height / 6f, 0f, 0.0f };

GL.PushMatrix();

GL.ColorMask(false, false, false, false);
GL.Enable(EnableCap.StencilTest);
GL.StencilFunc(StencilFunction.Always, 1, 1);
GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Replace);
GL.Disable(EnableCap.DepthTest);
drawMirror();
GL.Enable(EnableCap.DepthTest);
GL.ColorMask(true, true, true, true);
GL.StencilFunc(StencilFunction.Equal, 1, 1);
GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);

GL.Enable(EnableCap.ClipPlane0);
GL.ClipPlane(ClipPlaneName.ClipPlane0, eqr);
GL.PushMatrix();
GL.Scale(1, -1, 1);
drawFrame();
GL.PopMatrix();
GL.Disable(EnableCap.ClipPlane0);
GL.Disable(EnableCap.StencilTest);

GL.Enable(EnableCap.Blend);
GL.Disable(EnableCap.Lighting);
GL.Color4(1, 1, 1, 0.3f);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
drawMirror();
GL.Enable(EnableCap.Lighting);
GL.Disable(EnableCap.Blend);
drawFrame();
GL.PopMatrix();
}
}

public class CustomOpenGLControl : GLControl
{
public CustomOpenGLControl()
: base(new OpenTK.Graphics.GraphicsMode(32, 24, 8))
{

}
}
}





Aucun commentaire:

Enregistrer un commentaire