Capítulo perteneciente al math engine LordPakus
Hola a todos,
Bienvenidos a un nuevo capitulo del math engine.
El capitulo de hoy trata sobre la clase LPVector que es la que se encarga de almacenar un vector de cualquier tamaño y poder opera con el.
La lista de operaciones que he considerado imprescindibles son las siguientes, todas las que querais que pongamos adicionales las ponemos... a la que tengamos una lista estable de operaciones nos dedicaremos a optimizarlas con SSE.:
//Funciones anexas.
void Set(int t, float* vector); //Funcion para inicializar un vector de n elementos
void Delete(); //Función para limpiar la variable vector
void print(); //Función para imprimir el vector por la consola
//OPERACIONES DE AMULACIÓN DE RESULTADO (+=,-=,etc...), devuelven void como norma general
//Operaciones vectoriales
void operator +=(LPVector vector);
void operator -=(LPVector vector);
void sqrt_vec(); //Calculamos la raíz cuadrada de todo los elementos del vector
void normalize(); //Normaliza el vector (hace que el módulo sea 1)
//Operaciones con escalares ( sumar , restar , etc ... todo un vector por un escalar)
void operator +=(float scal);
void operator -=(float scal);
void operator *=(float scal);
void operator /=(float scal);
//OPERACIONES QUE DEVUELVEN ALGO (NO ACUMULADORES: +,-,*, etc...)
//Operaciones vectoriales que devuelven escalares
float operator ^(LPVector vector); //Operador producto escalar.
float module(); //Calcula el módulo del vector
El código se organiza en dos archivos LPVector (.cpp y .h) junto con los cambios del main para demostrar que funcionan:
main.cpp:
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un math engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/
/**************************************************************************************************/
// main.cpp : Main de nuestro MathEngine
/**************************************************************************************************/
//Include del Math engine
#include "LPMath.h"
//Delete console
//#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#include <iostream> //Usada para imprimir por consola
using namespace std;
int main (int argc, char* argv[])
{
LPVector v1,v2;
float vec1[4] = { 1.0f ,1.1f ,1.5f ,2.5f };
float vec2[4] = { 3.0f ,4.1f ,0.5f ,0.4f };
float n;
//Creamos los vectores
v1.Set(4,vec1);
v2.Set(4,vec2);
cout << "Vector 1: ";
v1.print();
cout << "\n";
cout << "Vector 2: ";
v2.print();
cout << "\n";
n = v1^v2;
cout << "Producto escalar: " << n << "\n";
n = v1.module();
cout << "Modulo vector 1: " << n << "\n";
n = v2.module();
cout << "Modulo vector 2: " << n << "\n";
v1.normalize();
n = v1.module();
cout << "Modulo vector 1 normalizado: " << n << "\n";
v2.normalize();
n = v2.module();
cout << "Modulo vector 2 normalizado: " << n << "\n";
v2 += v1;
cout << "Suma de vectores: ";
v2.print();
cout << "\n";
n = v2.module();
cout << "Modulo de suma de vectores: " << n << "\n";
v2.normalize();
n = v2.module();
cout << "Modulo de suma de vectores normalizado: " << n << "\n";
//Eliminamos los vectores
v1.Delete();
v2.Delete();
system("PAUSE");
}
LPVector.cpp
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un math engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/
#include "LPVector.h"
#include <math.h>
#include <iostream> //Usada para imprimir por consola
using namespace std;
//Constructor
LPVector::LPVector()
{
n = 0;
v = NULL;
}
//Destructor
LPVector::~LPVector()
{
//if (n)
//{
// if( v != NULL )
// free(v);
//}
}
//Funcion para inicializar un vector de n elementos
void LPVector::Set(int t, float* vector)
{
n = t; //Inicializamos el número de elementos del vector
//Creamos un vector de memoria dinámica.
v = (float*) malloc( sizeof(float) * n );
//Copiamos el vector externo en el vector interno
memcpy(v,vector,sizeof(float) * n );
}
//Función para limpiar la variable vector
void LPVector::Delete()
{
n=0;
free(v);
}
//Imprimimos el valor del vector
void LPVector::print()
{
for(int i = 0 ; i < n ; ++i)
{
cout << (float) v[i] << " ";
}
}
void LPVector::random(int t, float min, float max)
{
n = t; //Inicializamos el número de elementos del vector
//Creamos un vector de memoria dinámica.
v = (float*) malloc( sizeof(float) * n );
for(int i = 0 ; i < n ; ++i)
v[i] = (float)(rand()%(int)(max*1000 - min*1000))/1000 + min;
}
void LPVector::cross(LPVector vector)
{
//POR IMPLEMENTAR
}
void LPVector::sqrt_vec()
{
for(int i = 0 ; i < n ; ++i)
v[i] = sqrt(v[i]);
}
void LPVector::normalize()
{
//Dividimos cada componente por el módulo
*this /= this->module();
}
//Sobrecarga operador +=
void LPVector::operator +=(LPVector vector)
{
//Si las dimensiones son diferentes , tenemos un problema grave.
if (n != vector.n)
{
cout << "ERROR DIMENSIONAL ENTRE VECTORES\n";
return;
}
for(int i = 0 ; i < n ; ++i)
v[i] += vector.v[i];
}
//Sobrecarga operador -=
void LPVector::operator -=(LPVector vector)
{
//Si las dimensiones son diferentes , tenemos un problema grave.
if (n != vector.n)
{
cout << "ERROR DIMENSIONAL ENTRE VECTORES\n";
return;
}
for(int i = 0 ; i < n ; ++i)
v[i] -= vector.v[i];
}
//Sobrecarga operador +=
void LPVector::operator +=(float scal)
{
for(int i = 0 ; i < n ; ++i)
v[i] += scal;
}
//Sobrecarga operador -=
void LPVector::operator -=(float scal)
{
for(int i = 0 ; i < n ; ++i)
v[i] -= scal;
}
//Sobrecarga operador *=
void LPVector::operator *=(float scal)
{
for(int i = 0 ; i < n ; ++i)
v[i] *= scal;
}
//Sobrecarga operador /=
void LPVector::operator /=(float scal)
{
for(int i = 0 ; i < n ; ++i)
v[i] /= scal;
}
//Sobrecarga operador *= //Este operador es el que nos devolverá matrices como resultado del producto de una columna por un fila.
//Es decir, es el producto vectorial. Ya lo veremos a su momento
/*void LPVector::operator *=(LPVector vector)
{
//Si las dimensiones son diferentes , tenemos un problema grave.
if (n != vector.n)
{
cout << "ERROR DIMENSIONAL ENTRE VECTORES\n";
return;
}
for(int i = 0 ; i < n ; ++i)
v[i] += vector.v[i];
}
*/
//Sobrecarga operador ^ A partir de ahora se entederá que es el producto escalar.
float LPVector::operator ^(LPVector vector)
{
float a = 0.0;
//Si las dimensiones son diferentes , tenemos un problema grave.
if (n != vector.n)
{
cout << "ERROR DIMENSIONAL ENTRE VECTORES\n";
return 0.0;
}
for(int i = 0 ; i < n ; ++i)
a += v[i] * vector.v[i];
return a;
}
float LPVector::module()
{
float a = 0.0;
for(int i = 0 ; i < n ; ++i)
a += v[i] * v[i];
return sqrt(a);
}
float LPVector::distance(LPVector vector)
{
float a = 0.0;
float temp = 0.0;
//Si las dimensiones son diferentes , tenemos un problema grave.
if (n != vector.n)
{
cout << "ERROR DIMENSIONAL ENTRE VECTORES\n";
return (-1.0);
}
for(int i = 0 ; i < n ; ++i)
{
temp = (v[i] - vector.v[i]);
a+=temp*temp;
}
return sqrt(a);
}
LPVector.h
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un math engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/
/**************************************************************************************************/
// LPVector.h
/**************************************************************************************************/
#ifndef __LPVector__
#define __LPVector__
class LPVector
{
public:
LPVector();
~LPVector();
//Funciones anexas.
void Set(int t, float* vector); //Funcion para inicializar un vector de n elementos
void Delete(); //Función para limpiar la variable vector
void print(); //Función para imprimir el vector por la consola
void random(int t,float min, float max); //Función para rellenar de random un vector de t posiciones
//OPERACIONES DE AMULACIÓN DE RESULTADO (+=,-=,etc...), devuelven void como norma general
//Operaciones vectoriales
void operator +=(LPVector vector);
void operator -=(LPVector vector);
void cross(LPVector vector); //Calculamos el producto vectorial (cross) POR HACER
void sqrt_vec(); //Calculamos la raíz cuadrada de todo los elementos del vector
void normalize(); //Normaliza el vector (hace que el módulo sea 1)
//Operaciones con escalares ( sumar , restar , etc ... todo un vector por un escalar)
void operator +=(float scal);
void operator -=(float scal);
void operator *=(float scal);
void operator /=(float scal);
//OPERACIONES QUE DEVUELVEN ALGO (NO ACUMULADORES: +,-,*, etc...)
//Operaciones vectoriales que devuelven escalares
float operator ^(LPVector vector); //Operador producto escalar.
float module(); //Calcula el módulo del vector
float distance(LPVector vector);
public:
int n; //número de elementos del vector
float *v; //puntero a memoria dinámica
};
#endif
Cualquier otra cosa que se os ocurra que le pongamos o cualquier fallo que veais, hacedmelo llegar
Espero que os haya gustado,
Nos vemos
EDIT:
27-08-2011:Se han añadido las funciones siguientes:
- vector de randoms
- distancia entre vectores
- se deja a la espera el cross product (alguíen tiene el código y me lo quiere pasar??)
Blog de programación enfocado a estudiantes principiantes de C/C++ en español. Dispone de cursos de todos los niveles y para multitud de usos.
Entradas populares
-
Una pregunta que me hacen en muchas ocasiones es ¿¿qué significa %2?? La respuesta tiene dos acepciones en función de si lo estamos u...
-
<< Ejemplo anterior Artículos Relacionados Ejemplo siguiente >> Hola a todos, ASCII Art es el hecho de hacer di...
-
Articulo perteneciente a : Referencias de programación Hola a todos Os pongo una aportación que a más de uno le irá bien, un resumen de ...
-
<< Ejemplo anterior Artículos Relacionados Ejemplo siguiente >> Hola a todos, El ejercicio de hoy se basa en c...
-
Capítulo perteneciente al tutorial de opengl desde cero Hola a todos, Este capítulo tal vez es de lo más complicados de la teoría necesa...
-
<< Capítulo anterior Artículos Relacionados Capítulo siguiente >> Hola a todos, Este tutorial intenta ser e...
-
<< Capítulo anterior Artículos Relacionados Capítulo siguiente >> Hola a todos... Un compañero vuestro ha...
-
Hola a todos... He aquí la primera entrega "Como crear tu propio motor de videojuegos y no morir en el intento". Antes que nada ...
-
<< Capítulo anterior Artículos Relacionados Capítulo siguiente >> El c apitulo de hoy trata sobre las instrucc...
-
Hola a todos Ya que he recibido un par de mails pidiéndome información sobre SEO, os adjunto unos cuantos trucos que he ido aprendiendo du...
El math engine entiendo que es un proyecto aparte del game engine, aunque ¿siempre te podrás apoyar en el posteriormente no?
ResponderEliminarAlgunas operaciones que uso yo y que creo que no están son:
-el producto vectorial(cross)
-la distancia entre dos vectores(la resta i luego el modulo)
-vector de randoms.
También me gustaría saber porque el game engine no lo haces 3d ya que normalmente llama más la atención y creo que captarías mas gente.
Igualmente yo seguiré mirando todos tus post, ya que aparte de interesantes creo que es muy portable a 3D lo que haces.
Saludos!!
26 de agosto de 2011 15:42
Si, el math engine es un proyecto aparte del game engine y la idea es que en un futuro se puedan entremezclar o aprovechar ciertos códigos del uno en el otro.
ResponderEliminarEl objetivo final no es mas que una excusa de poder hacer cosillas de SSE y paralelización (que siempre me ha gustado pero que en el game engine es complicado de implementar).
Las tres funciones que me propones me parecen buenas... en breve las implemento a ver si te parecen bien.
El game engine es 2D/3D lo que por motivos de tiempo solo me he podido poner con el tema de 2D. De hecho, aquí : http://lordpakus.blogspot.com/2011/06/gameengine-capitulo-8.html y aquí: http://lordpakus.blogspot.com/2011/06/gameengine-capitulo-3.html,podrás ver cosillas de 3D dentro del motor.
Espero que en breve pueda acabar lo que tenga a medias de 2D y me pueda poner más a fondo con el 3D.
Gracias por tu apoyo y dedicación
Nos vemos
Buenas LordPakus, tienes un pequeño error que se puede subsanar muy fácilmente. En el método:
ResponderEliminarvoid operator +=(LPVector vector);
Lo que estás haciendo es pasar el parámetro "vector" por copia, osea, que cada vez que llamas al operador += estás copiando el parámetro. Como es de solo lectura (debería), puedes pasarlo por referencia, ¿no? Quedaría así:
void operator +=(const LPVector& vector);
El resto de tu código queda inalterado. Un saludo!
Pues tienes toda la razón, he hecho el fallo del novato. Thenkius, el tema de la sobrecarga de operadores aún no lo tengo controlado al 100% :D.
ResponderEliminarPor ahora no lo toco por que estoy metido con el game engine... si vierais que subo otra versión del math engine sin arreglar esto, caneadme :D.
Muchisimas gracias por tu aportación, por mi mismo este fallo se me habría pasado seguro.