quick backup of geosphere generation etc
authorEleni Maria Stea <estea@igalia.com>
Sat, 29 Jul 2017 15:22:20 +0000 (18:22 +0300)
committerEleni Maria Stea <estea@igalia.com>
Sat, 29 Jul 2017 15:22:20 +0000 (18:22 +0300)
src/mesh.h
src/meshgen.cc [new file with mode: 0644]
src/meshgen.h [new file with mode: 0644]
src/renderer.cc
src/renderer.h

index 57165ba..ed40f5d 100644 (file)
@@ -19,7 +19,6 @@ public:
        std::vector<uint16_t> indices;
        std::vector<Vec3> vertices;
        std::vector<Vec3> normals;
-       std::vector<Vec3> tangents;
        std::vector<Vec2> tex_coords;
 
        std::string name;
diff --git a/src/meshgen.cc b/src/meshgen.cc
new file mode 100644 (file)
index 0000000..fb4fae2
--- /dev/null
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include "meshgen.h"
+#include "mesh.h"
+
+// ------ geosphere ------
+#define PHI            1.618034
+
+/* icosahedron points */
+static Vec3 icosa_pt[] = {
+       Vec3(PHI, 1, 0),
+       Vec3(-PHI, 1, 0),
+       Vec3(PHI, -1, 0),
+       Vec3(-PHI, -1, 0),
+       Vec3(1, 0, PHI),
+       Vec3(1, 0, -PHI),
+       Vec3(-1, 0, PHI),
+       Vec3(-1, 0, -PHI),
+       Vec3(0, PHI, 1),
+       Vec3(0, -PHI, 1),
+       Vec3(0, PHI, -1),
+       Vec3(0, -PHI, -1)
+};
+/* indices that map to 20hedron pts to create the polygons */
+enum { P11, P12, P13, P14, P21, P22, P23, P24, P31, P32, P33, P34 };
+static int icosa_idx[] = {
+       P11, P31, P21,
+       P11, P22, P33,
+       P13, P21, P32,
+       P13, P34, P22,
+       P12, P23, P31,
+       P12, P33, P24,
+       P14, P32, P23,
+       P14, P24, P34,
+
+       P11, P33, P31,
+       P12, P31, P33,
+       P13, P32, P34,
+       P14, P34, P32,
+
+       P21, P13, P11,
+       P22, P11, P13,
+       P23, P12, P14,
+       P24, P14, P12,
+
+       P31, P23, P21,
+       P32, P21, P23,
+       P33, P22, P24,
+       P34, P24, P22
+};
+
+static void geosphere(std::vector<Vec3> *verts, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, int iter)
+{
+       if(!iter) {
+               verts->push_back(v1);
+               verts->push_back(v2);
+               verts->push_back(v3);
+               return;
+       }
+
+       /* we find mid points of the 3 vertices + normalize */
+
+       Vec3 v12 = normalize(v1 + v2);
+       Vec3 v23 = normalize(v2 + v3);
+       Vec3 v31 = normalize(v3 + v1);
+
+       /* create 4 triangles (recursive subdivision of the initial icosahedron */
+
+       geosphere(verts, v1, v12, v31, iter - 1);
+       geosphere(verts, v2, v23, v12, iter - 1);
+       geosphere(verts, v3, v31, v23, iter - 1);
+       geosphere(verts, v12, v23, v31, iter - 1);
+}
+
+void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi)
+{
+       /* the triangles of the icosahedron (fixed) */
+       int num_tri = (sizeof icosa_idx / sizeof *icosa_idx) / 3;
+
+       std::vector<Vec3> verts;
+       for(int i=0; i<num_tri; i++) {
+               Vec3 v[3];
+
+               /* we select the 3 vertices from the i-th triangle of the 20hedron */
+               for(int j=0; j<3; j++) {
+                       int vidx = icosa_idx[i * 3 + j];
+                       v[j] = normalize(icosa_pt[vidx]);
+               }
+
+               /* if hemi, we discard the triangles of the lower part of the 20hedron */
+               if(hemi && (v[0].y < 0.0 || v[1].y < 0.0 || v[2].y < 0.0)) {
+                       continue;
+               }
+
+               geosphere(&verts, v[0], v[1], v[2], subdiv);
+       }
+
+       /* now the verts contains all the sphere vertices */
+
+       int num_verts = (int)verts.size();
+
+       mesh->vertices.resize(num_verts);
+       mesh->normals.resize(num_verts);
+       mesh->tex_coords.resize(num_verts);
+
+       for(int i=0; i<num_verts; i++) {
+               mesh->vertices[i] = verts[i] * rad;
+               mesh->normals[i] = verts[i];
+
+               float theta = atan2(verts[i].z, verts[i].x);
+               float phi = acos(verts[i].y);
+
+               float u = 0.5 * theta / M_PI + 0.5;
+               float v = phi / M_PI;
+               mesh->tex_coords[i] = Vec2(u, v);
+       }
+
+       /* TODO: optimize indices by detecting the common vertices */
+       mesh->indices.resize(num_verts);
+       for(int i=0; i<num_verts; i++) {
+               mesh->indices[i] = i;
+       }
+       mesh->update_vertex_data();
+}
\ No newline at end of file
diff --git a/src/meshgen.h b/src/meshgen.h
new file mode 100644 (file)
index 0000000..bcd09ae
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef MESHGEN_H_
+#define MESHGEN_H_
+
+#include <gmath/gmath.h>
+
+class Mesh;
+
+/* generates geodesic sphere: if hemi is true we only gen the hemisphere */
+void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi = false);
+
+#endif // MESHGEN_H_
index 260c3cf..10dd766 100644 (file)
@@ -1,9 +1,12 @@
 #include <GL/glew.h>
+#include <gmath/gmath.h>
 
 #include "global.h"
+#include "gfxapi.h"
 
 #include "camera.h"
 #include "mesh.h"
+#include "meshgen.h"
 #include "object.h"
 #include "renderer.h"
 #include "scene.h"
 #include "shader_manager.h"
 #include "texture.h"
 
+/* skybox */
+
+static Mesh *skymesh; /* it will be used by many renderers => no destroy */
+static ShaderProgram *skyprog;
+static int viewproj_loc;
+
 Renderer::Renderer()
 {
        scene = 0;
@@ -31,10 +40,6 @@ bool Renderer::create()
                return false;
        }
 
-       if(!(sprog->link())) {
-               return false;
-       }
-
        /* getting material uniform locations: diffuse, specular, specular exponent (strength) */
 
        if((diff_loc = sprog->get_uniform_location("diffuse")) == -1) {
@@ -111,10 +116,35 @@ void Renderer::draw_object(Object *object) const
 
 void Renderer::set_sky_tex(Texture *stex)
 {
+       if(!skymesh) {
+               skymesh = gfx_create_mesh();
+               gen_geosphere(skymesh, 1, 0);
+       }
+       if(!skyprog) {
+               if(!(skyprog = sdr_man->create_shader_program("sky.v.glsl", "sky.f.glsl")))
+                       return;
+               if((viewproj_loc = skyprog->get_uniform_location("viewproj") == -1))
+                       return;
+       }
        skytex = stex;
 }
 
 void Renderer::set_diffuse_sky_tex(Texture *dstex)
 {
        dskytex = dstex;
+}
+
+void Renderer::draw_skybox()
+{
+       if(!skymesh || !skytex)
+               return;
+
+       skytex->bind();
+       skyprog->use();
+
+       Mat4 mviewproj;
+       mviewproj = camera->get_view_matrix().upper3x3() * mprojection;
+       skyprog->set_uniform_matrix(viewproj_loc, mviewproj);
+
+       skymesh->draw();
 }
\ No newline at end of file
index efbab80..07db322 100644 (file)
@@ -14,9 +14,12 @@ protected:
        int mmviewproj_loc;
        int mview_loc;
 
-       Texture *skytex, *dskytex;
        ShaderProgram *sprog;
+
+       Texture *skytex, *dskytex;
+
        virtual void draw_object(Object *object) const;
+       virtual void draw_skybox();
 
 public:
        Scene *scene;