summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Suhren <suhren.stefan@fh-swf.de>2015-11-03 10:07:31 +0100
committerStefan Suhren <suhren.stefan@fh-swf.de>2015-11-03 10:07:31 +0100
commitdfc13e1b2c7f83b386cb7fb4e62d46b44c6ba5e4 (patch)
tree870a3435403bf913332668551320c5f22006e373
parentf229dfa705b356b1a557ffccfec779642fe0c3f5 (diff)
downloadMultimedia-dfc13e1b2c7f83b386cb7fb4e62d46b44c6ba5e4.tar.gz
Multimedia-dfc13e1b2c7f83b386cb7fb4e62d46b44c6ba5e4.zip
Add GLBody class
-rw-r--r--MM_2015_Base_Project.pro8
-rw-r--r--src/glbody.cpp272
-rw-r--r--src/glbody.h225
3 files changed, 502 insertions, 3 deletions
diff --git a/MM_2015_Base_Project.pro b/MM_2015_Base_Project.pro
index 5caf8e2..051b639 100644
--- a/MM_2015_Base_Project.pro
+++ b/MM_2015_Base_Project.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
-QT += qml quick widgets
+QT += qml quick widgets opengl
SOURCES += \
src/main.cpp \
@@ -9,7 +9,8 @@ SOURCES += \
src/glitem.cpp \
src/glpoint.cpp \
src/shaderdebugger.cpp \
- src/mmscene.cpp
+ src/mmscene.cpp \
+ src/glbody.cpp
HEADERS += \
src/glcolorrgba.h \
@@ -18,7 +19,8 @@ HEADERS += \
src/glitem.h \
src/glpoint.h \
src/shaderdebugger.h \
- src/mmscene.h
+ src/mmscene.h \
+ src/glbody.h
RESOURCES += qml.qrc \
shaders.qrc
diff --git a/src/glbody.cpp b/src/glbody.cpp
new file mode 100644
index 0000000..b1be10f
--- /dev/null
+++ b/src/glbody.cpp
@@ -0,0 +1,272 @@
+/***************************************************************************
+ * Copyright (C) 2008, 2012 by Walter Roth *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "glbody.h"
+
+#include <QImage>
+#include <QtOpenGL/QGLWidget>
+#include <QFile>
+
+/**Constructor does NOT create the surface.
+*/
+GLBody::GLBody(float radius, const GLColorRgba &color, const QString textureFile)
+{
+ m_surfaceIsValid = false;
+ this->m_textureFile = textureFile; //DO NOT call setTextureFile here! It needs a current context!
+ m_texture = 0;
+ this->m_color = color;
+ m_specularColor = cl_White;
+ m_shininess = 50;
+ this->m_radius = radius;
+ m_drawingMode = GL_TRIANGLES;
+ m_selected = false;
+ m_points = NULL;
+ m_ownPointsContainer = false;
+ m_indices = NULL;
+ m_ownIndexContainer = false;
+ m_firstPoint = 0;
+ m_nextPoint = 0;
+ m_firstIndex = 0;
+ m_nextIndex = 0;
+}
+
+/** Destructor
+ */
+GLBody::~GLBody()
+{
+ if(m_texture != 0){//delete an existing texture
+ glDeleteTextures(1, &m_texture);
+ m_texture = 0;
+ }
+ if(m_ownPointsContainer)
+ delete m_points;
+ if(m_ownIndexContainer)
+ delete m_indices;
+}
+
+/** Creates the surface. Should be called, when a GL engine is already running.
+ * Is called automatically by draw, if required.
+ */
+void GLBody::makeSurface(QVector<GLPoint> *pointContainer, QVector<GLshort> * indexContainer)
+{
+ if(pointContainer == NULL)
+ {
+ m_points = new QVector<GLPoint>();
+ m_ownPointsContainer = true;
+ }
+ else m_points = pointContainer;
+ if(indexContainer == NULL)
+ {
+ m_indices = new QVector<GLshort>();
+ m_ownIndexContainer = true;
+ }
+ else m_indices = indexContainer;
+ setTexture(m_textureFile);
+ m_surfaceIsValid = true;
+}
+
+void GLBody::calculateDrawMatrix()
+{
+ m_drawMatrix = m_transformationMatrix;
+}
+
+/** Draws the surface and calls makeSurface if required.
+ * Needs an active (made current) GL-Context.
+ */
+void GLBody::draw(GLESRenderer * renderer){
+ if(!m_surfaceIsValid)
+ makeSurface(NULL, NULL);
+ if(!m_points || m_points->size() == 0) //check for existing points
+ {
+ qDebug() << "GLESBody::draw ERROR: No points!";
+ return;
+ }
+ int stride = sizeof(GLPoint);
+ bool oldTextureEnabled = false;
+
+ //set colors
+ renderer->setAmbientAndDiffuseColor(m_color);
+
+ //enable required arrays
+ renderer->activateAttributeArray(GLESRenderer::VERTEX_LOCATION,
+ (*m_points)[0].vertexPointer(), stride);
+ if (renderer->isLightingEnabled())
+ renderer->activateAttributeArray(GLESRenderer::NORMAL_LOCATION,
+ (*m_points)[0].normalPointer(), stride);
+ if(m_texture != 0){
+ glActiveTexture(GL_TEXTURE0); //use texture unit 0
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+ oldTextureEnabled = renderer->isTextureEnabled();
+ renderer->setTextureEnabled(true);
+ }
+ else renderer->setTextureEnabled(false);
+ renderer->activateAttributeArray(GLESRenderer::TEXCOORD_LOCATION,
+ (*m_points)[0].texCoordPointer(), stride);
+ renderer->activateAttributeArray(GLESRenderer::COLOR_LOCATION,
+ (*m_points)[0].colorPointer(), stride);
+
+// for(int i = 0; i < indices.count(); i++)
+// points[indices[i]].debugOutput("Point" +QString::number(i) + ":" + QString::number(indices[i]) + " ");
+
+ calculateDrawMatrix();
+ renderer->pushMvMatrix();
+ renderer->addTransformation(m_drawMatrix);
+ if(m_firstIndex >= 0 && m_nextIndex > 0)
+ glDrawElements(m_drawingMode, m_nextIndex -m_firstIndex,
+ GL_UNSIGNED_SHORT, &m_indices->data()[m_firstIndex]);
+ else
+ glDrawArrays(m_drawingMode, m_firstPoint, m_nextPoint - m_firstPoint);
+
+ if(isSelected())
+ {
+ bool lightingOn = renderer->isLightingEnabled();
+ if(lightingOn)
+ renderer->setLightingEnabled(false);
+ GLColorRgba pointColor(m_color.inverted());
+ renderer->setAmbientAndDiffuseColor(pointColor);
+#ifdef GLES
+ glDrawArrays(GL_LINES, 0, m_points->size());
+#else
+ int oldPointSize = renderer->getPointSize();
+ renderer->setPointSize(5);
+ glDrawArrays(GL_POINTS, 0, m_points->size());
+ renderer->setPointSize(oldPointSize);
+#endif
+ if(lightingOn)
+ renderer->setLightingEnabled(true);
+ }
+ //disable arrays
+ renderer->disableAttributeArrays();
+ if(m_texture != 0)
+ renderer->setTextureEnabled(oldTextureEnabled);
+ renderer->popMvMatrix();
+}
+
+/** Set texture from file. Returns true on success
+ */
+bool GLBody::setTexture(const QString & textureFile){
+ if(textureFile == "")
+ return false;
+
+ QImage image;
+ if(m_texture != 0){//delete an existing texture
+ glDeleteTextures(1, &m_texture);
+ m_texture = 0;
+ }
+
+ qDebug("%s", QString("Loading Texture:" + textureFile).toLatin1().data());
+ if (image.load(textureFile)){
+ //we have got a valid image, give it to GL
+ if (image.format() != QImage::Format_ARGB32) //make shure, that we have 32bit colors
+ image = image.convertToFormat(QImage::Format_ARGB32);
+ image = QGLWidget::convertToGLFormat(image);
+ glGenTextures(1, &m_texture); // get a number (name) for the new texture and create a new texture object
+ if(m_texture == 0) //GL does not work properly
+ {
+ qDebug("Could not create texture object. GL-engine not yet active?");
+ return false;
+ }
+ glBindTexture(GL_TEXTURE_2D, m_texture); // Bind texture object to OpenGL.
+ //All following calls work on the bound texture object.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ GL_NEAREST); //use values of nearest pixel for magnification.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_NEAREST); // use nearest pixel minimization.
+ // Replace with other values if aliasing occurs. See doc for GL_TEXTURE_MAG_FILTER
+
+ //The next call copies the pixel data from the QImage, which is no longer needed afterwards.
+ glTexImage2D(GL_TEXTURE_2D,
+ 0, // use only one resolution
+ GL_RGBA, //internal format to use for the texture
+ image.width(),
+ image.height(),
+ 0, //width of the texture border, may be 0 or 1
+ GL_RGBA, //format of the QImage
+ GL_UNSIGNED_BYTE, // QImage uses values from 0 to 255 for R,G,B,A
+ image.bits() //pointer to the first pixel in image
+ );
+ glBindTexture(GL_TEXTURE_2D, 0); // finally remove texture from OpenGL machine
+ return true;
+ }
+ else{ //loading failed
+ qDebug("Texture loading failed");
+ return false;
+ }
+}
+
+/** Set texture file.
+ */
+bool GLBody::setTextureFile(const QString & textureFile){
+ this->m_textureFile = textureFile;
+ if(m_texture != 0) //we have an activated texture already. Replace it.
+ return setTexture(textureFile);
+ else return true; //texture is not yet active, leave it as it is
+}
+
+/**
+ * Moves the body by adding vMove to all vertices.
+ */
+void GLBody::move(QVector3D vMove)
+{
+ for(int i = m_firstPoint; i < m_nextPoint; i++)
+ (*m_points)[i].move(vMove);
+ m_center = m_center + vMove;
+}
+
+/**
+ * Returns true, when line through p1 and p2 intersects body shpere
+ */
+bool GLBody::isHit(QVector3D p1, QVector3D p2)
+{
+ QVector3D lineVector = p2 - p1;
+ double area = QVector3D::crossProduct((m_center - p1), lineVector).length();
+ double distance = area / lineVector.length();
+ //qDebug("Radius: %f", radius);
+ return distance < m_radius;
+}
+
+/*
+ * Returns true, if enclosing spheres touch or intersect
+ */
+bool GLBody::spheresAreColliding(const GLBody *other)
+{
+ bool result;
+ if(this == other)
+ result = false;
+ else
+ {
+ double distance = (m_center - other->m_center).length();
+ result = (m_radius + other->m_radius) >= distance;
+ }
+ if(result)
+ return true; //hook for debugger
+ else return false; //hook for debugger
+}
+
+/**
+ * Set new center and invalidate surface.
+ */
+void GLBody::setCenter(const QVector3D & newVal)
+{
+ m_center = newVal;
+ m_surfaceIsValid = false;
+}
+
+
diff --git a/src/glbody.h b/src/glbody.h
new file mode 100644
index 0000000..1bbaa82
--- /dev/null
+++ b/src/glbody.h
@@ -0,0 +1,225 @@
+/***************************************************************************
+ * Copyright (C) 2008, 2012 by Walter Roth *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef GLBODY_H
+#define GLBODY_H
+
+#include <QVector>
+
+#include "glesrenderer.h"
+#include "glpoint.h"
+#include "gldefines.h"
+
+/**
+ * \brief A 3D body that uses a GLESRenderer for drawing and GLPoint objects for defining its surface.
+ *
+ * Overwrite makeSurface() in subclasses to create the GLPoints that form the surface.
+ * Set drawingMode to GL_LINE_STRIP or GL_LINES for debugging the surface. Default is GL_TRIANGLE_STRIP.
+ * Vertices and indices may be stored in external or internal containers. If GlBody::makeSurface is called
+ * with pointers to existing containers, these will be used. Otherwise GlBody::makeSurface will create new
+ * containers. Only in this case, the destructor will delete the containers.
+ * Overwrite draw() if you do need special drawing procedures.
+ */
+class GLBody{
+public:
+ /**Constructor does NOT create the surface.
+ */
+ GLBody(float m_radius = 1.0, const GLColorRgba & m_color = GLColorRgba::clBlue, const QString m_textureFile = "");
+
+ /** Destructor will delete created containers.
+ */
+ virtual ~GLBody();
+
+ /** Creates the surface. Should be called, when a GL engine is already running.
+ * To be overwritten by subclasses. GLESBody::createSurface should be called at the beginning
+ * of overriding functions. It will create the pointContainer, if none is supplied
+ * Is called automatically by draw, if required.
+ * MUST NOT be called without a working GL engine.
+ *
+ * @param pointContainer The container for the geometry data. If NULL, a new one is created.
+ * @param indexContainer The container for the index data. If NULL, a new one is created.
+ * Created containers will be deleted by destructor.
+ */
+ virtual void makeSurface(QVector<GLPoint> * pointContainer, QVector<GLshort> * indexContainer);
+
+
+ /**
+ * @brief calculateDrawMatrix Virtual function to calculate the final matrix to be used for drawing.
+ * May be overwritten in subclasses. GLBody::calculateDrawMatrix simply copies m_transformationMatrix.
+ */
+ virtual void calculateDrawMatrix();
+ /** Draws the surface and calls makeSurface if required.
+ * Needs an active (made current) GL-Context.
+ */
+ virtual void draw(GLESRenderer * renderer);
+
+ /**
+ * Returns true, when line through p1 and p2 intersects body sphere
+ * To be overwritten by subclasses.
+ */
+ virtual bool isHit(QVector3D p1, QVector3D p2);
+
+ /**
+ * Returns true, if enclosing spheres touch or intersect
+ */
+ virtual bool spheresAreColliding(const GLBody * other);
+
+ /** Set texture from file. Returns true on success. Needs a current OpenGL context.
+ */
+ bool setTexture(const QString & m_textureFile);
+
+ /** Set texture file. Needs a current OpenGL context.
+ */
+ bool setTextureFile(const QString & m_textureFile);
+
+ /**
+ * Moves the body by adding vMove to all vertices.
+ */
+ void move(QVector3D vMove);
+ /**
+ * Simple gettters
+ */
+ bool isSelected(){return m_selected;}
+ const QVector3D & getCenter()const{return m_center;}
+
+ /**Simple setters
+ */
+ void setColor(const GLColorRgba & newVal){m_color = newVal;}
+ void setSpecularColor(const GLColorRgba & newVal){m_specularColor = newVal;}
+ void setShininess(int newVal){m_shininess = newVal;}
+ void setSelected(bool newVal){m_selected = newVal;}
+ void setDrawingMode(GLint newVal){m_drawingMode = newVal;}
+ void setTransformation(const QMatrix4x4 & transformation){m_transformationMatrix = transformation;}
+
+ /**
+ * Set new center and invalidate surface.
+ */
+ void setCenter(const QVector3D & newVal);
+
+ /**
+ *Simple getters
+ */
+ const GLColorRgba & getColor()const{return m_color;}
+ const QMatrix4x4 & getTransformation()const{return m_transformationMatrix;}
+ double getRadius()const{return m_radius;}
+ void setScale(double scale){m_scale = scale;}
+
+protected:
+ /**
+ * The center of the enclosing sphere
+ */
+ QVector3D m_center;
+
+ /**
+ * The radius of the enclosing sphere
+ */
+ GLfloat m_radius;
+
+ /**
+ * The mode to be passed to glDrawArrays or glDrawElements e.g. GL_TRIANGLES, GL_TRIANGLE_STRIP
+ */
+ GLint m_drawingMode;
+
+ /** The array of points defining the surface.
+ * This *may be* a container not owned by this body.
+ */
+ QVector <GLPoint> * m_points;
+
+ /**
+ * @brief ownPointsContainer Set this Flag, if points container was created by this body.
+ */
+ bool m_ownPointsContainer;
+
+ /**
+ * @brief firstPoint The firstPoint for this body
+ */
+ int m_firstPoint;
+
+ /**
+ * @brief lastPoint The next point for this body. ( last point +1)
+ */
+ int m_nextPoint;
+
+ /** The array with the indices. May be left empty.
+ */
+ QVector <GLshort> * m_indices;
+
+ /**
+ * @brief ownPointsContainer Set this Flag, if points container was created by this body.
+ */
+ bool m_ownIndexContainer;
+
+ /**
+ * @brief startIndex The first index for this body
+ */
+ int m_firstIndex;
+
+ /**
+ * @brief indexCount The next index for this body. (last index + 1)
+ */
+ int m_nextIndex;
+
+ /** The flag for a valid surface.
+ */
+ bool m_surfaceIsValid;
+
+ /** The texture to be used.
+ */
+ GLuint m_texture;
+
+ /** The tetxure file.
+ */
+ QString m_textureFile;
+
+ /** The diffuse and ambient color for the body.
+ */
+ GLColorRgba m_color;
+
+ /**
+ * The specular color
+ */
+ GLColorRgba m_specularColor;
+
+ /**
+ * Shininess for specular color
+ */
+ int m_shininess;
+
+ /**
+ * Flag for selected mode.
+ */
+ bool m_selected;
+ /**
+ * This matrix holds the basic transformation for the body and
+ * should not be modified after first setting.
+ */
+ QMatrix4x4 m_transformationMatrix;
+
+ /**
+ * @brief m_drawMatrix
+ * This matrix is multiplied with the modelview matrix prior to
+ * rendering the body.
+ */
+ QMatrix4x4 m_drawMatrix;
+ /**
+ * @brief m_scale
+ */
+ double m_scale; //meters per logical unit
+};
+
+#endif