|
Grado en Ingeniería Informática
Realidad Virtual
Curso 2023/2024
|
Objetivos
|
|
En esta práctica se describe la forma de añadir texturas a los
objetos dibujados. Una textura describe la imagen que se proyecta
sobre la superficie de los objetos. Para definir la forma de
proyectar la imagen hay que añadir a los vértices un nuevo atributo
que representa la posición del vértice sobre la imagen de textura.
Este atributo se conoce como "coordenadas de textura". El resultado final
de esta práctica es similar al
presentado en la práctica anterior, pero añadiendo las texturas a los
cuerpos representados.

|
|
La biblioteca FreeImage
|
|
OpenGL utiliza su propio formato de almacenamiento de imágenes y no
dispone de funciones que permitan leer ficheros de imágenes en los
formatos comunes (GIF, JPG, PNG, etc.). Para resolver este
problema es habitual utilizar alguna biblioteca auxiliar dedicada al
tratameinto de imágenes en distintos formatos. A lo largo de las
prácticas vamos a utilizar una de estas bibliotecas denominada
FreeImage.
Al igual que hemos hecho con las bibliotecas
glfw, glew y glm, la
biblioteca FreeImage se ha incluido en la distríbución del código de
la práctica en el directorio 'C:\ComputerGraphics\Tools'.
A lo largo de todas las prácticas hemos ido incluyendo la biblioteca
FreeImage en las propiedades de los proyectos, tanto en los
directorios de búsqueda como en las dependencias adicionales. En
esta práctica vamos a hacer uso por primera vez de esta bilbioteca.
Para utilizar sus funciones hay que incluir en el código el archivo de cabecera <FreeImage.h>.
Hay que tener en cuenta además que el fichero FreeImage.dll
debe copiarse
en el directorio de trabajo de la aplicación.
|
|
La clase CGMaterial
|
|
Las texturas se van a configurar como parte de la descripción del
material asociado a cada figura. Para ello se ha añadido un nuevo
campo a la clase CGMaterial, denominado textureId,
que almacenará la referencia a la textura incluida en el material.
Para almacenar una textura en la tarjeta gráfica se utilizará el
método InitTexture(), que puede leer la textura desde un
fichero externo o desde un recurso de la aplicación. Para poder utilizar la misma textura
en varios materiales, se ha añadido también los métodos
GetTexture() y SetTexture() que permiten editar la
referencia a la textura (textureId) sin necesidad de cargar
una nueva imagen. La cabecera de la clase CGMaterial queda así.
#pragma once
#include <glm/glm.hpp>
#include "CGShaderProgram.h"
class CGMaterial {
private:
glm::vec3 Ka; // Reflectividad ambiental (color ante la luz ambiental)
glm::vec3 Kd; // Reflectividad difusa (color ante la luz difusa)
glm::vec3 Ks; // Reflectividad especular (color ante la luz especular)
GLfloat Shininess; // Factor de brillo (comportamiento ante la luz especular)
GLuint textureId; // Identificador de la textura básica
public:
CGMaterial();
void SetAmbientReflect(GLfloat r, GLfloat g, GLfloat b);
void SetDifusseReflect(GLfloat r, GLfloat g, GLfloat b);
void SetSpecularReflect(GLfloat r, GLfloat g, GLfloat b);
void SetShininess(GLfloat f);
void SetUniforms(CGShaderProgram* program);
void SetTexture(GLuint id);
void InitTexture(const char* filename);
void InitTexture(int idr);
GLuint GetTexture();
};
|
El método InitTexture(const char* filename) se encarga de
leer el archivo de textura, almacenarlo en la tarjeta gráfica y
configurar el modo de aplicación de la textura. Este método utiliza
las funciones de FreeImage para determinar el formato de la imagen a
cargar (FreeImage_GetFileType), leer el fichero de imagen (FreeImage_Load)
y convertirlo a un formato compatible con OpenGL (FreeImage_ConvertTo32Bits).
Tambien utiliza funciones para obtener la anchura y altura de la
imagen (FreeImage_GetWidth, FreeImage_GetHeight) y
para eliminarla (FreeImage_Unload). El método InitTexture()
se encarga también de crear un objeto textura (glGenTextures), seleccionar la textura (glBindTexture),
copiar los datos de la imagen (glTexImage2D) y configurar
el proceso de aplicación de dicha textura (glTexParameteri).
El método InitTexture(int idr) es similar al anterior pero
en este caso carga el contenido de la textura desde un recurso de la
aplicación. Para ello en primer lugar almacena en memoria el
contenido del recurso de forma similar a la que se almacena el
contenido de los recursos de los shaders. A continuación se utilizan
las funciones de FreeImage para abrir como fichero el contenido
almacenado en memoria (FreeImage_OpenMemory), determinar el
formato de la imagen (FreeImage_GetFileTypeFromMemory) y
cargar su contenido en la estructura de datos utilizada en la
biblioteca (FreeImage_LoadFromMemory). A partir de ahí el
código es idéntico a la versión anterior.
El método Draw() debe modificarse para utilizar la textura.
Para eso hay que activarla como GL_TEXTURE0 (glActiveTexture),
seleccionarla (glBindTexture) y asignar el valor 0 a la
variable uniforme BaseTex que se utiliza en el
FragmentShader para acceder a la textura.
#include "CGMaterial.h"
#include <GL/glew.h>
#include <FreeImage.h>
//
// FUNCIÓN: CGMaterial::CGMaterial()
//
// PROPÓSITO: Construye un material con los valores por defecto
//
CGMaterial::CGMaterial()
{
Ka = glm::vec3(1.0f, 1.0f, 1.0f);
Kd = glm::vec3(1.0f, 1.0f, 1.0f);
Ks = glm::vec3(0.8f, 0.8f, 0.8f);
Shininess = 16.0f;
textureId = 0;
}
//
// FUNCIÓN: CGMaterial::SetAmbientReflect(GLfloat r, GLfloat g, GLfloat b)
//
// PROPÓSITO: Asigna la reflectividad ambiental (color ante la luz ambiental)
//
void CGMaterial::SetAmbientReflect(GLfloat r, GLfloat g, GLfloat b)
{
Ka = glm::vec3(r, g, b);
}
//
// FUNCIÓN: CGMaterial::SetDifusseReflect(GLfloat r, GLfloat g, GLfloat b)
//
// PROPÓSITO: Asigna la reflectividad difusa (color ante la luz difusa)
//
void CGMaterial::SetDifusseReflect(GLfloat r, GLfloat g, GLfloat b)
{
Kd = glm::vec3(r, g, b);
}
//
// FUNCIÓN: CGMaterial::SetSpecularReflect(GLfloat r, GLfloat g, GLfloat b)
//
// PROPÓSITO: Asigna la reflectividad especular (color ante la luz especular)
//
void CGMaterial::SetSpecularReflect(GLfloat r, GLfloat g, GLfloat b)
{
Ks = glm::vec3(r, g, b);
}
//
// FUNCIÓN: CGMaterial::SetShininess(GLfloat f)
//
// PROPÓSITO: Asigna el factor de brillo (comportamiento ante la luz especular)
//
void CGMaterial::SetShininess(GLfloat f)
{
Shininess = f;
}
//
// FUNCIÓN: CGMaterial::SetUniforms(CGShaderProgram* program)
//
// PROPÓSITO: Configura las propiedades de material en el programa gráfico
//
void CGMaterial::SetUniforms(CGShaderProgram* program)
{
program->SetUniformVec3("Material.Ka", Ka);
program->SetUniformVec3("Material.Kd", Kd);
program->SetUniformVec3("Material.Ks", Ks);
program->SetUniformF("Material.Shininess", Shininess);
program->SetUniformI("BaseTex", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
}
//
// FUNCIÓN: CGMaterial::SetTexture(GLuint id)
//
// PROPÓSITO: Asigna el identificador de la textura básica
//
void CGMaterial::SetTexture(GLuint id)
{
textureId = id;
}
//
// FUNCIÓN: CGMaterial::GetTexture()
//
// PROPÓSITO: Obtiene el identificador de la textura básica
//
GLuint CGMaterial::GetTexture()
{
return textureId;
}
//
// FUNCIÓN: void CGMAterial::InitTexture(const char* filename)
//
// PROPÓSITO: Carga una textura
//
void CGMaterial::InitTexture(const char* filename)
{
FREE_IMAGE_FORMAT format = FreeImage_GetFileType(filename, 0);
FIBITMAP* bitmap = FreeImage_Load(format, filename);
FIBITMAP* pImage = FreeImage_ConvertTo32Bits(bitmap);
int nWidth = FreeImage_GetWidth(pImage);
int nHeight = FreeImage_GetHeight(pImage);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight,
0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));
FreeImage_Unload(pImage);
}
//
// FUNCIÓN: void CGMAterial::InitTexture(int idr)
//
// PROPÓSITO: Carga una textura a partir de un recurso
//
void CGMaterial::InitTexture(int idr)
{
HRSRC handle = FindResource(NULL, MAKEINTRESOURCE(idr), L"IMAGE");
HGLOBAL hGlobal = LoadResource(NULL, handle);
LPCTSTR rsc_ptr = static_cast<LPCTSTR>(LockResource(hGlobal));
DWORD mem_size = SizeofResource(NULL, handle);
BYTE* mem_buffer = (BYTE*)malloc((mem_size) * sizeof(BYTE));
memcpy(mem_buffer, rsc_ptr, mem_size * sizeof(BYTE));
FreeResource(hGlobal);
FIMEMORY* hmem = FreeImage_OpenMemory(mem_buffer, mem_size * sizeof(BYTE));
FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
FIBITMAP* check = FreeImage_LoadFromMemory(fif, hmem, 0);
FIBITMAP* pImage = FreeImage_ConvertTo32Bits(check);
int nWidth = FreeImage_GetWidth(pImage);
int nHeight = FreeImage_GetHeight(pImage);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight,
0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));
FreeImage_Unload(pImage);
FreeImage_CloseMemory(hmem);
free(mem_buffer);
}
|
|
|
Texturas
|
|
Los ficheros de textura
que vamos a utilizar en esta práctica se llaman "stone.jpg",
"moon.jpg" y "wood.jpg" y se
deben encontrar en el directorio "textures". A
continuación se muestra el aspecto de estas texturas.
Para
cargar las texturas como recursos en VisualStudio se procede de la
misma forma que se indicó en la Práctica 2. Hay que abrir la
ventana de "Agregar recurso" y crear
un nuevo tipo de recurso pulsando sobre la opción "Personalizar".
En este caso crearemos un nuevo tipo de recurso
que llamaremos "IMAGE".
Una vez creado el recurso es posible editar sus propiedades utilizando la "Vista de recursos".
En la propiedad de nombre de fichero hay que introducir la ruta al
fichero de la textura. De esta forma creamos el recurso IDR_IMAGE1
con la textura "textures/stone.jpg", el recurso IDR_IMAGE2 con la
textura "textures/moon.jpg" y el recurso IDR_IMAGE3 con la textura
"textures/wood.jpg".
|
|
El programa gráfico
|
|
Para incorporar texturas en la generación de la imagen es necesario
añadir a los vértices un nuevo atributo que indica la posición de
cada vértice sobre la textura. Este atributo se conoce como
"coordenadas de textura" y está formado por dos componentes
definidas en un rango entre 0.0 y 1.0. La incorporación de estos
nuevos atributos suponen modificar el VertexShader de
manera que incluya una nueva entrada (VertexTexCoord) y una
nueva salida (TexCoord) de tipo vec2. Las
coordenadas de textura no dependen de la posición del observador así
que no es necesario transformarlas dentro del VertexShader.
Por tanto, el código del VertexShader se limita a copiar
las coordenadas de textura como variable de salida para que puedan
ser procesadas en el FragmentShader.
#version 400
layout(location = 0) in vec3 VertexPosition;
layout(location = 1) in vec3 VertexNormal;
layout(location = 2) in vec2 VertexTexCoord;
uniform mat4 MVP;
uniform mat4 ViewMatrix;
uniform mat4 ModelViewMatrix;
out vec3 Position;
out vec3 Normal;
out vec2 TexCoord;
void main()
{
vec4 n4 = ModelViewMatrix*vec4(VertexNormal, 0.0);
vec4 v4 = ModelViewMatrix*vec4(VertexPosition, 1.0);
Normal = vec3(n4);
Position = vec3(v4);
TexCoord = VertexTexCoord;
gl_Position = MVP * vec4(VertexPosition, 1.0);
}
|
Para incorporar la textura al cálculo del color de cada pixel es
necesario incluir en el FragmentShader tanto las
coordenadas de textura del pixel (TexCoord) como una nueva
variable uniforme que permita acceder a la imagen de textura (BaseTex).
Las texturas se tratan en GLSL como tipos de datos opacos
denominados sampler2D (para texturas 2D). En realidad, la
variable uniforme BaseTex contiene el identificador que
permite referenciar la textura activa. Por ejemplo, el valor 0
permite referenciar a la textura activa GL_TEXTURE0. Para acceder al
color correspondiente a una cierta coordenada de textura (lo que se
conoce como un texel) se utiliza la función predefinida
texture() que devuelve un vec4 que contiene el color del texel
en formato RGBA.
A continuación se muestra el contenido del FragmentShader
incorporando el modelo de iluminación de Phong junto al uso de
texturas. Para ello se ha modificado la función ads() para
incluir como parámetro el color de textura del pixel. El color de la
textura influye en el efecto de la luz ambiental y difusa, pero no
en el de la luz especular. La razón por la que se trata de forma
diferente la luz especular es que ésta es la que provoca un efecto
de brillo o de destello. Si un pixel tiene un color de textura
oscuro y multiplicamos este color por el efecto de la luz especular,
como mucho el color seguirá siendo oscuro. Al no incluir la textura
sobre el efecto especular se consigue mantener los efectos de
brillo.
#version 400
in vec3 Position;
in vec3 Normal;
in vec2 TexCoord;
uniform sampler2D BaseTex;
uniform mat4 ViewMatrix;
struct LightInfo {
vec3 Ldir;
vec3 La;
vec3 Ld;
vec3 Ls;
};
uniform LightInfo Light;
struct MaterialInfo{
vec3 Ka;
vec3 Kd;
vec3 Ks;
float Shininess;
};
uniform MaterialInfo Material;
out vec4 FragColor;
vec3 ads(vec3 TexColor) {
vec4 s4 = ViewMatrix*vec4(Light.Ldir, 0.0);
vec3 n = normalize(Normal);
vec3 v = normalize(-Position);
vec3 s = normalize(-vec3(s4));
vec3 r = reflect(-s, n);
float dRate = max(dot(s, n), 0.0);
float sRate = pow(max(dot(r, v), 0.0), Material.Shininess);
vec3 ambient = Light.La * Material.Ka;
vec3 difusse = Light.Ld * Material.Kd * dRate;
vec3 specular = Light.Ls * Material.Ks * sRate;
return (ambient + difusse)*TexColor + specular;
}
void main()
{
vec3 TexColor = vec3( texture(BaseTex,TexCoord) );
vec3 Color = ads(TexColor);
FragColor = vec4(Color,1.0);
}
|
|
|
La clase CGFigure
|
|
La clase CGFigure describe el comportamiento general de
cualquiera de las figuras geométricas que vamos a incluir en la
escena. Con respecto a la práctica anterior, la modificación
principal consiste en añadir un nuevo atributo al VAO asociado a la
figura. Este atributo contendrá las coordenadas de textura de cada
vértice y requiere su propio VBO para almacenar sus datos. Estos
datos se incluirán inicialmente en un campo denominado textures
(los valores de este array dependen de cada figura geométrica
concreta) cuyo contenido se almacenará en el VBO correspondiente al
ejecutar el método InitBuffers().
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
#include "CGMaterial.h"
#include "CGShaderProgram.h"
#define VERTEX_DATA 0
#define INDEX_DATA 1
#define NORMAL_DATA 2
#define TEXTURE_DATA 3
//
// CLASE: CGFigure
//
// DESCRIPCIÓN: Clase abstracta que representa un objeto descrito mediante
// VAO para su renderizado mediante shaders
//
class CGFigure {
protected:
GLushort* indexes; // Array of indexes
GLfloat* vertices; // Array of vertices
GLfloat* normals; // Array of normals
GLfloat* textures; // Array of texture coordinates
GLuint numFaces; // Number of faces
GLuint numVertices; // Number of vertices
GLuint VBO[4];
GLuint VAO;
glm::mat4 location; // Model matrix
CGMaterial* material;
public:
~CGFigure();
void InitBuffers();
void SetMaterial(CGMaterial* mat);
void ResetLocation();
void Translate(glm::vec3 t);
void Rotate(GLfloat angle, glm::vec3 axis);
void Draw(CGShaderProgram* program, glm::mat4 projection, glm::mat4 view);
};
#endif
|
Con respecto al código, los cambios en la clase
CGFigure consisten en incorporar el
nuevo atributo asociado a las coordenadas de textura en el método InitBuffers().
#include "CGFigure.h"
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
//
// FUNCIÓN: CGFigure::~CGFigure()
//
// PROPÓSITO: Destructor de la figura
//
CGFigure::~CGFigure()
{
if (vertices != NULL) delete[] vertices;
if (indexes != NULL) delete[] indexes;
if (normals != NULL) delete[] normals;
if (textures != NULL) delete[] textures;
// Delete vertex buffer objects
glDeleteBuffers(4, VBO);
glDeleteVertexArrays(1, &VAO);
}
//
// FUNCIÓN: CGFigure::InitBuffers()
//
// PROPÓSITO: Crea el VAO y los VBO y almacena todos los datos
// en la GPU.
//
void CGFigure::InitBuffers()
{
// Create the Vertex Array Object
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
// Create the Vertex Buffer Objects
glGenBuffers(4, VBO);
// Copy data to video memory
// Vertex data
int buffsize = sizeof(GLfloat) * numVertices * 3;
glBindBuffer(GL_ARRAY_BUFFER, VBO[VERTEX_DATA]);
glBufferData(GL_ARRAY_BUFFER, buffsize, vertices, GL_STATIC_DRAW);
// Normal data
glBindBuffer(GL_ARRAY_BUFFER, VBO[NORMAL_DATA]);
glBufferData(GL_ARRAY_BUFFER, buffsize, normals, GL_STATIC_DRAW);
// Texture coordinates
buffsize = sizeof(GLfloat) * numVertices * 2;
glBindBuffer(GL_ARRAY_BUFFER, VBO[TEXTURE_DATA]);
glBufferData(GL_ARRAY_BUFFER, buffsize, textures, GL_STATIC_DRAW);
// Indexes
buffsize = sizeof(GLushort) * numFaces * 3;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO[INDEX_DATA]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffsize, indexes, GL_STATIC_DRAW);
delete[] vertices;
delete[] indexes;
delete[] normals;
delete[] textures;
vertices = NULL;
indexes = NULL;
normals = NULL;
textures = NULL;
glEnableVertexAttribArray(0); // Vertex position
glBindBuffer(GL_ARRAY_BUFFER, VBO[VERTEX_DATA]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1); // Vertex normals
glBindBuffer(GL_ARRAY_BUFFER, VBO[NORMAL_DATA]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2); // Vertex textures
glBindBuffer(GL_ARRAY_BUFFER, VBO[TEXTURE_DATA]);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
//
// FUNCIÓN: CGFigure::SetMaterial(CGMaterial* m)
//
// PROPÓSITO: Asigna el material de la figura
//
void CGFigure::SetMaterial(CGMaterial* mat)
{
material = mat;
}
//
// FUNCIÓN: CGFigure::ResetLocation()
//
// PROPÓSITO: Asigna la posición inicial de la figura
//
void CGFigure::ResetLocation()
{
location = glm::mat4(1.0f);
}
//
// FUNCIÓN: CGFigure::Translate(glm::vec3 t)
//
// PROPÓSITO: Añade un desplazamiento a la matriz de posición de la figura
//
void CGFigure::Translate(glm::vec3 t)
{
location = glm::translate(location, t);
}
//
// FUNCIÓN: CGFigure::Rotate(GLfloat angle, glm::vec3 axis)
//
// PROPÓSITO: Añade una rotación a la matriz de posición de la figura
//
void CGFigure::Rotate(GLfloat angle, glm::vec3 axis)
{
location = glm::rotate(location, glm::radians(angle), axis);
}
//
// FUNCIÓN: CGFigure::Draw(CGShaderProgram * program, glm::mat4 projection,
// glm::mat4 view)
//
// PROPÓSITO: Dibuja la figura
//
void CGFigure::Draw(CGShaderProgram* program, glm::mat4 projection, glm::mat4 view)
{
glm::mat4 mvp = projection * view * location;
program->SetUniformMatrix4("MVP", mvp);
program->SetUniformMatrix4("ViewMatrix", view);
program->SetUniformMatrix4("ModelViewMatrix", view * location);
material->SetUniforms(program);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, numFaces * 3, GL_UNSIGNED_SHORT, NULL);
}
|
|
|
La clase CGScene
|
|
La escena a representar en el modelo
(descrita en la clase
CGScene) es muy parecida a la versión de la práctica anterior.
La única diferencia consiste en que se han definido materiales
diferentes para cada figura para que puedan dibujarse en diferentes colores
y que se han añadido las texturas a estos
materiales. La textura stone se va a utilizar en diferentes
materiales. Para no cargarla varias veces se ha
cargado una única vez en el material 'mat0' y se ha
utilizado el mismo identificador de textura (textureId) en
el resto de los materiales que la utilizan.
El fichero de cabecera de la clase incorpora ahora los nuevos
materiales.
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
#include "CGShaderProgram.h"
#include "CGLight.h"
#include "CGMaterial.h"
#include "CGFigure.h"
class CGScene {
public:
CGScene();
~CGScene();
void Draw(CGShaderProgram* program, glm::mat4 proj, glm::mat4 view);
private:
CGFigure* ground;
CGFigure* fig0;
CGFigure* fig1;
CGFigure* fig2;
CGFigure* fig3;
CGFigure* fig4;
CGFigure* fig5;
CGLight* light;
CGMaterial* matg;
CGMaterial* mat0;
CGMaterial* mat1;
CGMaterial* mat2;
CGMaterial* mat3;
CGMaterial* mat4;
CGMaterial* mat5;
};
|
El fichero de código queda así.
#include "CGScene.h"
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "CGShaderProgram.h"
#include "CGFigure.h"
#include "CGLight.h"
#include "CGMaterial.h"
#include "CGCube.h"
#include "CGCone.h"
#include "CGCylinder.h"
#include "CGSphere.h"
#include "CGTorus.h"
#include "CGIcosahedron.h"
#include "CGGround.h"
//
// FUNCIÓN: CGScene::CGScene()
//
// PROPÓSITO: Construye el objeto que representa la escena
//
CGScene::CGScene()
{
glm::vec3 Ldir = glm::vec3(1.0f, -0.8f, -1.0f);
Ldir = glm::normalize(Ldir);
light = new CGLight();
light->SetLightDirection(Ldir);
light->SetAmbientLight(glm::vec3(0.2f, 0.2f, 0.2f));
light->SetDifusseLight(glm::vec3(0.8f, 0.8f, 0.8f));
light->SetSpecularLight(glm::vec3(1.0f, 1.0f, 1.0f));
matg = new CGMaterial();
matg->SetAmbientReflect(1.0f, 1.0f, 1.0f);
matg->SetDifusseReflect(1.0f, 1.0f, 1.0f);
matg->SetSpecularReflect(0.8f, 0.8f, 0.8f);
matg->SetShininess(16.0f);
//matg->InitTexture("textures/wood.jpg");
matg->InitTexture(IDR_IMAGE2);
ground = new CGGround(50.0f, 50.0f);
ground->SetMaterial(matg);
mat0 = new CGMaterial();
mat0->SetAmbientReflect(1.0f, 0.0f, 1.0f);
mat0->SetDifusseReflect(1.0f, 0.0f, 1.0f);
mat0->SetSpecularReflect(0.8f, 0.8f, 0.8f);
mat0->SetShininess(16.0f);
//mat0->InitTexture("textures/stone.jpg");
mat0->InitTexture(IDR_IMAGE1);
GLuint textureId = mat0->GetTexture();
fig0 = new CGCone(5, 20, 5.0f, 5.0f);
fig0->SetMaterial(mat0);
fig0->Translate(glm::vec3(25.0f, 5.0f, 25.0f));
fig0->Rotate(-90.0f, glm::vec3(1.0f, 0.0f, 0.0f));
mat1 = new CGMaterial();
mat1->SetAmbientReflect(1.0f, 1.0f, 1.0f);
mat1->SetDifusseReflect(1.0f, 1.0f, 1.0f);
mat1->SetSpecularReflect(0.8f, 0.8f, 0.8f);
mat1->SetShininess(16.0f);
mat1->SetTexture(textureId);
fig1 = new CGCube(5.0f);
fig1->SetMaterial(mat1);
fig1->Translate(glm::vec3(-25.0f, 5.0f, 25.0f));
fig1->Rotate(-90.0f, glm::vec3(1.0f, 0.0f, 0.0f));
mat2 = new CGMaterial();
mat2->SetAmbientReflect(0.2f, 0.2f, 1.0f);
mat2->SetDifusseReflect(0.2f, 0.2f, 1.0f);
mat2->SetSpecularReflect(0.8f, 0.8f, 0.8f);
mat2->SetShininess(16.0f);
mat2->SetTexture(textureId);
fig2 = new CGCylinder(20, 20, 5.0f, 5.0f);
fig2->SetMaterial(mat2);
fig2->Translate(glm::vec3(25.0f, 5.0f, 0.0f));
fig2->Rotate(90.0f, glm::vec3(1.0f, 0.0f, 0.0f));
mat3 = new CGMaterial();
mat3->SetAmbientReflect(1.0f, 0.0f, 0.0f);
mat3->SetDifusseReflect(1.0f, 0.0f, 0.0f);
mat3->SetSpecularReflect(0.8f, 0.8f, 0.8f);
mat3->SetShininess(16.0f);
mat3->SetTexture(textureId);
fig3 = new CGTorus(20, 40, 3.0f, 5.0f);
fig3->SetMaterial(mat3);
fig3->Translate(glm::vec3(-25.0f, 8.0f, 0.0f));
mat4 = new CGMaterial();
mat4->SetAmbientReflect(1.0f, 1.0f, 0.0f);
mat4->SetDifusseReflect(1.0f, 1.0f, 0.0f);
mat4->SetSpecularReflect(0.8f, 0.8f, 0.8f);
mat4->SetShininess(16.0f);
//mat4->InitTexture("textures/moon.jpg");
mat4->InitTexture(IDR_IMAGE3);
fig4 = new CGSphere(20, 40, 8.0f);
fig4->SetMaterial(mat4);
fig4->Translate(glm::vec3(25.0f, 8.0f, -25.0f));
mat5 = new CGMaterial();
mat5->SetAmbientReflect(0.0f, 1.0f, 1.0f);
mat5->SetDifusseReflect(0.0f, 1.0f, 1.0f);
mat5->SetSpecularReflect(0.8f, 0.8f, 0.8f);
mat5->SetShininess(16.0f);
mat5->SetTexture(textureId);
fig5 = new CGIcosahedron(5.0f);
fig5->SetMaterial(mat5);
fig5->Translate(glm::vec3(-25.0f, 8.0f, -25.0f));
}
//
// FUNCIÓN: CGScene3:~CGScene()
//
// PROPÓSITO: Destruye el objeto que representa la escena
//
CGScene::~CGScene()
{
delete ground;
delete fig0;
delete fig1;
delete fig2;
delete fig3;
delete fig4;
delete fig5;
delete light;
delete matg;
delete mat0;
delete mat1;
delete mat2;
delete mat3;
delete mat4;
delete mat5;
}
//
// FUNCIÓN: CGScene::Draw()
//
// PROPÓSITO: Dibuja la escena
//
void CGScene::Draw(CGShaderProgram* program, glm::mat4 proj, glm::mat4 view)
{
light->SetUniforms(program);
ground->Draw(program, proj, view);
fig0->Draw(program, proj, view);
fig1->Draw(program, proj, view);
fig2->Draw(program, proj, view);
fig3->Draw(program, proj, view);
fig4->Draw(program, proj, view);
fig5->Draw(program, proj, view);
}
|
|
|
Figuras geométricas
|
|
Con respecto a las diferentes figuras geométricas, es necesario
modificar su código para incorporar a los atributos de los vértices
el valor las coordenadas de textura en cada vértice.
El código asociado al cubo
es el siguiente.
#include "CGCube.h"
#include <GL/glew.h>
#include "CGFigure.h"
///
/// FUNCION: CGCube::CGCube(GLfloat s)
///
/// PROPÓSITO: Construye un cubo de lado'2*s'
///
CGCube::CGCube(GLfloat s)
{
numFaces = 12; // Number of faces
numVertices = 24; // Number of vertices
GLfloat p_normals[24][3] = {
{ 1.0f, 0.0f, 0.0f }, // Positive X // 0
{ 1.0f, 0.0f, 0.0f }, // Positive X // 1
{ 1.0f, 0.0f, 0.0f }, // Positive X // 2
{ 1.0f, 0.0f, 0.0f }, // Positive X // 3
{ 0.0f, 1.0f, 0.0f }, // Positive Y // 4
{ 0.0f, 1.0f, 0.0f }, // Positive Y // 5
{ 0.0f, 1.0f, 0.0f }, // Positive Y // 6
{ 0.0f, 1.0f, 0.0f }, // Positive Y // 7
{ -1.0f, 0.0f, 0.0f }, // Negative X // 8
{ -1.0f, 0.0f, 0.0f }, // Negative X // 9
{ -1.0f, 0.0f, 0.0f }, // Negative X // 10
{ -1.0f, 0.0f, 0.0f }, // Negative X // 11
{ 0.0f, -1.0f, 0.0f }, // Negative Y // 12
{ 0.0f, -1.0f, 0.0f }, // Negative Y // 13
{ 0.0f, -1.0f, 0.0f }, // Negative Y // 14
{ 0.0f, -1.0f, 0.0f }, // Negative Y // 15
{ 0.0f, 0.0f, 1.0f }, // Positive Z // 16
{ 0.0f, 0.0f, 1.0f }, // Positive Z // 17
{ 0.0f, 0.0f, 1.0f }, // Positive Z // 18
{ 0.0f, 0.0f, 1.0f }, // Positive Z // 19
{ 0.0f, 0.0f, -1.0f }, // Negative Z // 20
{ 0.0f, 0.0f, -1.0f }, // Negative Z // 21
{ 0.0f, 0.0f, -1.0f }, // Negative Z // 22
{ 0.0f, 0.0f, -1.0f } // Negative Z // 23
};
GLfloat p_textures[24][2] = { // Array of texture coordinates
{ 0.0f, 0.0f }, // Positive X
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }, // Positive Y
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }, // Negative X
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }, // Negative Y
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }, // Positive Z
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f },
{ 0.0f, 0.0f }, // Negative Z
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f }
};
GLfloat p_vertices[24][3] = {
{ +s, +s, +s }, // A0 // Positive X
{ +s, -s, +s }, // D0
{ +s, -s, -s }, // D1
{ +s, +s, -s }, // A1
{ -s, +s, +s }, // B0 // Positive Y
{ +s, +s, +s }, // A0
{ +s, +s, -s }, // A1
{ -s, +s, -s }, // B1
{ -s, -s, +s }, // C0 // Negative X
{ -s, +s, +s }, // B0
{ -s, +s, -s }, // B1
{ -s, -s, -s }, // C1
{ +s, -s, +s }, // D0 // Negative Y
{ -s, -s, +s }, // C0
{ -s, -s, -s }, // C1
{ +s, -s, -s }, // D1 0
{ +s, +s, +s }, // A0 // Positive Z
{ -s, +s, +s }, // B0
{ -s, -s, +s }, // C0
{ +s, -s, +s }, // D0 0
{ +s, +s, -s }, // A1 // Negative Z
{ +s, -s, -s }, // D1
{ -s, -s, -s }, // C1
{ -s, +s, -s } // B1
};
GLushort p_indexes[12][3] = { // Array of indexes
{ 0, 1, 2 },
{ 0, 2, 3 },
{ 4, 5, 6 },
{ 4, 6, 7 },
{ 8, 9, 10 },
{ 8, 10, 11 },
{ 12, 13, 14 },
{ 12, 14, 15 },
{ 16, 17, 18 },
{ 16, 18, 19 },
{ 20, 21, 22 },
{ 20, 22, 23 }
};
normals = new GLfloat[numVertices * 3];
for (int i = 0; i < numVertices; i++)
for (int j = 0; j < 3; j++) normals[3 * i + j] = p_normals[i][j];
vertices = new GLfloat[numVertices * 3];
for (int i = 0; i < numVertices; i++)
for (int j = 0; j < 3; j++) vertices[3 * i + j] = p_vertices[i][j];
textures = new GLfloat[numVertices * 2];
for (int i = 0; i < numVertices; i++)
for (int j = 0; j < 2; j++) textures[2 * i + j] = p_textures[i][j];
indexes = new GLushort[numFaces * 3];
for (int i = 0; i < numFaces; i++)
for (int j = 0; j < 3; j++) indexes[3 * i + j] = p_indexes[i][j];
InitBuffers();
}
|
El código del constructor del cono
es el siguiente.
#include "CGCone.h"
#include <GL/glew.h>
#include <math.h>
#include "CGFigure.h"
///
/// FUNCION: CGCone::CGCone(GLint p, GLint m, GLfloat h, GLfloat r)
///
/// PROPÓSITO: Construir un cono de radio 'r' y altura '2*h'
/// considerando las circunferencias formadas por 'm' puntos
/// y el cuerpo del cono dividido en 'p' rodajas.
///
CGCone::CGCone(GLint p, GLint m, GLfloat h, GLfloat r)
{
numFaces = 2 * p * m; // Number of faces
numVertices = (p + 1)*m + 2; // Number of vertices
vertices = new GLfloat[numVertices * 3];
normals = new GLfloat[numVertices * 3];
indexes = new GLushort[numFaces * 3];
textures = new GLfloat[numVertices * 2];
double module = sqrt(4 * h*h + r*r);
double xyN = (GLfloat)(2 * h / module);
double zN = (GLfloat)(r / module);
int verticesIndex = 0;
int normalsIndex = 0;
int texturesIndex = 0;
// Centro de la base
vertices[0] = 0.0f;
vertices[1] = 0.0f;
vertices[2] = -h;
verticesIndex += 3;
normals[0] = 0.0f;
normals[1] = 0.0f;
normals[2] = -1.0f;
normalsIndex += 3;
textures[0] = 0.5f;
textures[1] = 0.5f;
texturesIndex += 2;
// Vértices de la base
for (int i = 0; i <m; i++)
{
GLfloat x = (GLfloat)cos(glm::radians(360.0 * i / m));
GLfloat y = -(GLfloat)sin(glm::radians(360.0 * i / m));
vertices[verticesIndex] = x*r;
vertices[verticesIndex + 1] = y*r;
vertices[verticesIndex + 2] = -h;
verticesIndex += 3;
normals[normalsIndex] = 0.0f;
normals[normalsIndex+1] = 0.0f;
normals[normalsIndex+2] = -1.0f;
normalsIndex += 3;
textures[texturesIndex] = 0.5f + x * 0.5f;
textures[texturesIndex + 1] = 0.5f + y * 0.5f;
texturesIndex += 2;
}
// Extremo del cono
vertices[verticesIndex] = 0.0f;
vertices[verticesIndex + 1] = 0.0f;
vertices[verticesIndex + 2] = h;
verticesIndex += 3;
normals[normalsIndex] = 0.0f;
normals[normalsIndex+1] = 0.0f;
normals[normalsIndex+2] = 1.0f;
normalsIndex += 3;
textures[texturesIndex] = 0.5f;
textures[texturesIndex + 1] = 0.5f;
texturesIndex += 2;
// Vértices de los lados
for (int i = 1; i <= p; i++)
{
GLfloat xy = i*1.0 / p;
GLfloat z = h - 2 * i*h / p;
for (int j = 0; j < m; j++)
{
GLfloat xN = (GLfloat)cos(glm::radians(360.0 * j / m));
GLfloat yN = (GLfloat)sin(glm::radians(360.0 * j / m));
GLfloat x = (GLfloat)(xN*xy);
GLfloat y = (GLfloat)(yN*xy);
vertices[verticesIndex] = x*r;
vertices[verticesIndex + 1] = y*r;
vertices[verticesIndex + 2] = z;
verticesIndex += 3;
normals[normalsIndex] = xN*xyN;
normals[normalsIndex + 1] = yN*xyN;
normals[normalsIndex + 2] = zN;
normalsIndex += 3;
textures[texturesIndex] = 0.5f + x * 0.5f;
textures[texturesIndex + 1] = 0.5f + y * 0.5f;
texturesIndex += 2;
}
}
int indicesIndex = 0;
// Base
for (int i = 0; i < m - 1; i++)
{
indexes[indicesIndex] = 0;
indexes[indicesIndex + 1] = i + 1;
indexes[indicesIndex + 2] = i + 2;
indicesIndex += 3;
}
indexes[indicesIndex] = 0;
indexes[indicesIndex + 1] = m;
indexes[indicesIndex + 2] = 1;
indicesIndex += 3;
// Extremo
for (int i = 0; i < m - 1; i++)
{
indexes[indicesIndex] = m + 1;
indexes[indicesIndex + 1] = m + 2 + i;
indexes[indicesIndex + 2] = m + 3 + i;
indicesIndex += 3;
}
indexes[indicesIndex] = m + 1;
indexes[indicesIndex + 1] = 2 * m + 1;
indexes[indicesIndex + 2] = m + 2;
indicesIndex += 3;
// Lados
for (int j = 1; j < p; j++)
{
for (int i = 0; i < m - 1; i++)
{
indexes[indicesIndex] = j*m + 2 + i;
indexes[indicesIndex + 1] = (j + 1)*m + 2 + i;
indexes[indicesIndex + 2] = (j + 1)*m + 3 + i;
indicesIndex += 3;
indexes[indicesIndex] = j*m + 2 + i;
indexes[indicesIndex + 1] = (j + 1)*m + 3 + i;
indexes[indicesIndex + 2] = j*m + 3 + i;
indicesIndex += 3;
}
indexes[indicesIndex] = (j + 1)*m + 1;
indexes[indicesIndex + 1] = (j + 2)*m + 1;
indexes[indicesIndex + 2] = (j + 1)*m + 2;
indicesIndex += 3;
indexes[indicesIndex] = (j + 1)*m + 1;
indexes[indicesIndex + 1] = (j + 1)*m + 2;
indexes[indicesIndex + 2] = j*m + 2;
indicesIndex += 3;
}
InitBuffers();
}
|
El constructor del cilindro
queda así:
#include "CGCylinder.h"
#include <GL/glew.h>
#include <math.h>
#include "CGFigure.h"
///
/// FUNCION: CGCylinder::CGCylinder(GLint p, GLint m, GLfloat r, GLfloat l)
///
/// PROPÓSITO: Construir un cilindro de radio 'r' y longitud '2*l'
/// considerando las circunferencias formadas por 'm' puntos
/// y el cuerpo del cilindro dividido en 'p' tambores.
///
/// Tapa1: (m+1) vertices, m triángulos
/// Tapa2: (m+1) vertices, m triángulos
/// Tambor: (p+1)*(m+1) vertices, 2*p*m triángulos
///
CGCylinder::CGCylinder(GLint p, GLint m, GLfloat r, GLfloat l)
{
numFaces = 2 * m * (p + 1); // Number of faces
numVertices = (m + 1)*(p + 3); // Number of vertices
normals = new GLfloat[numVertices * 3];
textures = new GLfloat[numVertices * 2];
vertices = new GLfloat[numVertices * 3];
indexes = new GLushort[numFaces * 3];
int texturesIndex = 0;
int normalsIndex = 0;
int verticesIndex = 0;
int indexesIndex = 0;
/* northern polar cap*/
vertices[0] = 0.0f;
vertices[1] = 0.0f;
vertices[2] = l;
verticesIndex += 3;
normals[0] = 0.0f;
normals[1] = 0.0f;
normals[2] = 1.0f;
normalsIndex += 3;
textures[0] = 0.5f;
textures[1] = 0.5f;
texturesIndex += 2;
for (int j = 0; j < m; j++)
{
GLfloat mCos = (GLfloat)cos(glm::radians(360.0 * j / m));
GLfloat mSin = (GLfloat)sin(glm::radians(360.0 * j / m));
vertices[verticesIndex] = mCos * r;
vertices[verticesIndex + 1] = mSin * r;
vertices[verticesIndex + 2] = l;
verticesIndex += 3;
normals[normalsIndex] = 0.0f;
normals[normalsIndex + 1] = 0.0f;
normals[normalsIndex + 2] = 1.0f;
normalsIndex += 3;
textures[texturesIndex] = 0.5f + mCos / 2;
textures[texturesIndex + 1] = 0.5f + mSin / 2;
texturesIndex += 2;
indexes[indexesIndex] = 0; // center
indexes[indexesIndex + 1] = j + 1;
indexes[indexesIndex + 2] = (j + 2>m ? 1 : j + 2);
indexesIndex += 3;
}
/* southern polar cap*/
vertices[verticesIndex] = 0.0f;
vertices[verticesIndex + 1] = 0.0f;
vertices[verticesIndex + 2] = -l;
verticesIndex += 3;
normals[normalsIndex] = 0.0f;
normals[normalsIndex + 1] = 0.0f;
normals[normalsIndex + 2] = -1.0f;
normalsIndex += 3;
textures[texturesIndex] = 0.5f;
textures[texturesIndex + 1] = 0.5f;
texturesIndex += 2;
for (int j = 0; j < m; j++)
{
GLfloat mCos = (GLfloat)cos(glm::radians(360.0 * j / m));
GLfloat mSin = (GLfloat)sin(glm::radians(360.0 * j / m));
vertices[verticesIndex] = mCos * r;
vertices[verticesIndex + 1] = -mSin * r;
vertices[verticesIndex + 2] = -l;
verticesIndex += 3;
normals[normalsIndex] = 0.0f;
normals[normalsIndex + 1] = 0.0f;
normals[normalsIndex + 2] = -1.0f;
normalsIndex += 3;
textures[texturesIndex] = 0.5f + mCos / 2;
textures[texturesIndex + 1] = 0.5f - mSin / 2;
texturesIndex += 2;
indexes[indexesIndex] = m + 1; // center
indexes[indexesIndex + 1] = j + m + 2;
indexes[indexesIndex + 2] = (j + 2>m ? m + 2 : j + m + 3);
indexesIndex += 3;
}
/* body */
for (int i = 0; i <= p; i++)
{
for (int j = 0; j <= m; j++)
{
GLfloat mCos = (GLfloat)cos(glm::radians(360.0 * j / m));
GLfloat mSin = (GLfloat)sin(glm::radians(360.0 * j / m));
vertices[verticesIndex] = mCos * r;
vertices[verticesIndex + 1] = mSin * r;
vertices[verticesIndex + 2] = l - 2 * l*i / p;
verticesIndex += 3;
normals[normalsIndex] = mCos;
normals[normalsIndex + 1] = mSin;
normals[normalsIndex + 2] = 0.0f;
normalsIndex += 3;
textures[texturesIndex] = ((GLfloat)j) / m;
textures[texturesIndex + 1] = ((GLfloat)i) / p;
texturesIndex += 2;
}
}
int base = 2 * m + 2;
for (int i = 0; i < p; i++)
{
for (int j = 0; j < m; j++)
{
indexes[indexesIndex] = base + (m + 1)*i + j;
indexes[indexesIndex + 1] = base + (m + 1)*(i + 1) + j;
indexes[indexesIndex + 2] = base + (m + 1)*(i + 1) + j + 1;
indexesIndex += 3;
indexes[indexesIndex] = base + (m + 1)*i + j;
indexes[indexesIndex + 1] = base + (m + 1)*(i + 1) + j + 1;
indexes[indexesIndex + 2] = base + (m + 1)*i + j + 1;
indexesIndex += 3;
}
}
InitBuffers();
}
|
El constructor de la esfera
sería este:
#include "CGSphere.h"
#include <GL/glew.h>
#include <math.h>
#include "CGFigure.h"
///
/// FUNCION: CGSphere::CGSphere(GLint p, GLint m, GLfloat r)
///
/// PROPÓSITO: Construye una espera de radio 'r' con 'p' paralelos
/// y 'm' meridianos
///
CGSphere::CGSphere(GLint p, GLint m, GLfloat r)
{
numFaces = 2 * m*(p - 1); // Number of faces
numVertices = (m + 1)*(p + 1); // Number of vertices
normals = new GLfloat[numVertices * 3];
textures = new GLfloat[numVertices * 2];
vertices = new GLfloat[numVertices * 3];
indexes = new GLushort[numFaces * 3];
int texturesIndex = 0;
int normalsIndex = 0;
int verticesIndex = 0;
int indexesIndex = 0;
/* northern polar cap*/
for (int j = 0; j <= m; j++)
{
textures[texturesIndex] = (j + 0.5) / m;
textures[texturesIndex + 1] = 1.0f;
texturesIndex += 2;
normals[normalsIndex] = 0.0f;
normals[normalsIndex + 1] = 0.0f;
normals[normalsIndex + 2] = 1.0f;
normalsIndex += 3;
vertices[verticesIndex] = 0.0;
vertices[verticesIndex + 1] = 0.0f;
vertices[verticesIndex + 2] = r;
verticesIndex += 3;
}
for (int i = 1; i < p; i++)
{
for (int j = 0; j <= m; j++)
{
GLfloat pCos = (GLfloat)cos(glm::radians(180.0 * i / p));
GLfloat pSin = (GLfloat)sin(glm::radians(180.0 * i / p));
GLfloat mCos = (GLfloat)cos(glm::radians(360.0 * j / m));
GLfloat mSin = (GLfloat)sin(glm::radians(360.0 * j / m));
textures[texturesIndex] = ((GLfloat)j) / m;
textures[texturesIndex + 1] = 1.0 - ((GLfloat)i / p);
texturesIndex += 2;
normals[normalsIndex] = pSin*mCos;
normals[normalsIndex + 1] = pSin*mSin;
normals[normalsIndex + 2] = pCos;
normalsIndex += 3;
vertices[verticesIndex] = pSin*mCos*r;
vertices[verticesIndex + 1] = pSin*mSin*r;
vertices[verticesIndex + 2] = pCos*r;
verticesIndex += 3;
}
}
/* southern polar cap*/
for (int j = 0; j <= m; j++)
{
textures[texturesIndex] = (j + 0.5) / m;
textures[texturesIndex + 1] = 0.0f;
texturesIndex += 2;
normals[normalsIndex] = 0.0f;
normals[normalsIndex + 1] = 0.0f;
normals[normalsIndex + 2] = -1.0f;
normalsIndex += 3;
vertices[verticesIndex] = 0.0;
vertices[verticesIndex + 1] = 0.0f;
vertices[verticesIndex + 2] = -r;
verticesIndex += 3;
}
/* northern polar cap*/
for (int j = 0; j < m; j++)
{
indexes[indexesIndex] = j;
indexes[indexesIndex + 1] = m + j + 1;
indexes[indexesIndex + 2] = m + j + 2;
indexesIndex += 3;
}
for (int i = 1; i < p - 1; i++)
{
for (int j = 0; j < m; j++)
{
indexes[indexesIndex] = i*(m + 1) + j;
indexes[indexesIndex + 1] = (i + 1)*(m + 1) + j;
indexes[indexesIndex + 2] = i*(m + 1) + j + 1;
indexes[indexesIndex + 3] = (i + 1)*(m + 1) + j;
indexes[indexesIndex + 4] = (i + 1)*(m + 1) + j + 1;
indexes[indexesIndex + 5] = i*(m + 1) + j + 1;
indexesIndex += 6;
}
}
for (int j = 0; j < m; j++)
{
indexes[indexesIndex] = (p - 1)*(m + 1) + j;
indexes[indexesIndex + 1] = p*(m + 1) + j;
indexes[indexesIndex + 2] = (p - 1)*(m + 1) + j + 1;
indexesIndex += 3;
}
InitBuffers();
}
|
El código para construir un toro
es el siguiente.
#include "CGTorus.h"
#include <GL/glew.h>
#include <math.h>
#include "CGFigure.h"
//
// FUNCIÓN: CGTorus::CGTorus(GLint p, GLint m, GLfloat r0, GLfloat r1)
//
// PROPÓSITO: Crea un toro
//
// COMENTARIOS:
//
// 'p' es el número de capas en las que se divide el toro
// 'm' es el número de sectores en que se divide cada capa
// 'r0' es el radio interior del toro
// 'r1' es el radio exterior del toro
//
CGTorus::CGTorus(GLint p, GLint m, GLfloat r0, GLfloat r1)
{
numFaces = 2 * m * p; // Number of faces
numVertices = (m + 1)*(p + 1); // Number of vertices
normals = new GLfloat[numVertices * 3];
textures = new GLfloat[numVertices * 2];
vertices = new GLfloat[numVertices * 3];
indexes = new GLushort[numFaces * 3];
int texturesIndex = 0;
int normalsIndex = 0;
int verticesIndex = 0;
int indexesIndex = 0;
for (int i = 0; i <= m; i++)
{
for (int j = 0; j <= p; j++)
{
GLfloat pCos = (GLfloat)cos(glm::radians(360.0 * j / p));
GLfloat pSin = (GLfloat)sin(glm::radians(360.0 * j / p));
GLfloat mCos = (GLfloat)cos(glm::radians(360.0 * i / m));
GLfloat mSin = (GLfloat)sin(glm::radians(360.0 * i / m));
vertices[verticesIndex] = (r1 + r0*pCos)*mCos;
vertices[verticesIndex + 1] = (r1 + r0*pCos)*mSin;
vertices[verticesIndex + 2] = r0*pSin;
verticesIndex += 3;
normals[normalsIndex] = pCos * mCos;
normals[normalsIndex + 1] = pCos * mSin;
normals[normalsIndex + 2] = pSin;
normalsIndex += 3;
textures[texturesIndex] = ((GLfloat)j) / p;
textures[texturesIndex + 1] = ((GLfloat)i) / m;
texturesIndex += 2;
}
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < p; j++)
{
indexes[indexesIndex] = (p + 1)*i + j;
indexes[indexesIndex + 1] = (p + 1)*(i + 1) + j;
indexes[indexesIndex + 2] = (p + 1)*(i + 1) + j + 1;
indexesIndex += 3;
indexes[indexesIndex] = (p + 1)*i + j;
indexes[indexesIndex + 1] = (p + 1)*(i + 1) + j + 1;
indexes[indexesIndex + 2] = (p + 1)*i + j + 1;
indexesIndex += 3;
}
}
InitBuffers();
}
|
El icosahedro
se construye con el siguiente código.
#include "CGIcosahedron.h"
#include <GL/glew.h>
#include <math.h>
#include "CGFigure.h"
//
// FUNCIÓN: CGIcosahedron::CGIcosahedron(GLfloat r)
//
// PROPÓSITO: Dibuja un icosaedro de arista '2r'
//
CGIcosahedron::CGIcosahedron(GLfloat r)
{
numFaces = 20; // Number of faces
numVertices = 60; // Number of vertices
normals = new GLfloat[numVertices * 3];
textures = new GLfloat[numVertices * 2];
vertices = new GLfloat[numVertices * 3];
indexes = new GLushort[numFaces * 3];
GLfloat phi = (GLfloat)((1 + sqrt(5.0)) / 2.0);
GLfloat mod = (GLfloat)sqrt(6 + 9 * phi);
GLfloat p0M = (GLfloat)phi / mod;
GLfloat p1M = (GLfloat)(phi + 1) / mod;
GLfloat p2M = (GLfloat)(2 * phi + 1) / mod;
GLfloat X0 = 0.0f;
GLfloat X1 = 1.0f / 11;
GLfloat X2 = 2.0f / 11;
GLfloat X3 = 3.0f / 11;
GLfloat X4 = 4.0f / 11;
GLfloat X5 = 5.0f / 11;
GLfloat X6 = 6.0f / 11;
GLfloat X7 = 7.0f / 11;
GLfloat X8 = 8.0f / 11;
GLfloat X9 = 9.0f / 11;
GLfloat X10 = 10.0f / 11;
GLfloat X11 = 1.0f;
GLfloat Y0 = 0.0f;
GLfloat Y1 = 1.0f / 3;
GLfloat Y2 = 2.0f / 3;
GLfloat Y3 = 1.0f;
GLfloat A0[] = { 0, r*phi, r };
GLfloat A1[] = { 0, r*phi, -r };
GLfloat A2[] = { 0, -r*phi, -r };
GLfloat A3[] = { 0, -r*phi, r };
GLfloat B0[] = { r*phi, r, 0 };
GLfloat B1[] = { r*phi, -r, 0 };
GLfloat B2[] = { -r*phi, -r, 0 };
GLfloat B3[] = { -r*phi, r, 0 };
GLfloat C0[] = { r, 0, r*phi };
GLfloat C1[] = { r, 0, -r*phi };
GLfloat C2[] = { -r, 0, -r*phi };
GLfloat C3[] = { -r, 0, r*phi };
GLfloat N1[] = { -p0M, p2M, 0 };
GLfloat N2[] = { -p1M, p1M, p1M };
GLfloat N3[] = { 0, p0M, p2M };
GLfloat N4[] = { p1M, p1M, p1M };
GLfloat N5[] = { p0M, p2M, 0 };
GLfloat N6[] = { p2M, 0, -p0M };
GLfloat N7[] = { p2M, 0, p0M };
GLfloat N8[] = { p1M, -p1M, p1M };
GLfloat N9[] = { p0M, -p2M, 0 };
GLfloat N10[] = { p1M, -p1M, -p1M };
GLfloat N11[] = { p1M, p1M, -p1M };
GLfloat N12[] = { 0, -p0M, p2M };
GLfloat N13[] = { 0, p0M, -p2M };
GLfloat N14[] = { -p1M, p1M, -p1M };
GLfloat N15[] = { -p2M, 0, p0M };
GLfloat N16[] = { -p1M, -p1M, p1M };
GLfloat N17[] = { -p2M, 0, -p0M };
GLfloat N18[] = { 0, -p0M, -p2M };
GLfloat N19[] = { -p1M, -p1M, -p1M };
GLfloat N20[] = { -p0M, -p2M, 0 };
int texturesIndex = 0;
int normalsIndex = 0;
int verticesIndex = 0;
// face 1; vertex[1] = A0; normals[1]=N1; textures[1]={X1,Y3};
vertices[verticesIndex] = A0[0];
vertices[verticesIndex + 1] = A0[1];
vertices[verticesIndex + 2] = A0[2];
verticesIndex += 3;
normals[normalsIndex] = N1[0];
normals[normalsIndex + 1] = N1[1];
normals[normalsIndex + 2] = N1[2];
normalsIndex += 3;
textures[texturesIndex] = X1;
textures[texturesIndex + 1] = Y3;
texturesIndex += 2;
// face 1; vertex[2]=A1; normals[2]=N1; textures[2]={X0,Y2};
vertices[verticesIndex] = A1[0];
vertices[verticesIndex + 1] = A1[1];
vertices[verticesIndex + 2] = A1[2];
verticesIndex += 3;
normals[normalsIndex] = N1[0];
normals[normalsIndex + 1] = N1[1];
normals[normalsIndex + 2] = N1[2];
normalsIndex += 3;
textures[texturesIndex] = X0;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 1; vertex[3]=B3; normals[3]=N1; textures[3]={X2,Y2};
vertices[verticesIndex] = B3[0];
vertices[verticesIndex + 1] = B3[1];
vertices[verticesIndex + 2] = B3[2];
verticesIndex += 3;
normals[normalsIndex] = N1[0];
normals[normalsIndex + 1] = N1[1];
normals[normalsIndex + 2] = N1[2];
normalsIndex += 3;
textures[texturesIndex] = X2;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 2; vertex[1] = A0; normals[1]=N2; textures[1]={X3,Y3};
vertices[verticesIndex] = A0[0];
vertices[verticesIndex + 1] = A0[1];
vertices[verticesIndex + 2] = A0[2]; verticesIndex += 3;
normals[normalsIndex] = N2[0];
normals[normalsIndex + 1] = N2[1];
normals[normalsIndex + 2] = N2[2];
normalsIndex += 3;
textures[texturesIndex] = X3;
textures[texturesIndex + 1] = Y3;
texturesIndex += 2;
// face 2; vertex[2] = B3; normals[2]=N2; textures[2]={X2,Y2};
vertices[verticesIndex] = B3[0];
vertices[verticesIndex + 1] = B3[1];
vertices[verticesIndex + 2] = B3[2];
verticesIndex += 3;
normals[normalsIndex] = N2[0];
normals[normalsIndex + 1] = N2[1];
normals[normalsIndex + 2] = N2[2];
normalsIndex += 3;
textures[texturesIndex] = X2;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 2; vertex[3] = C3; normals[3]=N2; textures[3]={X4,Y2};
vertices[verticesIndex] = C3[0];
vertices[verticesIndex + 1] = C3[1];
vertices[verticesIndex + 2] = C3[2];
verticesIndex += 3;
normals[normalsIndex] = N2[0];
normals[normalsIndex + 1] = N2[1];
normals[normalsIndex + 2] = N2[2];
normalsIndex += 3;
textures[texturesIndex] = X4;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 3; vertex[1] = A0; normals[1]=N3; textures[1]={X5,Y3};
vertices[verticesIndex] = A0[0];
vertices[verticesIndex + 1] = A0[1];
vertices[verticesIndex + 2] = A0[2];
verticesIndex += 3;
normals[normalsIndex] = N3[0];
normals[normalsIndex + 1] = N3[1];
normals[normalsIndex + 2] = N3[2];
normalsIndex += 3;
textures[texturesIndex] = X5;
textures[texturesIndex + 1] = Y3;
texturesIndex += 2;
// face 3; vertex[2] = C3; normals[2]=N3; textures[2]={X4,Y2};
vertices[verticesIndex] = C3[0];
vertices[verticesIndex + 1] = C3[1];
vertices[verticesIndex + 2] = C3[2];
verticesIndex += 3;
normals[normalsIndex] = N3[0];
normals[normalsIndex + 1] = N3[1];
normals[normalsIndex + 2] = N3[2];
normalsIndex += 3;
textures[texturesIndex] = X4;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 3; vertex[3] = C0; normals[3]=N3; textures[3]={X6,Y2};
vertices[verticesIndex] = C0[0];
vertices[verticesIndex + 1] = C0[1];
vertices[verticesIndex + 2] = C0[2];
verticesIndex += 3;
normals[normalsIndex] = N3[0];
normals[normalsIndex + 1] = N3[1];
normals[normalsIndex + 2] = N3[2];
normalsIndex += 3;
textures[texturesIndex] = X6;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 4; vertex[1] = A0; normals[1]=N4; textures[1]={X7,Y3};
vertices[verticesIndex] = A0[0];
vertices[verticesIndex + 1] = A0[1];
vertices[verticesIndex + 2] = A0[2];
verticesIndex += 3;
normals[normalsIndex] = N4[0];
normals[normalsIndex + 1] = N4[1];
normals[normalsIndex + 2] = N4[2];
normalsIndex += 3;
textures[texturesIndex] = X7;
textures[texturesIndex + 1] = Y3;
texturesIndex += 2;
// face 4; vertex[2] = C0; normals[2]=N4; textures[2]={X6,Y2};
vertices[verticesIndex] = C0[0];
vertices[verticesIndex + 1] = C0[1];
vertices[verticesIndex + 2] = C0[2];
verticesIndex += 3;
normals[normalsIndex] = N4[0];
normals[normalsIndex + 1] = N4[1];
normals[normalsIndex + 2] = N4[2];
normalsIndex += 3;
textures[texturesIndex] = X6;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 4; vertex[3] = B0; normals[3]=N4; textures[3]={X8,Y2};
vertices[verticesIndex] = B0[0];
vertices[verticesIndex + 1] = B0[1];
vertices[verticesIndex + 2] = B0[2];
verticesIndex += 3;
normals[normalsIndex] = N4[0];
normals[normalsIndex + 1] = N4[1];
normals[normalsIndex + 2] = N4[2];
normalsIndex += 3;
textures[texturesIndex] = X8;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 5; vertex[1] = A0; normals[1]=N5; textures[1]={X9,Y3};
vertices[verticesIndex] = A0[0];
vertices[verticesIndex + 1] = A0[1];
vertices[verticesIndex + 2] = A0[2];
verticesIndex += 3;
normals[normalsIndex] = N5[0];
normals[normalsIndex + 1] = N5[1];
normals[normalsIndex + 2] = N5[2];
normalsIndex += 3;
textures[texturesIndex] = X9;
textures[texturesIndex + 1] = Y3;
texturesIndex += 2;
// face 5; vertex[2] = B0; normals[2]=N5; textures[2]={X8,Y2};
vertices[verticesIndex] = B0[0];
vertices[verticesIndex + 1] = B0[1];
vertices[verticesIndex + 2] = B0[2];
verticesIndex += 3;
normals[normalsIndex] = N5[0];
normals[normalsIndex + 1] = N5[1];
normals[normalsIndex + 2] = N5[2];
normalsIndex += 3;
textures[texturesIndex] = X8;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 5; vertex[3] = A1; normals[3]=N5; textures[3]={X10,Y2};
vertices[verticesIndex] = A1[0];
vertices[verticesIndex + 1] = A1[1];
vertices[verticesIndex + 2] = A1[2];
verticesIndex += 3;
normals[normalsIndex] = N5[0];
normals[normalsIndex + 1] = N5[1];
normals[normalsIndex + 2] = N5[2];
normalsIndex += 3;
textures[texturesIndex] = X10;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 6; vertex[1] = B1; normals[1]=N6; textures[1]={X7,Y1};
vertices[verticesIndex] = B1[0];
vertices[verticesIndex + 1] = B1[1];
vertices[verticesIndex + 2] = B1[2];
verticesIndex += 3;
normals[normalsIndex] = N6[0];
normals[normalsIndex + 1] = N6[1];
normals[normalsIndex + 2] = N6[2];
normalsIndex += 3;
textures[texturesIndex] = X7;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 6; vertex[2] = C1; normals[2]=N6; textures[2]={X9,Y1};
vertices[verticesIndex] = C1[0];
vertices[verticesIndex + 1] = C1[1];
vertices[verticesIndex + 2] = C1[2];
verticesIndex += 3;
normals[normalsIndex] = N6[0];
normals[normalsIndex + 1] = N6[1];
normals[normalsIndex + 2] = N6[2];
normalsIndex += 3;
textures[texturesIndex] = X9;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 6; vertex[3] = B0; normals[3]=N6; textures[3]={X8,Y2};
vertices[verticesIndex] = B0[0];
vertices[verticesIndex + 1] = B0[1];
vertices[verticesIndex + 2] = B0[2];
verticesIndex += 3;
normals[normalsIndex] = N6[0];
normals[normalsIndex + 1] = N6[1];
normals[normalsIndex + 2] = N6[2];
normalsIndex += 3;
textures[texturesIndex] = X8;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 7; vertex[1] = B1; normals[1]=N7; textures[1]={X7,Y1};
vertices[verticesIndex] = B1[0];
vertices[verticesIndex + 1] = B1[1];
vertices[verticesIndex + 2] = B1[2];
verticesIndex += 3;
normals[normalsIndex] = N7[0];
normals[normalsIndex + 1] = N7[1];
normals[normalsIndex + 2] = N7[2];
normalsIndex += 3;
textures[texturesIndex] = X7;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 7; vertex[2] = B0; normals[2]=N7; textures[2]={X8,Y2};
vertices[verticesIndex] = B0[0];
vertices[verticesIndex + 1] = B0[1];
vertices[verticesIndex + 2] = B0[2];
verticesIndex += 3;
normals[normalsIndex] = N7[0];
normals[normalsIndex + 1] = N7[1];
normals[normalsIndex + 2] = N7[2];
normalsIndex += 3;
textures[texturesIndex] = X8;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 7; vertex[3] = C0; normals[3]=N7; textures[3]={X6,Y2};
vertices[verticesIndex] = C0[0];
vertices[verticesIndex + 1] = C0[1];
vertices[verticesIndex + 2] = C0[2];
verticesIndex += 3;
normals[normalsIndex] = N7[0];
normals[normalsIndex + 1] = N7[1];
normals[normalsIndex + 2] = N7[2];
normalsIndex += 3;
textures[texturesIndex] = X6;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 8; vertex[1] = B1; normals[1]=N8; textures[1]={X7,Y1};
vertices[verticesIndex] = B1[0];
vertices[verticesIndex + 1] = B1[1];
vertices[verticesIndex + 2] = B1[2];
verticesIndex += 3;
normals[normalsIndex] = N8[0];
normals[normalsIndex + 1] = N8[1];
normals[normalsIndex + 2] = N8[2];
normalsIndex += 3;
textures[texturesIndex] = X7;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 8; vertex[2] = C0; normals[2]=N8; textures[2]={X6,Y2};
vertices[verticesIndex] = C0[0];
vertices[verticesIndex + 1] = C0[1];
vertices[verticesIndex + 2] = C0[2];
verticesIndex += 3;
normals[normalsIndex] = N8[0];
normals[normalsIndex + 1] = N8[1];
normals[normalsIndex + 2] = N8[2];
normalsIndex += 3;
textures[texturesIndex] = X6;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 8; vertex[3] = A3; normals[3]=N8; textures[3]={X5,Y1};
vertices[verticesIndex] = A3[0];
vertices[verticesIndex + 1] = A3[1];
vertices[verticesIndex + 2] = A3[2];
verticesIndex += 3;
normals[normalsIndex] = N8[0];
normals[normalsIndex + 1] = N8[1];
normals[normalsIndex + 2] = N8[2];
normalsIndex += 3;
textures[texturesIndex] = X5;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 9; vertex[1] = B1; normals[1]=N9; textures[1]={X7,Y1};
vertices[verticesIndex] = B1[0];
vertices[verticesIndex + 1] = B1[1];
vertices[verticesIndex + 2] = B1[2];
verticesIndex += 3;
normals[normalsIndex] = N9[0];
normals[normalsIndex + 1] = N9[1];
normals[normalsIndex + 2] = N9[2];
normalsIndex += 3;
textures[texturesIndex] = X7;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 9; vertex[2] = A3; normals[2]=N9; textures[2]={X5,Y1};
vertices[verticesIndex] = A3[0];
vertices[verticesIndex + 1] = A3[1];
vertices[verticesIndex + 2] = A3[2];
verticesIndex += 3;
normals[normalsIndex] = N9[0];
normals[normalsIndex + 1] = N9[1];
normals[normalsIndex + 2] = N9[2];
normalsIndex += 3;
textures[texturesIndex] = X5;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 9; vertex[3] = A2; normals[3]=N9; textures[3]={X6,Y0};
vertices[verticesIndex] = A2[0];
vertices[verticesIndex + 1] = A2[1];
vertices[verticesIndex + 2] = A2[2];
verticesIndex += 3;
normals[normalsIndex] = N9[0];
normals[normalsIndex + 1] = N9[1];
normals[normalsIndex + 2] = N9[2];
normalsIndex += 3;
textures[texturesIndex] = X6;
textures[texturesIndex + 1] = Y0;
texturesIndex += 2;
// face 10; vertex[1] = B1; normals[1]=N10; textures[1]={X7,Y1};
vertices[verticesIndex] = B1[0];
vertices[verticesIndex + 1] = B1[1];
vertices[verticesIndex + 2] = B1[2];
verticesIndex += 3;
normals[normalsIndex] = N10[0];
normals[normalsIndex + 1] = N10[1];
normals[normalsIndex + 2] = N10[2];
normalsIndex += 3;
textures[texturesIndex] = X7;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 10; vertex[2] = A2; normals[2]=N10; textures[2]={X8,Y0};
vertices[verticesIndex] = A2[0];
vertices[verticesIndex + 1] = A2[1];
vertices[verticesIndex + 2] = A2[2];
verticesIndex += 3;
normals[normalsIndex] = N10[0];
normals[normalsIndex + 1] = N10[1];
normals[normalsIndex + 2] = N10[2];
normalsIndex += 3;
textures[texturesIndex] = X8;
textures[texturesIndex + 1] = Y0;
texturesIndex += 2;
// face 10; vertex[3] = C1; normals[3]=N10; textures[3]={X9,Y1};
vertices[verticesIndex] = C1[0];
vertices[verticesIndex + 1] = C1[1];
vertices[verticesIndex + 2] = C1[2];
verticesIndex += 3;
normals[normalsIndex] = N10[0];
normals[normalsIndex + 1] = N10[1];
normals[normalsIndex + 2] = N10[2];
normalsIndex += 3;
textures[texturesIndex] = X9;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 11; vertex[1] = B0; normals[1]=N11; textures[1]={X8,Y2};
vertices[verticesIndex] = B0[0];
vertices[verticesIndex + 1] = B0[1];
vertices[verticesIndex + 2] = B0[2];
verticesIndex += 3;
normals[normalsIndex] = N11[0];
normals[normalsIndex + 1] = N11[1];
normals[normalsIndex + 2] = N11[2];
normalsIndex += 3;
textures[texturesIndex] = X8;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 11; vertex[2] = C1; normals[2]=N11; textures[2]={X9,Y1};
vertices[verticesIndex] = C1[0];
vertices[verticesIndex + 1] = C1[1];
vertices[verticesIndex + 2] = C1[2];
verticesIndex += 3;
normals[normalsIndex] = N11[0];
normals[normalsIndex + 1] = N11[1];
normals[normalsIndex + 2] = N11[2];
normalsIndex += 3;
textures[texturesIndex] = X9;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 11; vertex[3] = A1; normals[3]=N11; textures[3]={X10,Y2};
vertices[verticesIndex] = A1[0];
vertices[verticesIndex + 1] = A1[1];
vertices[verticesIndex + 2] = A1[2];
verticesIndex += 3;
normals[normalsIndex] = N11[0];
normals[normalsIndex + 1] = N11[1];
normals[normalsIndex + 2] = N11[2];
normalsIndex += 3;
textures[texturesIndex] = X10;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 12; vertex[1] = C0; normals[1]=N12; textures[1]={X6,Y2};
vertices[verticesIndex] = C0[0];
vertices[verticesIndex + 1] = C0[1];
vertices[verticesIndex + 2] = C0[2];
verticesIndex += 3;
normals[normalsIndex] = N12[0];
normals[normalsIndex + 1] = N12[1];
normals[normalsIndex + 2] = N12[2];
normalsIndex += 3;
textures[texturesIndex] = X6;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 12; vertex[2] = C3; normals[2]=N12; textures[2]={X4,Y2};
vertices[verticesIndex] = C3[0];
vertices[verticesIndex + 1] = C3[1];
vertices[verticesIndex + 2] = C3[2];
verticesIndex += 3;
normals[normalsIndex] = N12[0];
normals[normalsIndex + 1] = N12[1];
normals[normalsIndex + 2] = N12[2];
normalsIndex += 3;
textures[texturesIndex] = X4;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 12; vertex[3] = A3; normals[3]=N12; textures[3]={X5,Y1};
vertices[verticesIndex] = A3[0];
vertices[verticesIndex + 1] = A3[1];
vertices[verticesIndex + 2] = A3[2];
verticesIndex += 3;
normals[normalsIndex] = N12[0];
normals[normalsIndex + 1] = N12[1];
normals[normalsIndex + 2] = N12[2];
normalsIndex += 3;
textures[texturesIndex] = X5;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 13; vertex[1] = A1; normals[1]=N13; textures[1]={X10,Y2};
vertices[verticesIndex] = A1[0];
vertices[verticesIndex + 1] = A1[1];
vertices[verticesIndex + 2] = A1[2];
verticesIndex += 3;
normals[normalsIndex] = N13[0];
normals[normalsIndex + 1] = N13[1];
normals[normalsIndex + 2] = N13[2];
normalsIndex += 3;
textures[texturesIndex] = X10;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 13; vertex[2] = C1; normals[2]=N13; textures[2]={X9,Y1};
vertices[verticesIndex] = C1[0];
vertices[verticesIndex + 1] = C1[1];
vertices[verticesIndex + 2] = C1[2];
verticesIndex += 3;
normals[normalsIndex] = N13[0];
normals[normalsIndex + 1] = N13[1];
normals[normalsIndex + 2] = N13[2];
normalsIndex += 3;
textures[texturesIndex] = X9;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 13; vertex[3] = C2; normals[3]=N13; textures[3]={X11,Y1};
vertices[verticesIndex] = C2[0];
vertices[verticesIndex + 1] = C2[1];
vertices[verticesIndex + 2] = C2[2];
verticesIndex += 3;
normals[normalsIndex] = N13[0];
normals[normalsIndex + 1] = N13[1];
normals[normalsIndex + 2] = N13[2];
normalsIndex += 3;
textures[texturesIndex] = X11;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 14; vertex[1] = A1; normals[1]=N14; textures[1]={X0,Y2};
vertices[verticesIndex] = A1[0];
vertices[verticesIndex + 1] = A1[1];
vertices[verticesIndex + 2] = A1[2];
verticesIndex += 3;
normals[normalsIndex] = N14[0];
normals[normalsIndex + 1] = N14[1];
normals[normalsIndex + 2] = N14[2];
normalsIndex += 3;
textures[texturesIndex] = X0;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 14; vertex[2] = C2; normals[2]=N14; textures[2]={X1,Y1};
vertices[verticesIndex] = C2[0];
vertices[verticesIndex + 1] = C2[1];
vertices[verticesIndex + 2] = C2[2];
verticesIndex += 3;
normals[normalsIndex] = N14[0];
normals[normalsIndex + 1] = N14[1];
normals[normalsIndex + 2] = N14[2];
normalsIndex += 3;
textures[texturesIndex] = X1;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 14; vertex[3] = B3; normals[3]=N14; textures[3]={X2,Y2};
vertices[verticesIndex] = B3[0];
vertices[verticesIndex + 1] = B3[1];
vertices[verticesIndex + 2] = B3[2];
verticesIndex += 3;
normals[normalsIndex] = N14[0];
normals[normalsIndex + 1] = N14[1];
normals[normalsIndex + 2] = N14[2];
normalsIndex += 3;
textures[texturesIndex] = X2;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 15; vertex[1] = C3; normals[1]=N15; textures[1]={X4,Y2};
vertices[verticesIndex] = C3[0];
vertices[verticesIndex + 1] = C3[1];
vertices[verticesIndex + 2] = C3[2];
verticesIndex += 3;
normals[normalsIndex] = N15[0];
normals[normalsIndex + 1] = N15[1];
normals[normalsIndex + 2] = N15[2];
normalsIndex += 3;
textures[texturesIndex] = X4;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 15; vertex[2] = B3; normals[2]=N15; textures[2]={X2,Y2};
vertices[verticesIndex] = B3[0];
vertices[verticesIndex + 1] = B3[1];
vertices[verticesIndex + 2] = B3[2];
verticesIndex += 3;
normals[normalsIndex] = N15[0];
normals[normalsIndex + 1] = N15[1];
normals[normalsIndex + 2] = N15[2];
normalsIndex += 3;
textures[texturesIndex] = X2;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 15; vertex[3] = B2; normals[3]=N15; textures[3]={X3,Y1};
vertices[verticesIndex] = B2[0];
vertices[verticesIndex + 1] = B2[1];
vertices[verticesIndex + 2] = B2[2];
verticesIndex += 3;
normals[normalsIndex] = N15[0];
normals[normalsIndex + 1] = N15[1];
normals[normalsIndex + 2] = N15[2];
normalsIndex += 3;
textures[texturesIndex] = X3;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 16; vertex[1] = C3; normals[1]=N16; textures[1]={X4,Y2};
vertices[verticesIndex] = C3[0];
vertices[verticesIndex + 1] = C3[1];
vertices[verticesIndex + 2] = C3[2];
verticesIndex += 3;
normals[normalsIndex] = N16[0];
normals[normalsIndex + 1] = N16[1];
normals[normalsIndex + 2] = N16[2];
normalsIndex += 3;
textures[texturesIndex] = X4;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 16; vertex[2] = B2; normals[2]=N16; textures[2]={X3,Y1};
vertices[verticesIndex] = B2[0];
vertices[verticesIndex + 1] = B2[1];
vertices[verticesIndex + 2] = B2[2];
verticesIndex += 3;
normals[normalsIndex] = N16[0];
normals[normalsIndex + 1] = N16[1];
normals[normalsIndex + 2] = N16[2];
normalsIndex += 3;
textures[texturesIndex] = X3;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 16; vertex[3] = A3; normals[3]=N16; textures[3]={X5,Y1};
vertices[verticesIndex] = A3[0];
vertices[verticesIndex + 1] = A3[1];
vertices[verticesIndex + 2] = A3[2];
verticesIndex += 3;
normals[normalsIndex] = N16[0];
normals[normalsIndex + 1] = N16[1];
normals[normalsIndex + 2] = N16[2];
normalsIndex += 3;
textures[texturesIndex] = X5;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 17; vertex[1] = B3; normals[1]=N17; textures[1]={X2,Y2};
vertices[verticesIndex] = B3[0];
vertices[verticesIndex + 1] = B3[1];
vertices[verticesIndex + 2] = B3[2];
verticesIndex += 3;
normals[normalsIndex] = N17[0];
normals[normalsIndex + 1] = N17[1];
normals[normalsIndex + 2] = N17[2];
normalsIndex += 3;
textures[texturesIndex] = X2;
textures[texturesIndex + 1] = Y2;
texturesIndex += 2;
// face 17; vertex[2] = C2; normals[2]=N17; textures[2]={X1,Y1};
vertices[verticesIndex] = C2[0];
vertices[verticesIndex + 1] = C2[1];
vertices[verticesIndex + 2] = C2[2];
verticesIndex += 3;
normals[normalsIndex] = N17[0];
normals[normalsIndex + 1] = N17[1];
normals[normalsIndex + 2] = N17[2];
normalsIndex += 3;
textures[texturesIndex] = X1;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 17; vertex[3] = B2; normals[1]=N17; textures[3]={X3,Y1};
vertices[verticesIndex] = B2[0];
vertices[verticesIndex + 1] = B2[1];
vertices[verticesIndex + 2] = B2[2];
verticesIndex += 3;
normals[normalsIndex] = N17[0];
normals[normalsIndex + 1] = N17[1];
normals[normalsIndex + 2] = N17[2];
normalsIndex += 3;
textures[texturesIndex] = X3;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 18; vertex[1] = C2; normals[1]=N18; textures[1]={X11,Y1};
vertices[verticesIndex] = C2[0];
vertices[verticesIndex + 1] = C2[1];
vertices[verticesIndex + 2] = C2[2];
verticesIndex += 3;
normals[normalsIndex] = N18[0];
normals[normalsIndex + 1] = N18[1];
normals[normalsIndex + 2] = N18[2];
normalsIndex += 3;
textures[texturesIndex] = X11;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 18; vertex[2] = C1; normals[2]=N18; textures[2]={X9,Y1};
vertices[verticesIndex] = C1[0];
vertices[verticesIndex + 1] = C1[1];
vertices[verticesIndex + 2] = C1[2];
verticesIndex += 3;
normals[normalsIndex] = N18[0];
normals[normalsIndex + 1] = N18[1];
normals[normalsIndex + 2] = N18[2];
normalsIndex += 3;
textures[texturesIndex] = X9;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 18; vertex[3] = A2; normals[3]=N18; textures[3]={X10,Y0};
vertices[verticesIndex] = A2[0];
vertices[verticesIndex + 1] = A2[1];
vertices[verticesIndex + 2] = A2[2];
verticesIndex += 3;
normals[normalsIndex] = N18[0];
normals[normalsIndex + 1] = N18[1];
normals[normalsIndex + 2] = N18[2];
normalsIndex += 3;
textures[texturesIndex] = X10;
textures[texturesIndex + 1] = Y0;
texturesIndex += 2;
// face 19; vertex[1] = C2; normals[1]=N19; textures[1]={X1,Y1};
vertices[verticesIndex] = C2[0];
vertices[verticesIndex + 1] = C2[1];
vertices[verticesIndex + 2] = C2[2];
verticesIndex += 3;
normals[normalsIndex] = N19[0];
normals[normalsIndex + 1] = N19[1];
normals[normalsIndex + 2] = N19[2];
normalsIndex += 3;
textures[texturesIndex] = X1;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 19; vertex[2] = A2; normals[2]=N19; textures[2]={X2,Y0};
vertices[verticesIndex] = A2[0];
vertices[verticesIndex + 1] = A2[1];
vertices[verticesIndex + 2] = A2[2];
verticesIndex += 3;
normals[normalsIndex] = N19[0];
normals[normalsIndex + 1] = N19[1];
normals[normalsIndex + 2] = N19[2];
normalsIndex += 3;
textures[texturesIndex] = X2;
textures[texturesIndex + 1] = Y0;
texturesIndex += 2;
// face 19; vertex[3] = B2; normals[3]=N19; textures[3]={X3,Y1};
vertices[verticesIndex] = B2[0];
vertices[verticesIndex + 1] = B2[1];
vertices[verticesIndex + 2] = B2[2];
verticesIndex += 3;
normals[normalsIndex] = N19[0];
normals[normalsIndex + 1] = N19[1];
normals[normalsIndex + 2] = N19[2];
normalsIndex += 3;
textures[texturesIndex] = X3;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 20; vertex[1] = A2; normals[1]=N20; textures[1]={X4,Y0};
vertices[verticesIndex] = A2[0];
vertices[verticesIndex + 1] = A2[1];
vertices[verticesIndex + 2] = A2[2];
verticesIndex += 3;
normals[normalsIndex] = N20[0];
normals[normalsIndex + 1] = N20[1];
normals[normalsIndex + 2] = N20[2];
normalsIndex += 3;
textures[texturesIndex] = X4;
textures[texturesIndex + 1] = Y0;
texturesIndex += 2;
// face 20; vertex[2] = A3; normals[2]=N20; textures[2]={X5,Y1};
vertices[verticesIndex] = A3[0];
vertices[verticesIndex + 1] = A3[1];
vertices[verticesIndex + 2] = A3[2];
verticesIndex += 3;
normals[normalsIndex] = N20[0];
normals[normalsIndex + 1] = N20[1];
normals[normalsIndex + 2] = N20[2];
normalsIndex += 3;
textures[texturesIndex] = X5;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
// face 20; vertex[3] = B2; normals[3]=N20; textures[3]={X3,Y1};
vertices[verticesIndex] = B2[0];
vertices[verticesIndex + 1] = B2[1];
vertices[verticesIndex + 2] = B2[2];
verticesIndex += 3;
normals[normalsIndex] = N20[0];
normals[normalsIndex + 1] = N20[1];
normals[normalsIndex + 2] = N20[2];
normalsIndex += 3;
textures[texturesIndex] = X3;
textures[texturesIndex + 1] = Y1;
texturesIndex += 2;
for (int i = 0; i < numVertices; i++) indexes[i] = i;
InitBuffers();
}
|
El rectángulo utilizado como suelo se describe así.
#include "CGGround.h"
#include <GL/glew.h>
#include "CGFigure.h"
///
/// FUNCION: CGGround::CGGround(GLfloat l1, GLfloat l2)
///
/// PROPÓSITO: Construye un rectángulo de lados 2*l1 y 2*l2.
///
CGGround::CGGround(GLfloat l1, GLfloat l2)
{
numFaces = 2; // Number of faces
numVertices = 4; // Number of vertices
GLfloat p_normals[4][3] = {
{ 0.0f, 1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f }
};
GLfloat p_textures[4][2] = {
{ 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 1.0f, 1.0f },
{ 0.0f, 1.0f }
};
GLfloat p_vertices[4][3] = {
{ l1, 0.0f, l2 },
{ l1, 0.0f, -l2 },
{ -l1, 0.0f, -l2 },
{ -l1, 0.0f, l2 }
};
GLushort p_indexes[2][3] = {
{ 0, 1, 2 },
{ 0, 2, 3 }
};
normals = new GLfloat[numVertices * 3];
for (int i = 0; i < numVertices; i++)
for (int j = 0; j < 3; j++) normals[3 * i + j] = p_normals[i][j];
vertices = new GLfloat[numVertices * 3];
for (int i = 0; i < numVertices; i++)
for (int j = 0; j < 3; j++) vertices[3 * i + j] = p_vertices[i][j];
textures = new GLfloat[numVertices * 2];
for (int i = 0; i < numVertices; i++)
for (int j = 0; j < 2; j++) textures[2 * i + j] = p_textures[i][j];
indexes = new GLushort[numFaces * 3];
for (int i = 0; i < numFaces; i++)
for (int j = 0; j < 3; j++) indexes[3 * i + j] = p_indexes[i][j];
InitBuffers();
}
|
|
|