outdated: 27.Shadows

这次的代码没有按照辅导代码中的来。

VK_LEFT/VK_RIGHT/VK_UP/VK_DOWN控制长方体旋转,W/S/A/D/Q/E控制球移动,小键盘的8/5/4/6/7/9控制长方体移动,I/K/J/L/U/O控制光源移动。

在InitGLObject()函数中使用到的readObject()函数、setConnectivity()函数和calculatePlane()函数在3object.h中所写。

readObject()函数在.txt文件中读取物体顶点数、顶点坐标、平面数、vertexIndices以及顶点normals。

bool readObject(const char* filename, ShadowedObject& object)
{
    FILE* pInputFile = fopen(filename, "r");

    if (!pInputFile) {
        std::cerr << "Unable to open the object file: " << filename << std::endl;
        return false;
    }
    // Read vertices
    fscanf(pInputFile, "%d", &object.nVertices);
    object.pVertices = new Point3f[object.nVertices];

    for (int i = 0; i < object.nVertices; ++i) {
        fscanf(pInputFile, "%f", &object.pVertices[i].x);
        fscanf(pInputFile, "%f", &object.pVertices[i].y);
        fscanf(pInputFile, "%f", &object.pVertices[i].z);
    }
    // Read faces
    fscanf(pInputFile, "%d", &object.nFaces);
    object.pFaces = new Face[object.nFaces];

    for (int i = 0; i < object.nFaces; ++i) {
        Face* pFace = &object.pFaces[i];
        for (int j = 0; j < 3; ++j) {
            pFace->neighbourIndices[j] = -1;     // No neighbour set up
            fscanf(pInputFile, "%d", &pFace->vertexIndices[j]);
            pFace->vertexIndices[j]--;
        }

        for (int j = 0; j < 3; ++j) {
            fscanf(pInputFile, "%f", &pFace->normals[j].x);
            fscanf(pInputFile, "%f", &pFace->normals[j].y);
            fscanf(pInputFile, "%f", &pFace->normals[j].z);
        }
    }
    return true;
}

readObject

三个物体的txt文件:

8
-1  1 -1
 1  1 -1
 1  1  1
-1  1  1
-1 -1 -1
 1 -1 -1
 1 -1  1
-1 -1  1
12
1 3 2 0 1 0 0 1 0 0 1 0
1 4 3 0 1 0 0 1 0 0 1 0
5 6 7 0 -1 0 0 -1 0 0 -1 0
5 7 8 0 -1 0 0 -1 0 0 -1 0
5 4 1 -1 0 0 -1 0 0 -1 0 0
5 8 4 -1 0 0 -1 0 0 -1 0 0
3 6 2 1 0 0 1 0 0 1 0 0
3 7 6 1 0 0 1 0 0 1 0 0
5 1 2 0 0 -1 0 0 -1 0 0 -1
5 2 6 0 0 -1 0 0 -1 0 0 -1
3 4 8 0 0 1 0 0 1 0 0 1
3 8 7 0 0 1 0 0 1 0 0 1

cube.txt

16
-2  0.2 -0.2
 2  0.2 -0.2
 2  0.2  0.2
-2  0.2  0.2
-2 -0.2 -0.2
 2 -0.2 -0.2
 2 -0.2  0.2
-2 -0.2  0.2

-0.2  2 -0.2
 0.2  2 -0.2
 0.2  2  0.2
-0.2  2  0.2
-0.2 -2 -0.2
 0.2 -2 -0.2
 0.2 -2  0.2
-0.2 -2  0.2
24
1 3 2 0 1 0 0 1 0 0 1 0
1 4 3 0 1 0 0 1 0 0 1 0
5 6 7 0 -1 0 0 -1 0 0 -1 0
5 7 8 0 -1 0 0 -1 0 0 -1 0
5 4 1 -1 0 0 -1 0 0 -1 0 0
5 8 4 -1 0 0 -1 0 0 -1 0 0
3 6 2 1 0 0 1 0 0 1 0 0
3 7 6 1 0 0 1 0 0 1 0 0
5 1 2 0 0 -1 0 0 -1 0 0 -1
5 2 6 0 0 -1 0 0 -1 0 0 -1
3 4 8 0 0 1 0 0 1 0 0 1
3 8 7 0 0 1 0 0 1 0 0 1

9 11 10 0 1 0 0 1 0 0 1 0
9 12 11 0 1 0 0 1 0 0 1 0
13 14 15 0 -1 0 0 -1 0 0 -1 0
13 15 16 0 -1 0 0 -1 0 0 -1 0
13 12 9 -1 0 0 -1 0 0 -1 0 0
13 16 12 -1 0 0 -1 0 0 -1 0 0
11 14 10 1 0 0 1 0 0 1 0 0
11 15 14 1 0 0 1 0 0 1 0 0
13 9 10 0 0 -1 0 0 -1 0 0 -1
13 10 14 0 0 -1 0 0 -1 0 0 -1
11 12 16 0 0 1 0 0 1 0 0 1
11 16 15 0 0 1 0 0 1 0 0 1

rood.txt

24
-2  0.2 -0.2
 2  0.2 -0.2
 2  0.2  0.2
-2  0.2  0.2
-2 -0.2 -0.2
 2 -0.2 -0.2
 2 -0.2  0.2
-2 -0.2  0.2

-0.2  2 -0.2
 0.2  2 -0.2
 0.2  2  0.2
-0.2  2  0.2
-0.2 -2 -0.2
 0.2 -2 -0.2
 0.2 -2  0.2
-0.2 -2  0.2

-0.2  0.2 -2
 0.2  0.2 -2
 0.2  0.2  2
-0.2  0.2  2
-0.2 -0.2 -2
 0.2 -0.2 -2
 0.2 -0.2  2
-0.2 -0.2  2

36
1 3 2 0 1 0 0 1 0 0 1 0
1 4 3 0 1 0 0 1 0 0 1 0
5 6 7 0 -1 0 0 -1 0 0 -1 0
5 7 8 0 -1 0 0 -1 0 0 -1 0
5 4 1 -1 0 0 -1 0 0 -1 0 0
5 8 4 -1 0 0 -1 0 0 -1 0 0
3 6 2 1 0 0 1 0 0 1 0 0
3 7 6 1 0 0 1 0 0 1 0 0
5 1 2 0 0 -1 0 0 -1 0 0 -1
5 2 6 0 0 -1 0 0 -1 0 0 -1
3 4 8 0 0 1 0 0 1 0 0 1
3 8 7 0 0 1 0 0 1 0 0 1

9 11 10 0 1 0 0 1 0 0 1 0
9 12 11 0 1 0 0 1 0 0 1 0
13 14 15 0 -1 0 0 -1 0 0 -1 0
13 15 16 0 -1 0 0 -1 0 0 -1 0
13 12 9 -1 0 0 -1 0 0 -1 0 0
13 16 12 -1 0 0 -1 0 0 -1 0 0
11 14 10 1 0 0 1 0 0 1 0 0
11 15 14 1 0 0 1 0 0 1 0 0
13 9 10 0 0 -1 0 0 -1 0 0 -1
13 10 14 0 0 -1 0 0 -1 0 0 -1
11 12 16 0 0 1 0 0 1 0 0 1
11 16 15 0 0 1 0 0 1 0 0 1

