Advertisement
Guest User

grafhazi3

a guest
Dec 9th, 2019
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 27.22 KB | None | 0 0
  1. //=============================================================================================
  2. // Mintaprogram: Zöld háromszög. Ervenyes 2019. osztol.
  3. //
  4. // A beadott program csak ebben a fajlban lehet, a fajl 1 byte-os ASCII karaktereket tartalmazhat, BOM kihuzando.
  5. // Tilos:
  6. // - mast "beincludolni", illetve mas konyvtarat hasznalni
  7. // - faljmuveleteket vegezni a printf-et kiveve
  8. // - Mashonnan atvett programresszleteket forrasmegjeloles nelkul felhasznalni es
  9. // - felesleges programsorokat a beadott programban hagyni!!!!!!!
  10. // - felesleges kommenteket a beadott programba irni a forrasmegjelolest kommentjeit kiveve
  11. // ---------------------------------------------------------------------------------------------
  12. // A feladatot ANSI C++ nyelvu forditoprogrammal ellenorizzuk, a Visual Studio-hoz kepesti elteresekrol
  13. // es a leggyakoribb hibakrol (pl. ideiglenes objektumot nem lehet referencia tipusnak ertekul adni)
  14. // a hazibeado portal ad egy osszefoglalot.
  15. // ---------------------------------------------------------------------------------------------
  16. // A feladatmegoldasokban csak olyan OpenGL fuggvenyek hasznalhatok, amelyek az oran a feladatkiadasig elhangzottak
  17. // A keretben nem szereplo GLUT fuggvenyek tiltottak.
  18. //
  19. // NYILATKOZAT
  20. // ---------------------------------------------------------------------------------------------
  21. // Nev    : Szabados Ádám
  22. // Neptun : HKZEOI
  23. // ---------------------------------------------------------------------------------------------
  24. // ezennel kijelentem, hogy a feladatot magam keszitettem, es ha barmilyen segitseget igenybe vettem vagy
  25. // mas szellemi termeket felhasznaltam, akkor a forrast es az atvett reszt kommentekben egyertelmuen jeloltem.
  26. // A forrasmegjeloles kotelme vonatkozik az eloadas foliakat es a targy oktatoi, illetve a
  27. // grafhazi doktor tanacsait kiveve barmilyen csatornan (szoban, irasban, Interneten, stb.) erkezo minden egyeb
  28. // informaciora (keplet, program, algoritmus, stb.). Kijelentem, hogy a forrasmegjelolessel atvett reszeket is ertem,
  29. // azok helyessegere matematikai bizonyitast tudok adni. Tisztaban vagyok azzal, hogy az atvett reszek nem szamitanak
  30. // a sajat kontribucioba, igy a feladat elfogadasarol a tobbi resz mennyisege es minosege alapjan szuletik dontes.
  31. // Tudomasul veszem, hogy a forrasmegjeloles kotelmenek megsertese eseten a hazifeladatra adhato pontokat
  32. // negativ elojellel szamoljak el es ezzel parhuzamosan eljaras is indul velem szemben.
  33. //=============================================================================================
  34. //=============================================================================================
  35. // Computer Graphics Sample Program: 3D engine-let
  36. // Shader: Gouraud, Phong, NPR
  37. // Material: diffuse + Phong-Blinn
  38. // Texture: CPU-procedural
  39. // Geometry: sphere, torus, mobius
  40. // Camera: perspective
  41. // Light: point
  42. //=============================================================================================
  43.  
  44. #include "framework.h"
  45.  
  46. const int tessellationLevel = 20;
  47.  
  48. //---------------------------
  49. struct Camera { // 3D camera
  50. //---------------------------
  51.     vec3 wEye, wLookat, wVup;   // extinsic
  52.     float fov, asp, fp, bp;     // intrinsic
  53. public:
  54.     Camera() {
  55.         asp = (float)windowWidth / windowHeight;
  56.         fov = 75.0f * (float)M_PI / 180.0f;
  57.         fp = 1; bp = 10;
  58.     }
  59.     mat4 V() { // view matrix: translates the center to the origin
  60.         vec3 w = normalize(wEye - wLookat);
  61.         vec3 u = normalize(cross(wVup, w));
  62.         vec3 v = cross(w, u);
  63.         return TranslateMatrix(wEye * (-1)) * mat4(u.x, v.x, w.x, 0,
  64.             u.y, v.y, w.y, 0,
  65.             u.z, v.z, w.z, 0,
  66.             0, 0, 0, 1);
  67.     }
  68.  
  69.     mat4 P() { // projection matrix
  70.         return mat4(1 / (tan(fov / 2) * asp), 0, 0, 0,
  71.             0, 1 / tan(fov / 2), 0, 0,
  72.             0, 0, -(fp + bp) / (bp - fp), -1,
  73.             0, 0, -2 * fp * bp / (bp - fp), 0);
  74.     }
  75.  
  76.     void Animate(float t) { }
  77. };
  78.  
  79. //---------------------------
  80. struct Material {
  81.     //---------------------------
  82.     vec3 kd, ks, ka;
  83.     float shininess;
  84. };
  85.  
  86. //---------------------------
  87. struct Light {
  88.     //---------------------------
  89.     vec3 La, Le;
  90.     vec4 wLightPos;
  91.  
  92.     void Animate(float t) { }
  93. };
  94.  
  95. //---------------------------
  96. class CheckerBoardTexture : public Texture {
  97.     //---------------------------
  98. public:
  99.     CheckerBoardTexture(const int width = 0, const int height = 0) : Texture() {
  100.         std::vector<vec4> image(width * height);
  101.         const vec4 yellow(1, 1, 0, 1), blue(0, 0, 1, 1);
  102.         for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) {
  103.             image[y * width + x] = (x & 1) ^ (y & 1) ? yellow : blue;
  104.         }
  105.         create(width, height, image, GL_NEAREST);
  106.     }
  107. };
  108.  
  109. //---------------------------
  110. struct RenderState {
  111.     //---------------------------
  112.     mat4               MVP, M, Minv, V, P;
  113.     Material* material;
  114.     std::vector<Light> lights;
  115.     Texture* texture;
  116.     vec3               wEye;
  117. };
  118.  
  119. //---------------------------
  120. class Shader : public GPUProgram {
  121.     //---------------------------
  122. public:
  123.     virtual void Bind(RenderState state) = 0;
  124.  
  125.     void setUniformMaterial(const Material& material, const std::string& name) {
  126.         setUniform(material.kd, name + ".kd");
  127.         setUniform(material.ks, name + ".ks");
  128.         setUniform(material.ka, name + ".ka");
  129.         setUniform(material.shininess, name + ".shininess");
  130.     }
  131.  
  132.     void setUniformLight(const Light& light, const std::string& name) {
  133.         setUniform(light.La, name + ".La");
  134.         setUniform(light.Le, name + ".Le");
  135.         setUniform(light.wLightPos, name + ".wLightPos");
  136.     }
  137. };
  138.  
  139. //---------------------------
  140. class GouraudShader : public Shader {
  141.     //---------------------------
  142.     const char* vertexSource = R"(
  143.         #version 330
  144.         precision highp float;
  145.  
  146.         struct Light {
  147.             vec3 La, Le;
  148.             vec4 wLightPos;
  149.         };
  150.        
  151.         struct Material {
  152.             vec3 kd, ks, ka;
  153.             float shininess;
  154.         };
  155.  
  156.         uniform mat4  MVP, M, Minv;  // MVP, Model, Model-inverse
  157.         uniform Light[8] lights;     // light source direction
  158.         uniform int   nLights;       // number of light sources
  159.         uniform vec3  wEye;          // pos of eye
  160.         uniform Material  material;  // diffuse, specular, ambient ref
  161.  
  162.         layout(location = 0) in vec3  vtxPos;            // pos in modeling space
  163.         layout(location = 1) in vec3  vtxNorm;           // normal in modeling space
  164.  
  165.         out vec3 radiance;          // reflected radiance
  166.  
  167.         void main() {
  168.             gl_Position = vec4(vtxPos, 1) * MVP; // to NDC
  169.             // radiance computation
  170.             vec4 wPos = vec4(vtxPos, 1) * M;   
  171.             vec3 V = normalize(wEye * wPos.w - wPos.xyz);
  172.             vec3 N = normalize((Minv * vec4(vtxNorm, 0)).xyz);
  173.             if (dot(N, V) < 0) N = -N;  // prepare for one-sided surfaces like Mobius or Klein
  174.  
  175.             radiance = vec3(0, 0, 0);
  176.             for(int i = 0; i < nLights; i++) {
  177.                 vec3 L = normalize(lights[i].wLightPos.xyz * wPos.w - wPos.xyz * lights[i].wLightPos.w);
  178.                 vec3 H = normalize(L + V);
  179.                 float cost = max(dot(N,L), 0), cosd = max(dot(N,H), 0);
  180.                 radiance += material.ka * lights[i].La + (material.kd * cost + material.ks * pow(cosd, material.shininess)) * lights[i].Le;
  181.             }
  182.         }
  183.     )";
  184.  
  185.     // fragment shader in GLSL
  186.     const char* fragmentSource = R"(
  187.         #version 330
  188.         precision highp float;
  189.  
  190.         in  vec3 radiance;      // interpolated radiance
  191.         out vec4 fragmentColor; // output goes to frame buffer
  192.  
  193.         void main() {
  194.             fragmentColor = vec4(radiance, 1);
  195.         }
  196.     )";
  197. public:
  198.     GouraudShader() { create(vertexSource, fragmentSource, "fragmentColor"); }
  199.  
  200.     void Bind(RenderState state) {
  201.         Use();      // make this program run
  202.         setUniform(state.MVP, "MVP");
  203.         setUniform(state.M, "M");
  204.         setUniform(state.Minv, "Minv");
  205.         setUniform(state.wEye, "wEye");
  206.         setUniformMaterial(*state.material, "material");
  207.  
  208.         setUniform((int)state.lights.size(), "nLights");
  209.         for (unsigned int i = 0; i < state.lights.size(); i++) {
  210.             setUniformLight(state.lights[i], std::string("lights[") + std::to_string(i) + std::string("]"));
  211.         }
  212.     }
  213. };
  214.  
  215. //---------------------------
  216. class PhongShader : public Shader {
  217.     //---------------------------
  218.     const char* vertexSource = R"(
  219.         #version 330
  220.         precision highp float;
  221.  
  222.         struct Light {
  223.             vec3 La, Le;
  224.             vec4 wLightPos;
  225.         };
  226.  
  227.         uniform mat4  MVP, M, Minv; // MVP, Model, Model-inverse
  228.         uniform Light[8] lights;    // light sources
  229.         uniform int   nLights;
  230.         uniform vec3  wEye;         // pos of eye
  231.  
  232.         layout(location = 0) in vec3  vtxPos;            // pos in modeling space
  233.         layout(location = 1) in vec3  vtxNorm;           // normal in modeling space
  234.         layout(location = 2) in vec2  vtxUV;
  235.  
  236.         out vec3 wNormal;           // normal in world space
  237.         out vec3 wView;             // view in world space
  238.         out vec3 wLight[8];         // light dir in world space
  239.         out vec2 texcoord;
  240.  
  241.         void main() {
  242.             gl_Position = vec4(vtxPos, 1) * MVP; // to NDC
  243.             // vectors for radiance computation
  244.             vec4 wPos = vec4(vtxPos, 1) * M;
  245.             for(int i = 0; i < nLights; i++) {
  246.                 wLight[i] = lights[i].wLightPos.xyz * wPos.w - wPos.xyz * lights[i].wLightPos.w;
  247.             }
  248.             wView  = wEye * wPos.w - wPos.xyz;
  249.             wNormal = (Minv * vec4(vtxNorm, 0)).xyz;
  250.             texcoord = vtxUV;
  251.         }
  252.     )";
  253.  
  254.     // fragment shader in GLSL
  255.     const char* fragmentSource = R"(
  256.         #version 330
  257.         precision highp float;
  258.  
  259.         struct Light {
  260.             vec3 La, Le;
  261.             vec4 wLightPos;
  262.         };
  263.  
  264.         struct Material {
  265.             vec3 kd, ks, ka;
  266.             float shininess;
  267.         };
  268.  
  269.         uniform Material material;
  270.         uniform Light[8] lights;    // light sources
  271.         uniform int   nLights;
  272.         uniform sampler2D diffuseTexture;
  273.  
  274.         in  vec3 wNormal;       // interpolated world sp normal
  275.         in  vec3 wView;         // interpolated world sp view
  276.         in  vec3 wLight[8];     // interpolated world sp illum dir
  277.         in  vec2 texcoord;
  278.        
  279.        out vec4 fragmentColor; // output goes to frame buffer
  280.  
  281.         void main() {
  282.             vec3 N = normalize(wNormal);
  283.             vec3 V = normalize(wView);
  284.             if (dot(N, V) < 0) N = -N;  // prepare for one-sided surfaces like Mobius or Klein
  285.             vec3 texColor = texture(diffuseTexture, texcoord).rgb;
  286.             vec3 ka = material.ka * texColor;
  287.             vec3 kd = material.kd * texColor;
  288.  
  289.             vec3 radiance = vec3(0, 0, 0);
  290.             for(int i = 0; i < nLights; i++) {
  291.                 vec3 L = normalize(wLight[i]);
  292.                 vec3 H = normalize(L + V);
  293.                 float cost = max(dot(N,L), 0), cosd = max(dot(N,H), 0);
  294.                 // kd and ka are modulated by the texture
  295.                 radiance += ka * lights[i].La +
  296.                           (kd * texColor * cost + material.ks * pow(cosd, material.shininess)) * lights[i].Le;
  297.             }
  298.             fragmentColor = vec4(radiance, 1);
  299.         }
  300.     )";
  301. public:
  302.     PhongShader() { create(vertexSource, fragmentSource, "fragmentColor"); }
  303.  
  304.     void Bind(RenderState state) {
  305.         Use();      // make this program run
  306.         setUniform(state.MVP, "MVP");
  307.         setUniform(state.M, "M");
  308.         setUniform(state.Minv, "Minv");
  309.         setUniform(state.wEye, "wEye");
  310.         setUniform(*state.texture, std::string("diffuseTexture"));
  311.         setUniformMaterial(*state.material, "material");
  312.  
  313.         setUniform((int)state.lights.size(), "nLights");
  314.         for (unsigned int i = 0; i < state.lights.size(); i++) {
  315.             setUniformLight(state.lights[i], std::string("lights[") + std::to_string(i) + std::string("]"));
  316.         }
  317.     }
  318. };
  319.  
  320. //---------------------------
  321. class NPRShader : public Shader {
  322.     //---------------------------
  323.     const char* vertexSource = R"(
  324.         #version 330
  325.         precision highp float;
  326.  
  327.         uniform mat4  MVP, M, Minv; // MVP, Model, Model-inverse
  328.         uniform vec4  wLightPos;
  329.         uniform vec3  wEye;         // pos of eye
  330.  
  331.         layout(location = 0) in vec3  vtxPos;            // pos in modeling space
  332.         layout(location = 1) in vec3  vtxNorm;           // normal in modeling space
  333.         layout(location = 2) in vec2  vtxUV;
  334.  
  335.         out vec3 wNormal, wView, wLight;                // in world space
  336.         out vec2 texcoord;
  337.  
  338.         void main() {
  339.            gl_Position = vec4(vtxPos, 1) * MVP; // to NDC
  340.            vec4 wPos = vec4(vtxPos, 1) * M;
  341.            wLight = wLightPos.xyz * wPos.w - wPos.xyz * wLightPos.w;
  342.            wView  = wEye * wPos.w - wPos.xyz;
  343.            wNormal = (Minv * vec4(vtxNorm, 0)).xyz;
  344.            texcoord = vtxUV;
  345.         }
  346.     )";
  347.  
  348.     // fragment shader in GLSL
  349.     const char* fragmentSource = R"(
  350.         #version 330
  351.         precision highp float;
  352.  
  353.         uniform sampler2D diffuseTexture;
  354.  
  355.         in  vec3 wNormal, wView, wLight;    // interpolated
  356.         in  vec2 texcoord;
  357.         out vec4 fragmentColor;             // output goes to frame buffer
  358.  
  359.         void main() {
  360.            vec3 N = normalize(wNormal), V = normalize(wView), L = normalize(wLight);
  361.            float y = (dot(N, L) > 0.5) ? 1 : 0.5;
  362.            if (abs(dot(N, V)) < 0.2) fragmentColor = vec4(0, 0, 0, 1);
  363.            else                      fragmentColor = vec4(y * texture(diffuseTexture, texcoord).rgb, 1);
  364.         }
  365.     )";
  366. public:
  367.     NPRShader() { create(vertexSource, fragmentSource, "fragmentColor"); }
  368.  
  369.     void Bind(RenderState state) {
  370.         Use();      // make this program run
  371.         setUniform(state.MVP, "MVP");
  372.         setUniform(state.M, "M");
  373.         setUniform(state.Minv, "Minv");
  374.         setUniform(state.wEye, "wEye");
  375.         setUniform(*state.texture, std::string("diffuseTexture"));
  376.         setUniform(state.lights[0].wLightPos, "wLightPos");
  377.     }
  378. };
  379.  
  380. //---------------------------
  381. struct VertexData {
  382.     //---------------------------
  383.     vec3 position, normal;
  384.     vec2 texcoord;
  385. };
  386.  
  387. //---------------------------
  388. class Geometry {
  389.     //---------------------------
  390. protected:
  391.     unsigned int vao, vbo;        // vertex array object
  392. public:
  393.     Geometry() {
  394.         glGenVertexArrays(1, &vao);
  395.         glBindVertexArray(vao);
  396.         glGenBuffers(1, &vbo); // Generate 1 vertex buffer object
  397.         glBindBuffer(GL_ARRAY_BUFFER, vbo);
  398.     }
  399.     virtual void Draw() = 0;
  400.     ~Geometry() {
  401.         glDeleteBuffers(1, &vbo);
  402.         glDeleteVertexArrays(1, &vao);
  403.     }
  404. };
  405.  
  406. //---------------------------
  407. class ParamSurface : public Geometry {
  408.     //---------------------------
  409.     unsigned int nVtxPerStrip, nStrips;
  410. public:
  411.     ParamSurface() { nVtxPerStrip = nStrips = 0; }
  412.  
  413.     virtual VertexData GenVertexData(float u, float v) = 0;
  414.  
  415.     void create(int N = tessellationLevel, int M = tessellationLevel) {
  416.         nVtxPerStrip = (M + 1) * 2;
  417.         nStrips = N;
  418.         std::vector<VertexData> vtxData;    // vertices on the CPU
  419.         for (int i = 0; i < N; i++) {
  420.             for (int j = 0; j <= M; j++) {
  421.                 vtxData.push_back(GenVertexData((float)j / M, (float)i / N));
  422.                 vtxData.push_back(GenVertexData((float)j / M, (float)(i + 1) / N));
  423.             }
  424.         }
  425.         glBufferData(GL_ARRAY_BUFFER, nVtxPerStrip * nStrips * sizeof(VertexData), &vtxData[0], GL_STATIC_DRAW);
  426.         // Enable the vertex attribute arrays
  427.         glEnableVertexAttribArray(0);  // attribute array 0 = POSITION
  428.         glEnableVertexAttribArray(1);  // attribute array 1 = NORMAL
  429.         glEnableVertexAttribArray(2);  // attribute array 2 = TEXCOORD0
  430.         // attribute array, components/attribute, component type, normalize?, stride, offset
  431.         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position));
  432.         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, normal));
  433.         glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, texcoord));
  434.     }
  435.  
  436.     void Draw() {
  437.         glBindVertexArray(vao);
  438.         for (unsigned int i = 0; i < nStrips; i++) glDrawArrays(GL_TRIANGLE_STRIP, i * nVtxPerStrip, nVtxPerStrip);
  439.     }
  440. };
  441.  
  442. //---------------------------
  443. struct Clifford {
  444.     //---------------------------
  445.     float f, d;
  446.     Clifford(float f0 = 0, float d0 = 0) { f = f0, d = d0; }
  447.     Clifford operator+(Clifford r) { return Clifford(f + r.f, d + r.d); }
  448.     Clifford operator-(Clifford r) { return Clifford(f - r.f, d - r.d); }
  449.     Clifford operator*(Clifford r) { return Clifford(f * r.f, f * r.d + d * r.f); }
  450.     Clifford operator/(Clifford r) {
  451.         float l = r.f * r.f;
  452.         return (*this) * Clifford(r.f / l, -r.d / l);
  453.     }
  454. };
  455.  
  456. Clifford T(float t) { return Clifford(t, 1); }
  457. Clifford Sin(Clifford g) { return Clifford(sin(g.f), cos(g.f) * g.d); }
  458. Clifford Cos(Clifford g) { return Clifford(cos(g.f), -sin(g.f) * g.d); }
  459. Clifford Tan(Clifford g) { return Sin(g) / Cos(g); }
  460. Clifford Log(Clifford g) { return Clifford(logf(g.f), 1 / g.f * g.d); }
  461. Clifford Exp(Clifford g) { return Clifford(expf(g.f), expf(g.f) * g.d); }
  462. Clifford Pow(Clifford g, float n) { return Clifford(powf(g.f, n), n * powf(g.f, n - 1) * g.d); }
  463.  
  464. //---------------------------
  465. class Sphere : public ParamSurface {
  466.     //---------------------------
  467. public:
  468.     Sphere() { create(); }
  469.  
  470.     VertexData GenVertexData(float u, float v) {
  471.         VertexData vd;
  472.         vd.position = vd.normal = vec3(cosf(u * 2.0f * (float)M_PI) * sinf(v * (float)M_PI),
  473.             sinf(u * 2.0f * (float)M_PI) * sinf(v * (float)M_PI),
  474.             cosf(v * (float)M_PI));
  475.         vd.texcoord = vec2(u, v);
  476.         return vd;
  477.     }
  478. };
  479.  
  480. //---------------------------
  481. class Torus : public ParamSurface {
  482.     //---------------------------
  483.     const float R = 1, r = 0.5;
  484.  
  485.     vec3 Point(float u, float v, float rr) {
  486.         float ur = u * 2.0f * (float)M_PI, vr = v * 2.0f * (float)M_PI;
  487.         float l = R + rr * cosf(ur);
  488.         return vec3(l * cosf(vr), l * sinf(vr), rr * sinf(ur));
  489.     }
  490. public:
  491.     Torus() { create(); }
  492.  
  493.     VertexData GenVertexData(float u, float v) {
  494.         VertexData vd;
  495.         vd.position = Point(u, v, r);
  496.         vd.normal = (vd.position - Point(u, v, 0)) * (1.0f / r);
  497.         vd.texcoord = vec2(u, v);
  498.         return vd;
  499.     }
  500.     vec3 point(float u, float v) {
  501.         return Point(u, v, r);
  502.     }
  503. };
  504.  
  505. //---------------------------
  506. class Mobius : public ParamSurface {
  507.     //---------------------------
  508.     float R, w;
  509. public:
  510.     Mobius() { R = 1; w = 0.5; create(); }
  511.  
  512.     VertexData GenVertexData(float u, float v) {
  513.         VertexData vd;
  514.         Clifford U(u * (float)M_PI, 1), V((v - 0.5f) * w, 0);
  515.         Clifford x = (Cos(U) * V + R) * Cos(U * 2);
  516.         Clifford y = (Cos(U) * V + R) * Sin(U * 2);
  517.         Clifford z = Sin(U) * V;
  518.         vd.position = vec3(x.f, y.f, z.f);
  519.         vec3 drdU(x.d, y.d, z.d);
  520.         vec3 drdV(cos(U.f) * cosf(2 * U.f), cosf(U.f) * sin(2 * U.f), sinf(U.f));
  521.         vd.normal = cross(drdU, drdV);
  522.         vd.texcoord = vec2(u, v);
  523.         return vd;
  524.     }
  525. };
  526.  
  527. //---------------------------
  528. class Dini : public ParamSurface {
  529.     //---------------------------
  530.     Clifford a = 1.0f, b = 0.15f;
  531. public:
  532.     Dini() { create(); }
  533.  
  534.     VertexData GenVertexData(float u, float v) {
  535.         VertexData vd;
  536.         Clifford U(u * 4 * M_PI, 1), V(0.01f + (1 - 0.01f) * v, 0);
  537.         Clifford X = a * Cos(U) * Sin(V);
  538.         Clifford Y = a * Sin(U) * Sin(V);
  539.         Clifford Z = a * (Cos(V) + Log(Tan(V / 2))) + b * U + 3;
  540.         vd.position = vec3(X.f, Y.f, Z.f);
  541.         vec3 drdU = vec3(X.d, Y.d, Z.d);
  542.  
  543.         U.d = 0, V.d = 1;
  544.         X = a * Cos(U) * Sin(V);
  545.         Y = a * Sin(U) * Sin(V);
  546.         Z = a * (Cos(V) + Log(Tan(V) / 2)) + b * U + 10;
  547.         vec3 drdV = vec3(X.d, Y.d, Z.d);
  548.  
  549.         vd.normal = cross(drdU, drdV);
  550.         vd.texcoord = vec2(u, v);
  551.         return vd;
  552.     }
  553. };
  554.  
  555.  
  556. //---------------------------
  557. class BezierSurface : public ParamSurface {
  558.     //---------------------------
  559.     // Bezier using Bernstein polynomials
  560.     static const int nControlPoints = 7;
  561.     vec3 wCtrlPoints[nControlPoints][nControlPoints] = {
  562.         vec3(-3, -3, 0), vec3(-3, -2, 0), vec3(-3, -1, 0), vec3(-3, 0, 0),vec3(-3, 1, 2), vec3(-3, 2, 0), vec3(-3, 3, 0),
  563.         vec3(-2, -3, 1), vec3(-2, -2, 4), vec3(-2, -1, 2), vec3(-2, 0, 0),vec3(-2, 1, 4), vec3(-2, 2, 0), vec3(-2, 3, 0),
  564.         vec3(-1, -3, 2), vec3(-1, -2, 6), vec3(-1, -1, 5), vec3(-1, 0, 3),vec3(-1, 1, 1), vec3(-1, 2, 1), vec3(-1, 3, 0),
  565.         vec3( 0, -3, 2), vec3( 0, -2, 3), vec3( 0, -1, 2), vec3( 0, 0, 0),vec3( 0, 1, 0), vec3( 0, 2, 3), vec3( 0, 3, 0),
  566.         vec3( 1, -3, 0), vec3( 1, -2, 0), vec3( 1, -1, 0), vec3( 1, 0, 0),vec3( 1, 1, 2), vec3( 1, 2, 5), vec3( 1, 3, 3),
  567.         vec3( 2, -3, 0), vec3( 2, -2, 0), vec3( 2, -1, 0), vec3( 2, 0, 0),vec3( 2, 1, 0), vec3( 2, 2, 1), vec3( 2, 3, 0),
  568.         vec3( 3, -3, 0), vec3( 3, -2, 0), vec3( 3, -1, 0), vec3( 3, 0, 0),vec3( 3, 1, 0), vec3( 3, 2, 0), vec3( 3, 3, 0),
  569.     };
  570.  
  571.  
  572.     float B(int i, float t) {
  573.         int n = nControlPoints - 1; // n deg polynomial = n+1 pts!
  574.         float choose = 1;
  575.         for (int j = 1; j <= i; j++) choose *= (float)(n - j + 1) / j;
  576.         return choose * pow(t, i) * pow(1 - t, n - i);
  577.     }
  578.  
  579.     float Bd(int i, float t) { // derivative of the Bernstein polynomial
  580.         int n = nControlPoints - 1; // n deg polynomial = n+1 pts!
  581.         float choose = 1;
  582.         for (int j = 1; j <= i; j++) choose *= (float)(n - j + 1) / j;
  583.         if (i == 0)      return -choose * n * pow(1 - t, n - 1);
  584.         else if (i == n) return choose * n * pow(t, n - 1);
  585.         else             return choose * (i * pow(t, i - 1) * pow(1 - t, n - i) - pow(t, i) * (n - i) * pow(1 - t, n - i - 1));
  586.     }
  587. public:
  588.     BezierSurface() { create(); }
  589.  
  590.     VertexData GenVertexData(float u, float v) {
  591.         VertexData vd;
  592.         vd.position = vec3(0, 0, 0);
  593.         vec3 du(0, 0, 0), dv(0, 0, 0);
  594.         for (unsigned int i = 0; i < nControlPoints; i++) {
  595.             for (unsigned int j = 0; j < nControlPoints; j++) {
  596.                 vd.position = vd.position + wCtrlPoints[i][j] * B(i, u) * B(j, v);
  597.                 du = du + wCtrlPoints[i][j] * Bd(i, u) * B(j, v);
  598.                 dv = dv + wCtrlPoints[i][j] * B(i, u) * Bd(j, v);
  599.             }
  600.         }
  601.         vd.normal = cross(du, dv);
  602.         return vd;
  603.     }
  604. };
  605.  
  606. //---------------------------
  607. struct Object {
  608.     //---------------------------
  609.     Shader* shader;
  610.     Material* material;
  611.     Texture* texture;
  612.     Geometry* geometry;
  613.     vec3 scale, translation, rotationAxis;
  614.     float rotationAngle;
  615. public:
  616.     Object(Shader* _shader, Material* _material, Texture* _texture, Geometry* _geometry) :
  617.         scale(vec3(1, 1, 1)), translation(vec3(0, 0, 0)), rotationAxis(0, 0, 1), rotationAngle(0) {
  618.         shader = _shader;
  619.         texture = _texture;
  620.         material = _material;
  621.         geometry = _geometry;
  622.     }
  623.     virtual void SetModelingTransform(mat4& M, mat4& Minv) {
  624.         M = ScaleMatrix(scale) * RotationMatrix(rotationAngle, rotationAxis) * TranslateMatrix(translation);
  625.         Minv = TranslateMatrix(-translation) * RotationMatrix(-rotationAngle, rotationAxis) * ScaleMatrix(vec3(1 / scale.x, 1 / scale.y, 1 / scale.z));
  626.     }
  627.  
  628.     void Draw(RenderState state) {
  629.         mat4 M, Minv;
  630.         SetModelingTransform(M, Minv);
  631.         state.M = M;
  632.         state.Minv = Minv;
  633.         state.MVP = state.M * state.V * state.P;
  634.         state.material = material;
  635.         state.texture = texture;
  636.         shader->Bind(state);
  637.         geometry->Draw();
  638.     }
  639.  
  640.     virtual void Animate(float tstart, float tend) { rotationAngle = 0.8f * tend; }
  641. };
  642.  
  643. //---------------------------
  644. class Scene {
  645.     //---------------------------
  646.     std::vector<Object*> objects;
  647.     Camera camera; // 3D camera
  648.     std::vector<Light> lights;
  649. public:
  650.     void Build() {
  651.         // Shaders
  652.         Shader* phongShader = new PhongShader();
  653.         Shader* gouraudShader = new GouraudShader();
  654.         Shader* nprShader = new NPRShader();
  655.  
  656.         // Materials
  657.         Material* material0 = new Material;
  658.         material0->kd = vec3(0.6f, 0.4f, 0.2f);
  659.         material0->ks = vec3(4, 4, 4);
  660.         material0->ka = vec3(0.1f, 0.1f, 0.1f);
  661.         material0->shininess = 100;
  662.  
  663.         Material* material1 = new Material;
  664.         material1->kd = vec3(0.8f, 0.6f, 0.4f);
  665.         material1->ks = vec3(0.3f, 0.3f, 0.3f);
  666.         material1->ka = vec3(0.2f, 0.2f, 0.2f);
  667.         material1->shininess = 30;
  668.  
  669.         Material* material2 = new Material;
  670.         material1->kd = vec3(0.8f, 0.6f, 0.4f);
  671.         material1->ks = vec3(0.3f, 0.3f, 0.3f);
  672.         material1->ka = vec3(0.2f, 0.2f, 0.2f);
  673.         material1->shininess = 10;
  674.  
  675.         // Textures
  676.         Texture* texture4x8 = new CheckerBoardTexture(4, 8);
  677.         Texture* texture15x20 = new CheckerBoardTexture(15, 20);
  678.         Texture* texture6x6 = new CheckerBoardTexture(6, 6);
  679.  
  680.         // Geometries
  681.         Geometry* sphere = new Sphere();
  682.         Geometry* torus = new Torus();
  683.         Geometry* mobius = new Mobius();
  684.         Geometry* bezierSurf = new BezierSurface();
  685.  
  686.         // Create objects by setting up their vertex data on the GPU
  687.         Object* surfaceObject = new Object(phongShader, material2, texture6x6, bezierSurf);
  688.         objects.push_back(surfaceObject);
  689.  
  690.         /*
  691.         Object* sphereObject1 = new Object(phongShader, material0, texture15x20, sphere);
  692.         sphereObject1->translation = vec3(-3, 3, 0);
  693.         sphereObject1->rotationAxis = vec3(0, 1, 1);
  694.         sphereObject1->scale = vec3(0.5f, 1.2f, 0.5f);
  695.         objects.push_back(sphereObject1);
  696.  
  697.         Object* torusObject1 = new Object(phongShader, material0, texture4x8, torus);
  698.         torusObject1->translation = vec3(0, 3, 0);
  699.         torusObject1->rotationAxis = vec3(1, 1, -1);
  700.         torusObject1->scale = vec3(0.7f, 0.7f, 0.7f);
  701.         objects.push_back(torusObject1);
  702.  
  703.         Object* mobiusObject1 = new Object(phongShader, material0, texture4x8, mobius);
  704.         mobiusObject1->translation = vec3(3, 3, 0);
  705.         mobiusObject1->rotationAxis = vec3(1, 0, 0);
  706.         mobiusObject1->scale = vec3(0.7f, 0.7f, 0.7f);
  707.         objects.push_back(mobiusObject1);
  708.  
  709.         Object* sphereObject2 = new Object(*sphereObject1);
  710.         sphereObject2->translation = vec3(-3, -3, 0);
  711.         sphereObject2->shader = nprShader;
  712.         objects.push_back(sphereObject2);
  713.  
  714.         Object* torusObject2 = new Object(*torusObject1);
  715.         torusObject2->translation = vec3(0, -3, 0);
  716.         torusObject2->shader = nprShader;
  717.         objects.push_back(torusObject2);
  718.  
  719.         Object* mobiusObject2 = new Object(*mobiusObject1);
  720.         mobiusObject2->translation = vec3(3, -3, 0);
  721.         mobiusObject2->shader = nprShader;
  722.         objects.push_back(mobiusObject2);
  723.  
  724.         Object* sphereObject3 = new Object(*sphereObject1);
  725.         sphereObject3->translation = vec3(-3, 0, 0);
  726.         sphereObject3->shader = gouraudShader;
  727.         objects.push_back(sphereObject3);
  728.  
  729.         Object* torusObject3 = new Object(*torusObject1);
  730.         torusObject3->translation = vec3(0, 0, 0);
  731.         torusObject3->shader = gouraudShader;
  732.         objects.push_back(torusObject3);
  733.  
  734.         Object* mobiusObject3 = new Object(*mobiusObject1);
  735.         mobiusObject3->translation = vec3(3, 0, 0);
  736.         mobiusObject3->shader = gouraudShader;
  737.         objects.push_back(mobiusObject3);
  738.         */
  739.  
  740.         // Camera
  741.         camera.wEye = vec3(0, 0, 20);
  742.         camera.wLookat = vec3(0, 0, 0);
  743.         camera.wVup = vec3(0, 1, 0);
  744.  
  745.         // Lights
  746.         lights.resize(3);
  747.         lights[0].wLightPos = vec4(5, 5, 4, 0); // ideal point -> directional light source
  748.         lights[0].La = vec3(0.1f, 0.1f, 1);
  749.         lights[0].Le = vec3(3, 0, 0);
  750.  
  751.         lights[1].wLightPos = vec4(5, 10, 20, 0);   // ideal point -> directional light source
  752.         lights[1].La = vec3(0.2f, 0.2f, 0.2f);
  753.         lights[1].Le = vec3(0, 3, 0);
  754.  
  755.         lights[2].wLightPos = vec4(-5, 5, 5, 0);    // ideal point -> directional light source
  756.         lights[2].La = vec3(0.1f, 0.1f, 0.1f);
  757.         lights[2].Le = vec3(0, 0, 3);
  758.     }
  759.  
  760.     void Render() {
  761.         RenderState state;
  762.         state.wEye = camera.wEye;
  763.         state.V = camera.V();
  764.         state.P = camera.P();
  765.         state.lights = lights;
  766.         for (Object* obj : objects) obj->Draw(state);
  767.     }
  768.  
  769.     void Animate(float tstart, float tend) {
  770.         camera.Animate(tend);
  771.         for (unsigned int i = 0; i < lights.size(); i++) { lights[i].Animate(tend); }
  772.         for (Object* obj : objects) obj->Animate(tstart, tend);
  773.     }
  774. };
  775.  
  776. Scene scene;
  777.  
  778. // Initialization, create an OpenGL context
  779. void onInitialization() {
  780.     glViewport(0, 0, windowWidth, windowHeight);
  781.     glEnable(GL_DEPTH_TEST);
  782.     glDisable(GL_CULL_FACE);
  783.     scene.Build();
  784. }
  785.  
  786. // Window has become invalid: Redraw
  787. void onDisplay() {
  788.     glClearColor(0.5f, 0.5f, 0.8f, 1.0f);                           // background color
  789.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the screen
  790.     scene.Render();
  791.     glutSwapBuffers();                                  // exchange the two buffers
  792. }
  793.  
  794. // Key of ASCII code pressed
  795. void onKeyboard(unsigned char key, int pX, int pY) { }
  796.  
  797. // Key of ASCII code released
  798. void onKeyboardUp(unsigned char key, int pX, int pY) { }
  799.  
  800. // Mouse click event
  801. void onMouse(int button, int state, int pX, int pY) { }
  802.  
  803. // Move mouse with key pressed
  804. void onMouseMotion(int pX, int pY) {
  805. }
  806.  
  807. // Idle event indicating that some time elapsed: do animation here
  808. void onIdle() {
  809.     static float tend = 0;
  810.     const float dt = 0.1f; // dt is ”infinitesimal”
  811.     float tstart = tend;
  812.     tend = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
  813.  
  814.     for (float t = tstart; t < tend; t += dt) {
  815.         float Dt = fmin(dt, tend - t);
  816.         //scene.Animate(t, t + Dt);
  817.     }
  818.     glutPostRedisplay();
  819. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement