Create normals and actually use texture

This commit is contained in:
hodasemi 2019-06-01 14:35:43 +02:00
parent 71c1b73ec3
commit 9737818f81
2 changed files with 76 additions and 29 deletions

View file

@ -1,12 +1,12 @@
// //
// This source code is property of the Computer Graphics and Visualization // This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute in modified or unmodified form! // chair of the TU Dresden. Do not distribute in modified or unmodified form!
// Copyright (C) 2016 CGV TU Dresden - All Rights Reserved // Copyright (C) 2016 CGV TU Dresden - All Rights Reserved
// //
/************************************************************************* /*************************************************************************
Terrain. Terrain.
This class represents a textured and shaded terrain. Both, the texture This class represents a textured and shaded terrain. Both, the texture
and the height map is read from a bmp file (in the constructor). and the height map is read from a bmp file (in the constructor).
The height map is mapped to a regular grid consisting of triangle strips. The height map is mapped to a regular grid consisting of triangle strips.
During rendering the normals needed for lighting are calculated. During rendering the normals needed for lighting are calculated.
There are some additional rendering modes: There are some additional rendering modes:
@ -18,7 +18,7 @@ The rendering is done in the "render" method which sets the projection
and view via "setup_projection" and the light via "setup_light". and view via "setup_projection" and the light via "setup_light".
Depending on the settings (that can be changed using "set_show_solid", Depending on the settings (that can be changed using "set_show_solid",
"set_show_wireframe" and "set_show_levels") different passes are rendered "set_show_wireframe" and "set_show_levels") different passes are rendered
using the appropriate rendering method ("render_solid_terrain", using the appropriate rendering method ("render_solid_terrain",
"render_wireframe_terrain", "render_level_lines"). They call the "render_wireframe_terrain", "render_level_lines"). They call the
"render_terrain" method. "render_terrain" method.
*************************************************************************/ *************************************************************************/
@ -92,7 +92,10 @@ private:
// Create height lines for the level "level" // Create height lines for the level "level"
void create_level_line(int level); void create_level_line(int level);
void push_point(int x, int y);
vec3d create_point(int x, int y);
vec2d texture_coord(int x, int y);
// Load the height map from the file "filename" // Load the height map from the file "filename"
bool load_heightmap(const char *filename); bool load_heightmap(const char *filename);
// Return the width of the height map // Return the width of the height map

View file

@ -1,6 +1,6 @@
// //
// This source code is property of the Computer Graphics and Visualization // This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute in modified or unmodified form! // chair of the TU Dresden. Do not distribute in modified or unmodified form!
// Copyright (C) 2016 CGV TU Dresden - All Rights Reserved // Copyright (C) 2016 CGV TU Dresden - All Rights Reserved
// //
#include "terrain.h" #include "terrain.h"
@ -112,8 +112,9 @@ void terrain::render_solid_terrain()
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE0, texture_handle);
// Set the material color to white // Set the material color to white
glColor3d(1, 1, 1); glColor3d(1, 1, 1);
@ -123,7 +124,7 @@ void terrain::render_solid_terrain()
// Disable texture mapping // Disable texture mapping
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
// Disable support for depth buffer offsets // Disable support for depth buffer offsets
glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_POLYGON_OFFSET_FILL);
// Disable lighting // Disable lighting
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
} }
@ -141,13 +142,18 @@ void terrain::render_wireframe_terrain()
// Set the color to black // Set the color to black
glColor3d(0, 0, 0); glColor3d(0, 0, 0);
// Render the terrain // Render the terrain
render_terrain(); render_terrain();
// Set the draw mode to fill polygons // Set the draw mode to fill polygons
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} }
void terrain::push_point(int x, int y)
{
set_normal(x, y);
glTexCoord2dv(texture_coord(x, y));
glVertex3dv(create_point(x, y));
}
// Render the terrain // Render the terrain
void terrain::render_terrain() void terrain::render_terrain()
@ -175,7 +181,7 @@ void terrain::render_terrain()
and translated to use the values of the variables "x" and "y" and translated to use the values of the variables "x" and "y"
defined below directly as coordinates. The initial height of defined below directly as coordinates. The initial height of
the grid shall be 0. the grid shall be 0.
Aufgabe 2.2.1. Vervollstaendigen Sie den nachfolgenden Quelltext um die Aufgabe 2.2.1. Vervollstaendigen Sie den nachfolgenden Quelltext um die
Erstellung eines regelmaessigen Gitters das sich ueber die Erstellung eines regelmaessigen Gitters das sich ueber die
X-Z-Ebene erstreckt. Erstellen Sie dieses Gitter, indem Sie X-Z-Ebene erstreckt. Erstellen Sie dieses Gitter, indem Sie
zeilenweise Dreiecksstreifen definieren. Das Koordinatensystem zeilenweise Dreiecksstreifen definieren. Das Koordinatensystem
@ -184,23 +190,23 @@ void terrain::render_terrain()
als Koordinaten einsetzen koennen. Das Gitter soll zunaechst als Koordinaten einsetzen koennen. Das Gitter soll zunaechst
eine Hoehe von 0 besitzen. eine Hoehe von 0 besitzen.
Task 2.2.2. Now elevate the height of the vertices to create the grid terrain Task 2.2.2. Now elevate the height of the vertices to create the grid terrain
that corresponds to the height map. Use "get_heightmap_value(x, y)". that corresponds to the height map. Use "get_heightmap_value(x, y)".
Aufgabe 2.2.2. Heben Sie jetzt die Vertices an um ein Drahtgitterterrain zu erstellen, Aufgabe 2.2.2. Heben Sie jetzt die Vertices an um ein Drahtgitterterrain zu erstellen,
das zur Hoehenkarte korrespondiert. Nutzen Sie die Methode das zur Hoehenkarte korrespondiert. Nutzen Sie die Methode
"get_heightmap_value(x, y)". "get_heightmap_value(x, y)".
Task 2.2.3. Make sure to call "set_normal" for every vertex and continue this Task 2.2.3. Make sure to call "set_normal" for every vertex and continue this
task in "set_normal". task in "set_normal".
Aufgabe 2.2.3. Stellen Sie sicher, dass Sie "set_normal" f<EFBFBD>r jeden Vertex aufrufen Aufgabe 2.2.3. Stellen Sie sicher, dass Sie "set_normal" f<EFBFBD>r jeden Vertex aufrufen
und fahren Sie in "set_normal" mit der Aufgabe fort. und fahren Sie in "set_normal" mit der Aufgabe fort.
Task 2.2.4. Activate texture mapping and bind the texture in the method Task 2.2.4. Activate texture mapping and bind the texture in the method
"render_solid_terrain". Provide 2D texture coordinates per vertex in "render_solid_terrain". Provide 2D texture coordinates per vertex in
this method using "glTexCoord2d". this method using "glTexCoord2d".
Aufgabe 2.2.4. Aktivieren Sie Texturmapping und binden Sie eine Textur in der Aufgabe 2.2.4. Aktivieren Sie Texturmapping und binden Sie eine Textur in der
Methode "render_solid_terrain". Spezifizieren Sie in dieser Methode pro Methode "render_solid_terrain". Spezifizieren Sie in dieser Methode pro
Vertex eine Texturkoordinate mittels der Methode "glTexCoord2d". Vertex eine Texturkoordinate mittels der Methode "glTexCoord2d".
@ -214,8 +220,8 @@ void terrain::render_terrain()
// Draw one strip // Draw one strip
for (int x = 0; x < map_width; x++) { for (int x = 0; x < map_width; x++) {
glVertex3f(static_cast<float>(x), get_heightmap_value(x, y), static_cast<float>(y)); push_point(x, y);
glVertex3f(static_cast<float>(x), get_heightmap_value(x, y + 1), static_cast<float>(y) + 1.0f); push_point(x, y + 1);
} }
glEnd(); glEnd();
@ -224,8 +230,30 @@ void terrain::render_terrain()
glPopMatrix(); glPopMatrix();
} }
vec2d terrain::texture_coord(int x, int y)
{
return vec2d(
static_cast<double>(x) / static_cast<double>(get_heightmap_width()),
static_cast<double>(y) / static_cast<double>(get_heightmap_height())
);
}
vec3d terrain::create_point(int x, int y)
{
return vec3d(
static_cast<double>(x),
static_cast<double>(get_heightmap_value(x, y)),
static_cast<double>(y)
);
}
vec3d calculate_normal(vec3d middle, vec3d p0, vec3d p1)
{
vec3d v0 = middle - p0;
vec3d v1 = p1 - middle;
return cross(v0, v1);
}
// Calculate and set the normal for height map entry (x,y) // Calculate and set the normal for height map entry (x,y)
void terrain::set_normal(int x, int y) void terrain::set_normal(int x, int y)
@ -235,8 +263,8 @@ void terrain::set_normal(int x, int y)
the height map value (x, y). You can either use forward differences, the height map value (x, y). You can either use forward differences,
backward differences or central differences. The latter will give backward differences or central differences. The latter will give
the best results. The calculation is done by first determining direction the best results. The calculation is done by first determining direction
vectors in X and Z and then using vector operations to get a vector that vectors in X and Z and then using vector operations to get a vector that
is perpendicular to both. You find some examples for vector operations in is perpendicular to both. You find some examples for vector operations in
this project below. Do not forget to pass the normal to OpenGL using this project below. Do not forget to pass the normal to OpenGL using
the command glNormal3d. the command glNormal3d.
@ -246,7 +274,7 @@ void terrain::set_normal(int x, int y)
Fuer die Berechnung werden zunaechst Richtungvektoren in X- und Z-Richtung Fuer die Berechnung werden zunaechst Richtungvektoren in X- und Z-Richtung
gebildet und anschliessend mittels Vektoroperationen ein zu beiden Vektoren gebildet und anschliessend mittels Vektoroperationen ein zu beiden Vektoren
senkrechter Vektor berechnet. Nachfolgend ein paar Beispiele fuer Vektor- senkrechter Vektor berechnet. Nachfolgend ein paar Beispiele fuer Vektor-
rechnungen in diesem Projekt. Vergessen Sie nicht die Normale nach der rechnungen in diesem Projekt. Vergessen Sie nicht die Normale nach der
Berechnung mittels glNormal3d an OpenGL zu senden. Berechnung mittels glNormal3d an OpenGL zu senden.
// Create a vector // Create a vector
@ -270,6 +298,22 @@ void terrain::set_normal(int x, int y)
double y = vec3.y(); double y = vec3.y();
double z = vec3.z(); double z = vec3.z();
*****************/ *****************/
vec3d middle = create_point(x, y);
vec3d right = create_point(x + 1, y);
vec3d top = create_point(x, y + 1);
vec3d left = create_point(x - 1, y);
vec3d bottom = create_point(x, y - 1);
vec3d normal0 = calculate_normal(middle, right, top);
vec3d normal1 = calculate_normal(middle, top, left);
vec3d normal2 = calculate_normal(middle, left, bottom);
vec3d normal3 = calculate_normal(middle, bottom, right);
vec3d final_normal = (normal0 + normal1 + normal2 + normal3) / 4;
glNormal3dv(final_normal);
} }
@ -312,8 +356,8 @@ void terrain::render_level_lines()
void terrain::create_level_line(int level) void terrain::create_level_line(int level)
{ {
/******** /********
Additional Task: Find iso lines with the "Marching Squares" algorithm for the Additional Task: Find iso lines with the "Marching Squares" algorithm for the
height value "level". Store the start and end points of the height value "level". Store the start and end points of the
found lines in the list "level_lines". found lines in the list "level_lines".
Zusatzaufgabe: Finden Sie Hoehenlinien mittels des "Marching Squares"-Algorithmus Zusatzaufgabe: Finden Sie Hoehenlinien mittels des "Marching Squares"-Algorithmus
fuer den Hoehenwert "level". Legen Sie die Start- und Endpunkte fuer den Hoehenwert "level". Legen Sie die Start- und Endpunkte
@ -350,7 +394,7 @@ void terrain::setup_light()
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color); glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
glLightf(GL_LIGHT0,GL_SPOT_EXPONENT, 10.0f); glLightf(GL_LIGHT0,GL_SPOT_EXPONENT, 10.0f);
glPopMatrix(); glPopMatrix();
@ -403,7 +447,7 @@ void terrain::set_show_solid(bool state)
void terrain::set_show_wireframe(bool state) void terrain::set_show_wireframe(bool state)
{ {
show_wireframe = state; show_wireframe = state;
// The current display list is outdated now // The current display list is outdated now
dl_valid = false; dl_valid = false;
} }
@ -442,7 +486,7 @@ bool terrain::load_heightmap(const char *filename)
} }
// All went well... // All went well...
return true; return true;
} }
@ -476,7 +520,7 @@ bool terrain::load_texture(const char *filename, GLuint *handle)
// Clamp the texture at the borders // Clamp the texture at the borders
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// Transfer the image data to the graphics card. // Transfer the image data to the graphics card.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, BMP_GetWidth(bitmap), BMP_GetHeight(bitmap), 0, GL_RGB, GL_UNSIGNED_BYTE, data); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, BMP_GetWidth(bitmap), BMP_GetHeight(bitmap), 0, GL_RGB, GL_UNSIGNED_BYTE, data);
// Not needed anymore // Not needed anymore
free(data); free(data);