17 19 18 0 1 0 0 1 0 0 1 0
17 20 19 0 1 0 0 1 0 0 1 0
21 22 23 0 -1 0 0 -1 0 0 -1 0
21 23 24 0 -1 0 0 -1 0 0 -1 0
21 20 17 -1 0 0 -1 0 0 -1 0 0
21 24 20 -1 0 0 -1 0 0 -1 0 0
19 22 18 1 0 0 1 0 0 1 0 0
19 23 22 1 0 0 1 0 0 1 0 0
21 17 18 0 0 -1 0 0 -1 0 0 -1
21 18 22 0 0 -1 0 0 -1 0 0 -1
19 20 24 0 0 1 0 0 1 0 0 1
19 24 23 0 0 1 0 0 1 0 0 1

object.txt

setConnectivity()函数判断每个面的每条边是否是同一条边来设定每个面是否连接(连通)。

void setConnectivity(ShadowedObject& object)
{
    for (int faceA = 0; faceA < object.nFaces; ++faceA) {
        for (int edgeA = 0; edgeA < 3; ++edgeA) {
            if (!object.pFaces[faceA].neighbourIndices[edgeA]) {
                for (int faceB = faceA; faceB < object.nFaces; ++faceB) {
                    for (int edgeB = 0; edgeB < 3; ++edgeB) {
                        int vertA1 = object.pFaces[faceA].vertexIndices[edgeA];
                        int vertA2 = object.pFaces[faceA].vertexIndices[(edgeA + 1) % 3];
                        int vertB1 = object.pFaces[faceB].vertexIndices[edgeB];
                        int vertB2 = object.pFaces[faceB].vertexIndices[(edgeB + 1) % 3];
                        // Check If They Are Neighbours - IE, The Edges Are The Same
                        if ((vertA1 == vertB1 && vertA2 == vertB2) || (vertA1 == vertB2 && vertA2 == vertB1))
                        {
                            // They are neighbours
                            object.pFaces[faceA].neighbourIndices[edgeA] = faceB;
                            object.pFaces[faceB].neighbourIndices[edgeB] = faceA;
                            //edgeFound = true;
                            //break;
                        }
                    }
                }
            }
        }
    }
}

setConnectivity

calculatePlane()函数计算平面方程系数,很简单,用行列式计算就可以,下面为计算系数的过程,

void calculatePlane(const ShadowedObject& object, Face& face)
{
    // Get shortened names for the vertices of the face
    const Point3f& v1 = object.pVertices[face.vertexIndices[0]];
    const Point3f& v2 = object.pVertices[face.vertexIndices[1]];
    const Point3f& v3 = object.pVertices[face.vertexIndices[2]];

    face.PlaneEquation.a = v1.y * (v2.z - v3.z) + v2.y * (v3.z - v1.z) + v3.y * (v1.z - v2.z);
    face.PlaneEquation.b = v1.z * (v2.x - v3.x) + v2.z * (v3.x - v1.x) + v3.z * (v1.x - v2.x);
    face.PlaneEquation.c = v1.x * (v2.y - v3.y) + v2.x * (v3.y - v1.y) + v3.x * (v1.y - v2.y);
    face.PlaneEquation.d = -(v1.x * (v2.y * v3.z - v3.y * v2.z) + v2.x * (v3.y * v1.z - v1.y * v3.z) +
        v3.x * (v1.y * v2.z - v2.y * v1.z));
}

提前说下,两个向量的叉积与两个向量垂直,即平面的法向量。即,

已知三角形的三个点,求平面方程(系数)。

可由行列式得,

即平面方程系数,

在InitGL()函数中,glMaterialfv()函数为灯光模型添加材质,其原型为,

void WINAPI glMaterialfv(
         GLenum face,
         GLenum pname,
   const GLint  *params
);

glCullFace()函数选定正面或反面,来接收灯光效果,前提先要打开GL_CULL_FACE功能。

在DrawGLScene()函数中,glLightfv()函数设置灯光效果LightPos、LightAmb、LightDif或LightSpc,也只能用点光,别的看不出效果区别。

glGetFloatv()函数返回值或参数选择过的值。

glGetFloatv(GL_MODELVIEW_MATRIX, Minv);

这行代码返回一个4X4维矩阵,即GL_MODELVIEW_MATRIX:The params parameter returns 16 values: the modelview matrix on the top of the modelview matrix stack.即在前面的glPushMatrix()函数推进栈的矩阵。

glDepthMask()函数开启或关闭写入深度缓存。

VMatMult()函数实现一个4X4维矩阵和4维向量的相乘。

在castShadow()函数中,glPushAttrib()函数和glPopAttrib()函数作用相反,是对属性栈的操作。在原文中,作用为开启和关闭各项的功能。

glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT);

glPopAttrib();

glFrontFace()函数,用来指定多边形在窗口坐标中是否顺时针旋转。GL_CCW逆时针,GL_CW顺时针。

下面为代码,两个文件分为头文件和cpp文件,同样修改部分位于双行星号内。

  1 #ifndef _3DOBJECT_H_
  2 #define _3DOBJECT_H
  3
  4 #include <iostream>
  5 #include <stdio.h>
  6 #include <math.h>
  7 #include <GL\glut.h>
  8 #pragma comment(lib, "legacy_stdio_definitions.lib")
  9
 10 //3D-coordinate
 11 struct Point3f {
 12     float x, y, z;
 13 };
 14
 15 // Plane equation ax + by + cz + d = 0
 16 struct PlaneEq {
 17     float a, b, c, d;
 18 };
 19
 20 // Object‘s face
 21 struct Face {
 22     int vertexIndices[3];      // Index of each vertex within the triangle of this face
 23     Point3f normals[3];        // Normals of each vertex
 24     PlaneEq PlaneEquation;
 25     int neighbourIndices[3];   // Index of each face that neighbour
 26     bool visible;              // Is the face visible by the light
 27 };
 28
 29 struct ShadowedObject {
 30     int nVertices;
 31     Point3f* pVertices;        // Dynamically Allocated
 32     int nFaces;
 33     Face* pFaces;              // Dynamically Allocated
 34 };
 35
 36 bool readObject(const char* filename, ShadowedObject& object)
 37 {
 38     FILE* pInputFile = fopen(filename, "r");
 39
 40     if (!pInputFile) {
 41         std::cerr << "Unable to open the object file: " << filename << std::endl;
 42         return false;
 43     }
 44     // Read vertices
 45     fscanf(pInputFile, "%d", &object.nVertices);
 46     object.pVertices = new Point3f[object.nVertices];
 47
 48     for (int i = 0; i < object.nVertices; ++i) {
 49         fscanf(pInputFile, "%f", &object.pVertices[i].x);
 50         fscanf(pInputFile, "%f", &object.pVertices[i].y);
 51         fscanf(pInputFile, "%f", &object.pVertices[i].z);
 52     }
 53     // Read faces
 54     fscanf(pInputFile, "%d", &object.nFaces);
 55     object.pFaces = new Face[object.nFaces];
 56
 57     for (int i = 0; i < object.nFaces; ++i) {
 58         Face* pFace = &object.pFaces[i];
 59         for (int j = 0; j < 3; ++j) {
 60             pFace->neighbourIndices[j] = 0;     // No neighbour set up
 61             fscanf(pInputFile, "%d", &pFace->vertexIndices[j]);
 62             pFace->PlaneEquation.a = pFace->PlaneEquation.b = pFace->PlaneEquation.c = pFace->PlaneEquation.d = 0;
 63             pFace->visible = false;
 64 //            pFace->vertexIndices[j]--;
 65         }
 66
 67         for (int j = 0; j < 3; ++j) {
 68             fscanf(pInputFile, "%f", &pFace->normals[j].x);
 69             fscanf(pInputFile, "%f", &pFace->normals[j].y);
 70             fscanf(pInputFile, "%f", &pFace->normals[j].z);
 71         }
 72     }
 73     return true;
 74 }
 75
 76 void killObject(ShadowedObject& object)
 77 {
 78     delete[] object.pFaces;
 79     object.nFaces = 0;
 80     object.pFaces = NULL;
 81     delete[] object.pVertices;
 82     object.nVertices = 0;
 83     object.pVertices = NULL;
 84 }
 85
 86 void setConnectivity(ShadowedObject& object)
 87 {
 88     for (int faceA = 0; faceA < object.nFaces; ++faceA) {
 89         for (int edgeA = 0; edgeA < 3; ++edgeA) {
 90             if (!object.pFaces[faceA].neighbourIndices[edgeA]) {
 91                 for (int faceB = faceA; faceB < object.nFaces; ++faceB) {
 92                     for (int edgeB = 0; edgeB < 3; ++edgeB) {
 93                         int vertA1 = object.pFaces[faceA].vertexIndices[edgeA];
 94                         int vertA2 = object.pFaces[faceA].vertexIndices[(edgeA + 1) % 3];
 95                         int vertB1 = object.pFaces[faceB].vertexIndices[edgeB];
 96                         int vertB2 = object.pFaces[faceB].vertexIndices[(edgeB + 1) % 3];
 97                         // Check If They Are Neighbours - IE, The Edges Are The Same
 98                         if ((vertA1 == vertB1 && vertA2 == vertB2) || (vertA1 == vertB2 && vertA2 == vertB1))
 99                         {
100                             // They are neighbours
101                             object.pFaces[faceA].neighbourIndices[edgeA] = faceB + 1;
102                             object.pFaces[faceB].neighbourIndices[edgeB] = faceA + 1;
103                             //edgeFound = true;
104                             //break;
105                         }
106                     }
107                 }
108             }
109         }
110     }
111 }
112
113 void drawObject(const ShadowedObject& object)
114 {
115     glBegin(GL_TRIANGLES);
116     for (int i = 0; i < object.nFaces; ++i) {
117         const Face& face = object.pFaces[i];
118         for (int j = 0; j < 3; ++j) {
119             const Point3f& vertex = object.pVertices[face.vertexIndices[j]-1];
120             glNormal3f(face.normals[j].x, face.normals[j].y, face.normals[j].z);
121             glVertex3f(vertex.x, vertex.y, vertex.z);
122         }
123     }
124     glEnd();
125 }
126
127 void calculatePlane(const ShadowedObject object, Face& face)
128 {
129     // Get shortened names for the vertices of the face
130     const Point3f& v1 = object.pVertices[face.vertexIndices[0]-1];
131     const Point3f& v2 = object.pVertices[face.vertexIndices[1]-1];
132     const Point3f& v3 = object.pVertices[face.vertexIndices[2]-1];
133
134     face.PlaneEquation.a = v1.y * (v2.z - v3.z) + v2.y * (v3.z - v1.z) + v3.y * (v1.z - v2.z);
135     face.PlaneEquation.b = v1.z * (v2.x - v3.x) + v2.z * (v3.x - v1.x) + v3.z * (v1.x - v2.x);
136     face.PlaneEquation.c = v1.x * (v2.y - v3.y) + v2.x * (v3.y - v1.y) + v3.x * (v1.y - v2.y);
137     face.PlaneEquation.d = -(v1.x * (v2.y * v3.z - v3.y * v2.z) + v2.x * (v3.y * v1.z - v1.y * v3.z) +
138         v3.x * (v1.y * v2.z - v2.y * v1.z));
139 }
140
141 void doShadowPass(ShadowedObject& object, GLfloat* lightPosition)
142 {
143     for (int i = 0; i < object.nFaces; ++i) {
144         const Face&    face = object.pFaces[i];
145         if (face.visible) {
146             // Go through each edge
147             for (int j = 0; j < 3; ++j) {
148                 int neighbourIndex = face.neighbourIndices[j];
149                 if (!neighbourIndex || object.pFaces[neighbourIndex-1].visible == false) {
150                     // Get the points on the edge
151                     const Point3f& v1 = object.pVertices[face.vertexIndices[j]-1];
152                     const Point3f& v2 = object.pVertices[face.vertexIndices[(j + 1) % 3]-1];
153                     // Calculate the two vertices in distance
154                     Point3f v3, v4;
155                     v3.x = (v1.x - lightPosition[0]) * 10000000;
156                     v3.y = (v1.y - lightPosition[1]) * 10000000;
157                     v3.z = (v1.z - lightPosition[2]) * 10000000;
158
159                     v4.x = (v2.x - lightPosition[0]) * 10000000;
160                     v4.y = (v2.y - lightPosition[1]) * 10000000;
161                     v4.z = (v2.z - lightPosition[2]) * 10000000;
162
163                     // Draw the quadrilateral (as a triangle strip)
164                     glBegin(GL_TRIANGLE_STRIP);
165                         glVertex3f(v1.x, v1.y, v1.z);
166                         glVertex3f(v1.x + v3.x, v1.y + v3.y, v1.z + v3.z);
167                         glVertex3f(v2.x, v2.y, v2.z);
168                         glVertex3f(v2.x + v4.x, v2.y + v4.y, v2.z + v4.z);
169                     glEnd();
170                 }
171             }
172         }
173     }
174 }
175
176
177 void castShadow(ShadowedObject& object, GLfloat* lightPosition)
178 {
179     // Determine which faces are visible by the light
180     for (int i = 0; i < object.nFaces; ++i) {
181         const PlaneEq& plane = object.pFaces[i].PlaneEquation;
182         GLfloat side = plane.a * lightPosition[0] + plane.b * lightPosition[1] +
183             plane.c * lightPosition[2] + plane.d;
184         if (side > 0)
185             object.pFaces[i].visible = true;
186         else
187             object.pFaces[i].visible = false;
188     }
189     glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT |
190         GL_STENCIL_BUFFER_BIT);
191     glDisable(GL_LIGHTING);
192     glDepthMask(GL_FALSE);      // Turn off writing to the depth-buffer
193     glDepthFunc(GL_LEQUAL);
194     glEnable(GL_STENCIL_TEST);  // Trun on
195     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
196     glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL);
197     //First pass.Increase stencil value int the shadow
198     glFrontFace(GL_CCW);
199     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
200     doShadowPass(object, lightPosition);
201     // Scend pass. Decrease stencil value in the shadow
202     glFrontFace(GL_CW);
203     glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
204     doShadowPass(object, lightPosition);
205
206     glFrontFace(GL_CCW);
207     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);       // Enable rendering
208     // Draw a shadowing rectangle covering the entire screen
209     glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
210     glEnable(GL_BLEND);
211     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
212     glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL);
213     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
214     glPushMatrix();
215     glLoadIdentity();
216         glBegin(GL_TRIANGLE_STRIP);
217             glVertex3f(-0.1f, 0.1f, -0.1f);
218             glVertex3f(-0.1f, -0.1f, -0.1f);
219             glVertex3f(0.1f, 0.1f, -0.1f);
220             glVertex3f(0.1f, -0.1f, -0.1f);
221         glEnd();
222     glPopMatrix();
223     glPopAttrib();
224 }
225 #endif // !_3DOBJECT_H_

3Dobject.h

  1 #include <windows.h>
  2 #include <gl/glew.h>
  3 #include <GL/GLUAX.H>
  4 #include "C:\Users\lenovo\Desktop\OpenGL\OpenGL\3Dobject.h"
  5
  6 /*
  7 *  Every OpenGL program is linked to a Rendering Context.
  8 *  A Rendering Context is what links OpenGL calls to the Device Context.
  9 *  In order for your program to draw to a Window you need to create a Device Context.
 10 *  The DC connects the Window to the GDI (Graphics Device Interface).
 11 */
 12
 13 HGLRC     hRC = NULL;         // Permanent rendering context
 14 HDC       hDC = NULL;         // Private GDI device context
 15 HWND      hWnd = NULL;        // Holds our window handle
 16 HINSTANCE hInstance;          // Holds the instance of the application
 17
 18 /*
 19 *  It‘s important to make this global so that each procedure knows if
 20 *  the program is running in fullscreen mode or not.
 21 */
 22
 23 bool keys[256];         // Array used for the keyboard routine
 24 bool active = TRUE;     // Window active flag set to TRUE by default
 25 bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default
 26 /******************************************************************************************************************************************/
 27 /******************************************************************************************************************************************/
 28 typedef float GLvector4f[4];
 29 typedef float GLmatrix16f[16];
 30
 31 ShadowedObject object;
 32 GLfloat xrot = 0;
 33 GLfloat yrot = 0;
 34 GLfloat xspeed = 0;
 35 GLfloat yspeed = 0;
 36
 37 // Light parameters
 38 GLfloat LightPos[] = { 0.0f, 5.0f, -4.0f, 1.0f };
 39 GLfloat LightAmb[] = { 0.2f, 0.2f, 0.2f, 1.0f };
 40 GLfloat LightDif[] = { 0.6f, 0.6f, 0.6f, 1.0f };
 41 GLfloat LightSpc[] = { -0.2f, -0.2f, -0.2f, 1.0f };  // Specular light
 42
 43 GLfloat MatAmb[] = { 0.4f, 0.4f, 0.4f, 1.0f };
 44 GLfloat MatDif[] = { 0.2f, 0.6f, 0.9f, 1.0f };
 45 GLfloat MatSpc[] = { 0.0f, 0.0f, 0.0f, 1.0f };
 46 GLfloat MatShn[] = { 0.0f };              // Material - shininess
 47
 48 float ObjectPosition[] = { -2.0f, -2.0f, -5.0f };
 49
 50 GLUquadricObj * q;                // Quadratic for drawing a sphere
 51
 52 float SpherePosition[] = { -4.0f, -5.0f, -6.0f };
 53
 54 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc
 55 /******************************************************************************************************************************************/
 56 /******************************************************************************************************************************************/
 57 GLvoid ReSizeGLScene(GLsizei width, GLsizei height)   // Resize and initialize the GL window
 58 {
 59     if (height == 0) {                                // Prevent a divide by zero by
 60         height = 1;                                   // Making height equal one
 61     }
 62
 63     glViewport(0, 0, width, height);                  // Reset the current viewport
 64
 65     /*
 66      *  The following lines set the screen up for a perspective view.
 67      *  Meaning things in the distance get smaller. This creates a realistic looking scene.
 68      *  The perspective is calculated with a 45 degree viewing angle based on
 69      *  the windows width and height. The 0.1f, 100.0f is the starting point and
 70      *  ending point for how deep we can draw into the screen.
 71      *
 72      *  The projection matrix is responsible for adding perspective to our scene.
 73      *  glLoadIdentity() restores the selected matrix to it‘s original state.
 74      *  The modelview matrix is where our object information is stored.
 75      *   Lastly we reset the modelview matrix.
 76      */
 77
 78     glMatrixMode(GL_PROJECTION);                      // Select the projection matrix
 79     glLoadIdentity();                                 // Reset the projection matrix
 80
 81                                                       // Calculate the aspect ratio of the window
 82     gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
 83 //    glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);  // Create orhto 640X480 view (0, 0, at the top)
 84
 85     glMatrixMode(GL_MODELVIEW);                       // Seclet the modelview matrix
 86     glLoadIdentity();                                 // Reset the modelview matrix
 87 }
 88 /******************************************************************************************************************************************/
 89 /******************************************************************************************************************************************/
 90 void VMatMult(GLmatrix16f M, GLvector4f v)
 91 {
 92     GLfloat res[4];
 93     res[0] = M[0] * v[0] + M[4] * v[1] + M[8] * v[2] + M[12] * v[3];
 94     res[1] = M[1] * v[0] + M[5] * v[1] + M[9] * v[2] + M[13] * v[3];
 95     res[2] = M[2] * v[0] + M[6] * v[1] + M[10] * v[2] + M[14] * v[3];
 96     res[3] = M[3] * v[0] + M[7] * v[1] + M[11] * v[2] + M[15] * v[3];
 97     v[0] = res[0];
 98     v[1] = res[1];
 99     v[2] = res[2];
100     v[3] = res[3];
101 }
102
103 int InitGLObject()
104 {
105     if (!readObject("Data/Object2.txt", object)) {
106         return false;
107     }
108     setConnectivity(object);        // Set face to face connectivity
109
110     for (int i = 0; i < object.nFaces; ++i) {
111         calculatePlane(object, object.pFaces[i]);     // Compute plane equations for all faces
112     }
113     return true;
114 }
115
116 int InitGL(GLvoid)                                    // All setup for OpenGL goes here
117 {
118     if (!InitGLObject()) {
119         return false;
120     }
121
122     glShadeModel(GL_SMOOTH);
123     glClearColor(0.0f, 0.0f, 0.0f, 0.5);              // Background
124     glClearDepth(1.0f);                               // Depth buffer setup
125     glClearStencil(0);                                // Clear the stencil buffer to 0
126     glEnable(GL_DEPTH_TEST);
127     glDepthFunc(GL_LEQUAL);
128     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
129
130
131     glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmb);
132     glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDif);
133     glLightfv(GL_LIGHT1, GL_POSITION, LightPos);
134     glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpc);
135
136     glEnable(GL_LIGHT1);
137     glEnable(GL_LIGHTING);
138
139     glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmb);   // Set material ambience
140     glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDif);   // Set material diffuse
141     glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);  // Set material specular
142     glMaterialfv(GL_FRONT, GL_SHININESS, MatShn); // Set material shininess
143
144     glCullFace(GL_BACK);                        // Set culling face to back face
145     glEnable(GL_CULL_FACE);
146     glClearColor(0.1f, 1.0f, 0.5f, 1.0f);       // Greenish color
147
148     q = gluNewQuadric();
149     gluQuadricNormals(q, GL_SMOOTH);            // Generate smooth Normals for the quad
150     gluQuadricTexture(q, GL_FALSE);              // Disable auto texture coords for the quad
151
152     return TRUE;
153 }
154
155 void DrawGLRoom()
156 {
157     glBegin(GL_QUADS);
158         // Floor
159         glNormal3f(0.0f, 1.0f, 0.0f);
160         glVertex3f(-10.0f, -10.0f, -20.0f);
161         glVertex3f(-10.0f, -10.0f, 20.0f);
162         glVertex3f(10.0f, -10.0f, 20.0f);
163         glVertex3f(10.0f, -10.0f, -20.0f);
164         // Ceiling
165         glNormal3f(0.0f, -1.0f, 0.0f);
166         glVertex3f(-10.0f, 10.0f, 20.0f);
167         glVertex3f(-10.0f, 10.0f, -20.0f);
168         glVertex3f(10.0f, 10.0f, -20.0f);
169         glVertex3f(10.0f, 10.0f, 20.0f);
170         // Front Wall
171         glNormal3f(0.0f, 0.0f, 1.0f);
172         glVertex3f(-10.0f, 10.0f, -20.0f);
173         glVertex3f(-10.0f, -10.0f, -20.0f);
174         glVertex3f(10.0f, -10.0f, -20.0f);
175         glVertex3f(10.0f, 10.0f, -20.0f);
176         // Back Wall
177         glNormal3f(0.0f, 0.0f, -1.0f);
178         glVertex3f(10.0f, 10.0f, 20.0f);
179         glVertex3f(10.0f, -10.0f, 20.0f);
180         glVertex3f(-10.0f, -10.0f, 20.0f);
181         glVertex3f(-10.0f, 10.0f, 20.0f);
182         // Left Wall
183         glNormal3f(1.0f, 0.0f, 0.0f);
184         glVertex3f(-10.0f, 10.0f, 20.0f);
185         glVertex3f(-10.0f, -10.0f, 20.0f);
186         glVertex3f(-10.0f, -10.0f, -20.0f);
187         glVertex3f(-10.0f, 10.0f, -20.0f);
188         // Right Wall
189         glNormal3f(-1.0f, 0.0f, 0.0f);
190         glVertex3f(10.0f, 10.0f, -20.0f);
191         glVertex3f(10.0f, -10.0f, -20.0f);
192         glVertex3f(10.0f, -10.0f, 20.0f);
193         glVertex3f(10.0f, 10.0f, 20.0f);
194     glEnd();
195 }
196
197 /*
198  *  For now all we will do is clear the screen to the color we previously decided on,
199  *  clear the depth buffer and reset the scene. We wont draw anything yet.
200  */
201 bool DrawGLScene(GLvoid)                                  // Here‘s where we do all the drawing
202 {
203     GLmatrix16f Minv;
204     GLvector4f wlp, lp;
205
206     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
207
208     glLoadIdentity();
209     glTranslatef(0.0f, 0.0f, -20.0f);
210     glLightfv(GL_LIGHT1, GL_POSITION, LightPos);
211     glTranslatef(SpherePosition[0], SpherePosition[1], SpherePosition[2]);
212     gluSphere(q, 1.5f, 32, 16);
213
214     glLoadIdentity();
215     glRotatef(-yrot, 0.0f, 1.0f, 0.0f);
216     glRotatef(-xrot, 1.0f, 0.0f, 0.0f);
217     glGetFloatv(GL_MODELVIEW_MATRIX, Minv);
218
219     lp[0] = LightPos[0];
220     lp[1] = LightPos[1];
221     lp[2] = LightPos[2];
222     lp[3] = LightPos[3];
223     VMatMult(Minv, lp);
224     glTranslatef(-ObjectPosition[0], -ObjectPosition[1], -ObjectPosition[2]);
225     glGetFloatv(GL_MODELVIEW_MATRIX, Minv);
226
227     wlp[0] = 0.0f;
228     wlp[1] = 0.0f;
229     wlp[2] = 0.0f;
230     wlp[3] = 1.0f;
231     VMatMult(Minv, wlp);
232
233     lp[0] += wlp[0];
234     lp[1] += wlp[1];
235     lp[2] += wlp[2];
236
237     glColor4f(0.7f, 0.4f, 0.0f, 1.0f);
238     glLoadIdentity();
239     glTranslatef(0.0f, 0.0f, -20.0f);
240     DrawGLRoom();
241     glTranslatef(ObjectPosition[0], ObjectPosition[1], ObjectPosition[2]);
242     glRotatef(xrot, 1.0f, 0.0f, 0.0f);
243     glRotatef(yrot, 0.0f, 1.0f, 0.0f);
244     drawObject(object);
245     castShadow(object, lp);
246
247     glColor4f(0.7f, 0.4f, 0.0f, 1.0f);
248     glDisable(GL_LIGHTING);
249     glDepthMask(GL_FALSE);
250     glTranslatef(lp[0], lp[1], lp[2]);
251
252     gluSphere(q, 0.2f, 16, 8);
253     glEnable(GL_LIGHTING);
254     glDepthMask(GL_TRUE);
255     xrot += xspeed;
256     yrot += yspeed;
257     glFlush();
258     return true;
259 }
260
261 void ProcessKeyboard()
262 {
263     // Spin object
264     if (keys[VK_LEFT]) yspeed -= 0.001f;
265     if (keys[VK_RIGHT]) yspeed += 0.001f;
266     if (keys[VK_UP]) xspeed -= 0.001f;
267     if (keys[VK_DOWN]) xspeed += 0.001f;
268
269     // Adjust light‘s position
270     if (keys[‘L‘]) LightPos[0] += 0.01f;
271     if (keys[‘J‘]) LightPos[0] -= 0.01f;
272     if (keys[‘I‘]) LightPos[1] += 0.01f;
273     if (keys[‘K‘]) LightPos[1] -= 0.01f;
274     if (keys[‘O‘]) LightPos[2] += 0.01f;
275     if (keys[‘U‘]) LightPos[2] -= 0.01f;
276
277     // Adjust object‘s position
278     if (keys[VK_NUMPAD6]) ObjectPosition[0] += 0.01f;
279     if (keys[VK_NUMPAD4]) ObjectPosition[0] -= 0.01f;
280     if (keys[VK_NUMPAD8]) ObjectPosition[1] += 0.01f;
281     if (keys[VK_NUMPAD5]) ObjectPosition[1] -= 0.01f;
282     if (keys[VK_NUMPAD9]) ObjectPosition[2] += 0.01f;
283     if (keys[VK_NUMPAD7]) ObjectPosition[2] -= 0.01f;
284
285     // Adjust ball‘s position
286     if (keys[‘D‘]) SpherePosition[0] += 0.01f;
287     if (keys[‘A‘]) SpherePosition[0] -= 0.01f;
288     if (keys[‘W‘]) SpherePosition[1] += 0.01f;
289     if (keys[‘S‘]) SpherePosition[1] -= 0.01f;
290     if (keys[‘E‘]) SpherePosition[2] += 0.01f;
291     if (keys[‘Q‘]) SpherePosition[2] -= 0.01f;
292 }
293
294 /******************************************************************************************************************************************/
295 /******************************************************************************************************************************************/
296 /*
297  *  The job of KillGLWindow() is to release the Rendering Context,
298  *  the Device Context and finally the Window Handle.
299  */
300
301 GLvoid KillGLWindow(GLvoid)                              // Properly kill the window
302 {
303     if (fullscreen) {                                    // Are we in fullscreen mode
304
305         /*
306          *  We use ChangeDisplaySettings(NULL,0) to return us to our original desktop.
307          *  After we‘ve switched back to the desktop we make the cursor visible again.
308          */
309
310         ChangeDisplaySettings(NULL, 0);                  // if so switch back to the desktop
311         ShowCursor(TRUE);                                // Show mouse pointer
312     }
313
314     if (hRC) {                                           // Do we have a rendering context
315         if (!wglMakeCurrent(NULL, NULL)) {                // Are we able to release the DC and RC contexts
316             MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
317         }
318
319         if (!wglDeleteContext(hRC)) {                     // Are we able to delete the RC
320             MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
321             hRC = NULL;                                  // Set RC to NULL
322         }
323
324         if (hDC && !ReleaseDC(hWnd, hDC)) {              // Are we able to release the DC
325             MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
326             hDC = NULL;                                  // Set DC to NULL
327         }
328         if (hWnd && !DestroyWindow(hWnd)) {              // Are we able to destroy the window
329             MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
330             hWnd = NULL;                                 // Set hWnd to NULL
331         }
332
333         if (!UnregisterClass("OpenGL", hInstance)) {     // Are we able to unregister class
334             MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
335             hInstance = NULL;                            // Set hInstance to NULL
336         }
337     }
338 //******************************************************************************************************************************************/
339 //******************************************************************************************************************************************/
340     killObject(object);
341 //******************************************************************************************************************************************/
342 //******************************************************************************************************************************************/
343 }
344
345 /*
346  * The next section of code creates our OpenGL Window.
347  */
348
349 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
350 {
351     /*
352      * Find  a pixel format that matches the one we want
353      */
354     GLuint PixelFormat;                                  // Holds the result after serching for a match
355
356     /*
357      * Before you create a window, you MUST register a Class for the window
358      */
359     WNDCLASS wc;                                         // Windows class structure
360
361     /*
362      *  dwExStyle and dwStyle will store the Extended and normal Window Style Information.
363     */
364     DWORD dwExStyle;                                     // Window extend style
365     DWORD dwStyle;                                       // Window style
366
367
368     RECT WindowRect;                                     // Grabs rectangle upper left/lower right values
369     WindowRect.left = (long)0;                           // Set left value to 0
370     WindowRect.right = (long)width;                      // Set right value to requested width
371     WindowRect.top = (long)0;                            // Set top value to 0
372     WindowRect.bottom = (long)height;                    // Set bottom value to requested height
373
374     fullscreen = fullscreenflag;                         // Set the global fullscreen flag
375
376     /*
377      *  The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized.
378      *  CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications.
379      *  WndProc is the procedure that watches for messages in our program.
380      *  No extra Window data is used so we zero the two fields. Then we set the instance.
381      *  Next we set hIcon to NULL meaning we don‘t want an ICON in the Window,
382      *  and for a mouse pointer we use the standard arrow. The background color doesn‘t matter
383      *  (we set that in GL). We don‘t want a menu in this Window so we set it to NULL,
384      *  and the class name can be any name you want. I‘ll use "OpenGL" for simplicity.
385      */
386     hInstance = GetModuleHandle(NULL);                   // Grab an instance for our window
387     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;       // Redraw on move, and own DC for window
388     wc.lpfnWndProc = (WNDPROC)WndProc;                   // WndProc handles message
389     wc.cbClsExtra = 0;                                   // No extra window date
390     wc.cbWndExtra = 0;                                   // No extra window date
391     wc.hInstance = hInstance;                            // set the instance
392     wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);              // Load the default icon
393     wc.hCursor = LoadCursor(NULL, IDC_ARROW);            // Load the arrow pointer
394     wc.hbrBackground = NULL;                             // No background requried for GL
395     wc.lpszMenuName = NULL;                              // We don‘t want a menu
396     wc.lpszClassName = "OpenGL";                         // set the class name
397
398     if (!RegisterClass(&wc)) {                           // Attempt to register the window class
399         MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
400         return FALSE;                                    // Exit and return false
401     }
402
403     if (fullscreen) {                                    // attempt fullsreen model
404
405         /*
406         T*  here are a few very important things you should keep in mind when switching to full screen mode.
407          *  Make sure the width and height that you use in fullscreen mode is the same as
408          *  the width and height you plan to use for your window, and most importantly,
409          *  set fullscreen mode BEFORE you create your window.
410          */
411         DEVMODE dmScreenSettings;                        // Device mode
412         memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory‘s cleared
413         dmScreenSettings.dmSize = sizeof(dmScreenSettings);     // Size of devmode structure
414         dmScreenSettings.dmPelsWidth = width;            // Select window width
415         dmScreenSettings.dmPelsHeight = height;          // Select window height
416         dmScreenSettings.dmBitsPerPel = bits;            // Select bits per pixel
417         dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
418
419         /*
420          *  In the line below ChangeDisplaySettings tries to switch to a mode that matches
421          *  what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes,
422          *  because it‘s supposed to remove the start bar at the bottom of the screen,
423          *  plus it doesn‘t move or resize the windows on your desktop when you switch to
424          *  fullscreen mode and back.
425          */
426         //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar
427         if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
428             //If the mode fails, offer two options. Quit or run in a window
429             if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use"
430                 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
431             {
432                 fullscreen = FALSE;                       // Select windowed mode (fullscreen=FLASE)
433             }
434             else {
435                 // Pop up a message box letting user know the programe is closing.
436                 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP);
437                 return FALSE;                             // Exit and return FALSE
438             }
439         }
440     }
441
442     if (fullscreen) {                                     // Are we still in fullscreen mode
443
444         /*
445          *  If we are still in fullscreen mode we‘ll set the extended style to WS_EX_APPWINDOW,
446          *  which force a top level window down to the taskbar once our window is visible.
447          *  For the window style we‘ll create a WS_POPUP window.
448          *  This type of window has no border around it, making it perfect for fullscreen mode.
449
450          *  Finally, we disable the mouse pointer. If your program is not interactive,
451          *  it‘s usually nice to disable the mouse pointer when in fullscreen mode. It‘s up to you though.
452          */
453         dwExStyle = WS_EX_APPWINDOW;                      // Window extended style
454         dwStyle = WS_POPUP;                               // Window style
455         ShowCursor(FALSE);                                // Hide mosue pointer
456     }
457     else {
458
459         /*
460          *  If we‘re using a window instead of fullscreen mode,
461          *  we‘ll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look.
462          *  For style we‘ll use WS_OVERLAPPEDWINDOW instead of WS_POPUP.
463          *  WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border,
464          *  window menu, and minimize / maximize buttons.
465          */
466         dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   // Window extended style
467         dwStyle = WS_OVERLAPPEDWINDOW;                    // Window style
468     }
469
470     /*
471      *  By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders,
472      *  instead, the window will be made larger to account for the pixels needed to draw the window border.
473      *  In fullscreen mode, this command has no effect.
474      */
475     AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);  // Adjust window to true resqusted
476
477     /*
478      *  WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly.
479      *  These styles prevent other windows from drawing over or into our OpenGL Window.
480      */
481     if (!(hWnd = CreateWindowEx(dwExStyle,                // Extended style for the window
482         "OpenGL",                                         // Class name
483         title,                                            // Window title
484         WS_CLIPSIBLINGS |                                 // Requried window style
485         WS_CLIPCHILDREN |                                 // Requried window style
486         dwStyle,                                          // Select window style
487         0, 0,                                             // Window position
488         WindowRect.right - WindowRect.left,               // Calculate adjusted window width
489         WindowRect.bottom - WindowRect.top,               // Calculate adjusted window height
490         NULL,                                             // No parent window
491         NULL,                                             // No menu
492         hInstance,                                        // Instance
493         NULL)))                                           // Don‘t pass anything to WM_CREATE
494     {
495         KillGLWindow();                                   //Reset the display
496         MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
497         return FALSE;                                     // Retrurn FALSE;
498     }
499
500     /*
501      *  aside from the stencil buffer and the (slow) accumulation buffer
502      */
503     static PIXELFORMATDESCRIPTOR pfd =                    // pfd tells windows how we want things to be
504     {
505         sizeof(PIXELFORMATDESCRIPTOR),                    // Size of this pixel format descriptor
506         1,                                                // Version number
507         PFD_DRAW_TO_WINDOW |                              // Format must support window
508         PFD_SUPPORT_OPENGL |                              // Format must support OpenGL
509         PFD_DOUBLEBUFFER,                                 // Must support double buffer
510         PFD_TYPE_RGBA,                                    // Request an RGBA format
511         bits,                                             // Select our color depth
512         0, 0, 0, 0, 0, 0,                                 // Color bits ignored
513         0,                                                // No alpha buffer
514         0,                                                // shift bit ignored
515         0,                                                // No accumulation buffer
516         0, 0, 0, 0,                                       // Accumulation bits ignored
517         16,                                               // 16Bits Z_Buffer (depth buffer)
518         1,                                                // stencil buffer
519         0,                                                // No auxiliary buffer
520         PFD_MAIN_PLANE,                                   // Main drawing layer
521         0,                                                // Reserved
522         0, 0, 0                                           // Layer makes ignored
523     };
524
525     if (!(hDC = GetDC(hWnd))) {                           // Did we get a device context
526         KillGLWindow();                                   // Reset the display
527         MessageBox(NULL, "Can‘t create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
528         return FALSE;                                     // Return FALSE
529     }
530
531     if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) {  // Did window find a matching pixel format
532         KillGLWindow();                                   // Reset the display
533         MessageBox(NULL, "Can‘t find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
534         return FALSE;                                     // Return FALSE;
535     }
536
537     if (!SetPixelFormat(hDC, PixelFormat, &pfd)) {        // Are we able to set the pixel format
538         KillGLWindow();                                   // Reset the display
539         MessageBox(NULL, "Can‘t set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
540         return FALSE;                                     // Return FALSE;
541     }
542
543     if (!(hRC = wglCreateContext(hDC))) {                 // Are we able to rendering context
544         KillGLWindow();                                   // Reset the display
545         MessageBox(NULL, "Can‘t create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
546         return FALSE;                                     // Return FASLE;
547     }
548
549     if (!wglMakeCurrent(hDC, hRC)) {                      // Try to activate the rendering context
550         KillGLWindow();                                   // Reset the display
551         MessageBox(NULL, "Can‘t activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
552         return FALSE;                                     // Return FALSE
553     }
554
555     /*
556      *  ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen.
557      */
558     ShowWindow(hWnd, SW_SHOW);                            // Show the window
559     SetForegroundWindow(hWnd);                            // slightly higher priority
560     SetFocus(hWnd);                                       // Sets keyboard focus to the window
561     ReSizeGLScene(width, height);                         // Set up our perspective GL screen
562
563 /*
564  *  we can set up lighting, textures, and anything else that needs to be setup in InitGL().
565  */
566     if (!InitGL()) {                                      // Initialize our newly created GL window
567         KillGLWindow();                                   // Reset the display
568         MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
569         return FALSE;                                     // Return FALSE
570     }
571     return TRUE;
572 }
573
574 LRESULT CALLBACK WndProc(HWND hWnd,                       // Handle for this window
575     UINT uMsg,                                            // Message for this window
576     WPARAM wParam,                                        // Additional message information
577     LPARAM lParam)                                        // Additional message information
578 {
579     switch (uMsg) {                                       // Check for window message
580     case WM_ACTIVATE: {                               // Check minimization state
581         if (!HIWORD(wParam)) {
582             active = TRUE;                            // Program is active
583         }
584         else {
585             active = FALSE;                           // Program is no longer active
586         }
587         return 0;                                     // Return to the message loop
588     }
589     case WM_SYSCOMMAND: {                             // Intercept system commands
590         switch (wParam) {                             // Check system calls
591         case SC_SCREENSAVE:                       // Screensaver trying to start
592         case SC_MONITORPOWER:                     // Monitor trying to enter powersave
593             return 0;                                 // Prevent form happening
594         }
595         break;                                        // Exit
596     }
597     case WM_CLOSE: {                                  // Did we receive a close message
598         PostQuitMessage(0);                           // Send a quit message
599         return 0;
600     }
601     case WM_KEYDOWN: {                                // Is a key being held down
602         keys[wParam] = TRUE;                          // if so, mark it as TRUE
603         return 0;                                     // Jump back
604     }
605     case WM_KEYUP: {                                  // Has a key been released
606         keys[wParam] = FALSE;                         // if so, mark it as FALSE
607         return 0;                                     // Jump back
608     }
609     case WM_SIZE: {                                   // Resize the OpenGL window
610         ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));   // LoWord = width HiWord = height
611         return 0;                                     // Jump back
612     }
613     }
614     return DefWindowProc(hWnd, uMsg, wParam, lParam);     // Pass all unhandled message to DefWindwProc
615 }
616
617 int WINAPI WinMain(HINSTANCE hInstance,                   // Instance
618     HINSTANCE hPrevInstance,                              // Previous instance
619     LPSTR lpCmdLine,                                      // Command line parameters
620     int nCmdShow)                                         // Window show state
621 {
622     MSG msg;                                              // Window message structure
623     BOOL done = FALSE;                                    // Bool variable to exit loop
624                                                           // Ask the user which screen mode they prefer
625     if (MessageBox(NULL, "Would you like to run in fullscreen mode?",
626         "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO)
627     {
628         fullscreen = FALSE;                               // Window mode
629     }
630     // Create our OpenGL window
631     if (!CreateGLWindow("3D Shapes", 800, 600, 32, fullscreen)) {  // (Modified)
632         return 0;                                         // Quit if window was not create
633     }
634     while (!done) {                                       // Loop that runs until donw = TRUE
635         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {   // Is there a message wating
636             if (msg.message == WM_QUIT) {                 // Havw we received a quit message
637                 done = TRUE;                              // if so done  = TRUE
638             }
639             else {                                        // If not, deal with window message
640                 TranslateMessage(&msg);                   // Translate message
641                 DispatchMessage(&msg);                    // Dispatch message
642             }
643         }
644         else {
645             // Draw the scene. Watch for ESC key and quit message from DrawGLScene()
646             if (active) {                                 // Program active
647                 if (keys[VK_ESCAPE]) {                    // Was ESC pressed
648                     done = TRUE;                          // ESC signalled a quit
649                 }
650                 else {                                    // Not time to quit, update screen
651                     DrawGLScene();                        // Draw scene
652                     SwapBuffers(hDC);                     // Swap buffers (double buffering)
653                     ProcessKeyboard();
654                 }
655             }
656             /*
657             *  It allows us to press the F1 key to switch from fullscreen mode to
658             *  windowed mode or windowed mode to fullscreen mode.
659             */
660             if (keys[VK_F1]) {                            // Is F1 being pressed
661                 keys[VK_F1] = FALSE;                      // If so make key FASLE
662                 KillGLWindow();                           // Kill our current window
663                 fullscreen = !fullscreen;                 // Toggle fullscreen / window mode
664                 //Recreate our OpenGL window(modified)
665                 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) {
666                     return 0;                             // Quit if window was not create
667                 }
668             }
669         }
670     }
671     // Shutdown
672     KillGLWindow();                                       // Kill the window
673     return (msg.wParam);                                  // Exit the program
674 }

work.cpp

Thanks for Nehe‘s tutorials, this is his home.

时间: 2024-11-02 23:35:58

outdated: 27.Shadows的相关文章

react+redux+webpack+git技术栈

1 一.git bash here 2 mdkr 3 cnpm init -y 4 ls -a 5 ls -l 6 ls -la隐藏的也可查看 7 cat package.json 8 二.npm 9 npm i webpack-dev-server -g 10 全局:任何目录运行 11 本地:本地需要调用附带的插件 12 npm list 13 npm list -g 14 npm uninstall supervisor -g 全局删除 15 npm remove supervisor -g

吉萨法律时间浪费拉丝粉;阿里山

http://www.ebay.com/cln/tmotshu/book/157890749018/2015.01.27.html http://www.ebay.com/cln/tmotshu/book/157890755018/2015.01.27.html http://www.ebay.com/cln/tmotshu/book/157890757018/2015.01.27.html http://www.ebay.com/cln/tmotshu/book/157890775018/20

10.23 linux任务计划cron10.24chkconfig工具10.25 systemd管理服务10.26 unit介绍 10.27 target介绍

- 10.23 linux任务计划cron - 10.24 chkconfig工具 - 10.25 systemd管理服务 - 10.26 unit介绍 - 10.27 target介绍 - 扩展 1. anacron http://blog.csdn.net/strikers1982/article/details/4787226  2. xinetd服(默认机器没有安装这个服务,需要yum install xinetd安装) http://blog.sina.com.cn/s/blog_46

20.27分发系统介绍;20.28expect脚本远程登录;20.29expect脚本远程执行命令;20.30expect脚本传递参数

20.27 分发系统介绍 shell项目-分发系统-expect 20.28 expect脚本远程登录 1. 安装expect [[email protected] ~]# yum install -y expect 自动远程登录 2. 创建配置1.expect脚本(远程登录) [[email protected] ~]# vim 1.expect 添加内容(自动远程登录hao2机器并执行命令) #! /usr/bin/expect set host "192.168.211.129"

Oracle SQL语言DDL和对象管理_超越OCP精通Oracle视频教程培训27

Oracle SQL语言DDL和对象管理_超越OCP精通Oracle视频教程培训27 本课程介绍: Oracle视频教程,风哥本套oracle教程培训是<<Oracle数据库SQL语言实战培训教程>>的第2/5套:Oracle SQL语言DDL和对象管理.主要学习Oracle数据库模式对象和表中可用的数据类型,表/临时表的创建与使用,索引/约束的创建与管理,视图/同义词/序列的创建和使用,触发器/存储过程/包的创建和使用. Oracle SQL语言DDL和对象管理,课程内容详细如下

软工课设第一天 6.27

day1 姓名 王日 时间 2016年6月27日 学习内容 1)  选择java编程 2)  人员分工 编写代码: 段杰(组长).于博文.张鹏 测试用例: 陶元睿.王日(我) 美工&文档整理 杨子彤 3)  系统反馈表填写收集 4)  建立微信群,及时发布通知 所遇问题 1)  有组员java环境未搭建好 2)  由用户反馈发现的问题 游戏难度过于简单 缺乏创新点 不能存储成绩 解决方案 1)  增加金币&游戏道具加强游戏性 2)  增加难度选择 3)  添加成绩本地存储,进一步可以联网

27款经典的CSS框架

利用 CSS 框架,可以简化你的工作,提高工作效率.CSS 框架是一系列 CSS 文件的集合体,包含了基本的元素重置,页面排版.网格布局.表单样式.通用规则等代码块.下面给你推荐了27款优秀的CSS框架,你可以选用. 1. 960gs 960 像素的页面宽度似乎成为了一种设计标准,在当前各种分辨率下,能够很好地展现网页内容.提供较为常用的尺寸来简化网页设计过程,使工作简单高效. 2. YUI 2: Grids CSS 芒果曾经介绍过由雅虎开发小组推出的 YUI,而这个 YUI Grids CSS

【Aguin】第六周 6.21-6.27

6.21 最长不下降子序列 LIS有nlgn的算法.纯学dp.  Aguin 矩形嵌套 紫薯题.  Aguin 6.22 UVA 103 Stacking Boxes 升级版的n维矩形.打印一个路径就好.然而数据太亲民.  Aguin 6.23 发觉自己对dp的理解就有问题.紫薯啃的不明白. 文章也难找到合适的. 有的过于抽象.实例又容易固化思维. P1084 数字三角形4 稍微改了下就不会了.只能说没领会. 往上往下dp.  Aguin P1004 滑雪 题目没什么.代码丑.  Aguin 6

java每日小算法(27)

/* [程序27]  题目:求100之内的素数    */ package test; import java.util.Scanner; public class test { public static boolean prime(int number) { boolean flag = true; int mid = (int)Math.sqrt(number); for(int i = 2; i< mid+1; i++) { if(number % i == 0) { flag = fa