Use the opengl-framework library for the examples

This commit is contained in:
Daniel Chappuis 2013-04-14 21:32:40 +02:00
parent f84382bbbe
commit a1bd7f7be9
78 changed files with 33401 additions and 289 deletions

View File

@ -35,7 +35,7 @@ ADD_LIBRARY (
# If we need to compile the examples
IF (COMPILE_EXAMPLES)
add_subdirectory(examples/fallingcubes)
add_subdirectory(examples/)
ENDIF (COMPILE_EXAMPLES)
# If we need to compile the tests

5
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
# Minimum cmake version required
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
add_subdirectory(opengl-framework/)
add_subdirectory(fallingcubes/)

View File

@ -26,38 +26,155 @@
// Libraries
#include "Box.h"
// Use the ReactPhysics3D namespace
using namespace reactphysics3d;
// Macros
#define MEMBER_OFFSET(s,m) ((char *)NULL + (offsetof(s,m)))
// Initialize static variables
openglframework::VertexBufferObject Box::mVBOVertices(GL_ARRAY_BUFFER);
openglframework::VertexBufferObject Box::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER);
bool Box::areVBOsCreated = false;
VertexData Box::mCubeVertices[8] = {
{openglframework::Vector3(1,1,1),openglframework::Vector3(1,1,1),openglframework::Color(0,0,1,1)},
{openglframework::Vector3(-1,1,1),openglframework::Vector3(-1,1,1),openglframework::Color(0,0,1,1)},
{openglframework::Vector3(-1,-1,1),openglframework::Vector3(-1,-1,1),openglframework::Color(0,0,1,1)},
{openglframework::Vector3(1,-1,1),openglframework::Vector3(1,-1,1),openglframework::Color(0,0,1,1)},
{openglframework::Vector3(1,-1,-1),openglframework::Vector3(1,-1,-1),openglframework::Color(0,0,1,1)},
{openglframework::Vector3(-1,-1,-1),openglframework::Vector3(-1,-1,-1),openglframework::Color(0,0,1,1)},
{openglframework::Vector3(-1,1,-1),openglframework::Vector3(-1,1,-1),openglframework::Color(0,0,1,1)},
{openglframework::Vector3(1,1,-1),openglframework::Vector3(1,1,-1),openglframework::Color(0,0,1,1)}
};
GLuint Box::mCubeIndices[36] = { 0, 1, 2,
2, 3, 0,
7, 4, 5,
5, 6, 7,
6, 5, 2,
2, 1, 6,
7, 0, 3,
3, 4, 7,
7, 6, 1,
1, 0, 7,
3, 2, 5,
5, 4, 3};
// Constructor
Box::Box(double size, RigidBody* rigidBody) {
mSize = size;
mRigidBody = rigidBody;
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position,
float mass, reactphysics3d::DynamicsWorld* dynamicsWorld)
: openglframework::Object3D() {
// Initialize the size of the box
mSize[0] = size.x * 0.5f;
mSize[1] = size.y * 0.5f;
mSize[2] = size.z * 0.5f;
// Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4(mSize[0], 0, 0, 0,
0, mSize[1], 0, 0,
0, 0, mSize[2], 0,
0, 0, 0, 1);
// Initialize the position where the cube will be rendered
translateWorld(position);
// Create the collision shape for the rigid body (box shape)
mCollisionShape = new rp3d::BoxShape(rp3d::Vector3(mSize[0], mSize[1], mSize[2]));
// Compute the inertia tensor of the body using its collision shape
rp3d::Matrix3x3 inertiaTensor;
mCollisionShape->computeLocalInertiaTensor(inertiaTensor, mass);
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the cube in the dynamics world
mRigidBody = dynamicsWorld->createRigidBody(transform, mass, inertiaTensor, mCollisionShape);
// If the Vertex Buffer object has not been created yet
if (!areVBOsCreated) {
// Create the Vertex Buffer
createVBO();
}
}
// Destructor
Box::~Box() {
// Destroy the collision shape
delete mCollisionShape;
}
// Draw the box
void Box::draw() const {
// Render the cube at the correct position and with the correct orientation
void Box::render(openglframework::Shader& shader) {
// Bind the shader
shader.bind();
// Set the model to World matrix
shader.setMatrix4x4Uniform("modelToWorldMatrix", mTransformMatrix);
// Bind the vertices VBO
mVBOVertices.bind();
// Enable the vertex, normal and color arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// Set the arrays pointers
glVertexPointer(3, GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, position));
glNormalPointer(GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, normal));
glColorPointer(3, GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, color));
// Bind the indices VBO
mVBOIndices.bind();
// Draw the geometry of the box
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (char*)NULL);
// Unbind the VBOs
mVBOVertices.unbind();
mVBOIndices.unbind();
// Disable the arrays
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// Unbind the shader
shader.unbind();
}
// Update the transform matrix of the box
void Box::updateTransform() {
// Get the interpolated transform of the rigid body
Transform transform = mRigidBody->getInterpolatedTransform();
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Get the corresponding OpenGL matrix
float openGLMatrix[16];
transform.getOpenGLMatrix(openGLMatrix);
// Compute the transform used for rendering the box
float matrix[16];
transform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
glPushMatrix();
// Multiply by the OpenGL transform matrix
glMultMatrixf(openGLMatrix);
// Draw the cube
glutSolidCube(mSize);
glPopMatrix();
// Apply the scaling matrix to have the correct box dimensions
mTransformMatrix = newMatrix * mScalingMatrix;
}
// Create the Vertex Buffer Objects used to render to box with OpenGL.
/// We create two VBOs (one for vertices and one for indices) to render all the boxes
/// in the simulation.
void Box::createVBO() {
// Create the VBOs
mVBOVertices.create();
mVBOIndices.create();
// Copy the data into the VBOs
mVBOVertices.copyDataIntoVBO(sizeof(mCubeVertices), mCubeVertices, GL_STATIC_DRAW);
mVBOIndices.copyDataIntoVBO(sizeof(mCubeIndices), mCubeIndices, GL_STATIC_DRAW);
areVBOsCreated = true;
}

View File

@ -23,60 +23,89 @@
* *
********************************************************************************/
// Libraries
#include <reactphysics3d.h>
#ifdef APPLE_OS
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif
#ifdef USE_FREEGLUT
#ifdef APPLE_OS
#include <OpenGL/freeglut.h>
#else
#include <GL/freeglut.h>
#endif
#else
#ifdef APPLE_OS
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#endif
#ifndef BOX_H
#define BOX_H
#define BOX_H
/// This class represents a cube box
class Box {
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
private:
// Structure VertexData
struct VertexData {
/// Size of the box
double mSize;
/// Vertex position
openglframework::Vector3 position;
/// Pointer to the rigid body associated to the box
/// Vertex normal
openglframework::Vector3 normal;
// Vertex color
openglframework::Color color;
};
// Class Box
class Box : public openglframework::Object3D {
private :
// -------------------- Attributes -------------------- //
/// Size of each side of the box
float mSize[3];
/// Rigid body used to simulate the dynamics of the box
rp3d::RigidBody* mRigidBody;
public:
/// Collision shape of the rigid body
rp3d::BoxShape* mCollisionShape;
/// Scaling matrix (applied to a cube to obtain the correct box dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Vertex Buffer Object for the vertices data used to render the box with OpenGL
static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the indices used to render the box with OpenGL
static openglframework::VertexBufferObject mVBOIndices;
/// Vertex data for each vertex of the cube (used to render the box)
static VertexData mCubeVertices[8];
/// Indices of the cube (used to render the box)
static GLuint mCubeIndices[36];
/// True if the VBOs have already been created
static bool areVBOsCreated;
// -------------------- Methods -------------------- //
/// Create a Vertex Buffer Object to render to box with OpenGL
static void createVBO();
public :
// -------------------- Methods -------------------- //
/// Constructor
Box(double size, rp3d::RigidBody* rigidBody);
Box(const openglframework::Vector3& size, const openglframework::Vector3& position,
float mass, rp3d::DynamicsWorld* dynamicsWorld);
/// Destructor
~Box();
/// Return the pointer to the rigid body
rp3d::RigidBody* getRigidBodyPointer() const;
/// Return a pointer to the rigid body of the box
rp3d::RigidBody* getRigidBody();
/// Draw the box
void draw() const;
/// Update the transform matrix of the box
void updateTransform();
/// Render the cube at the correct position and with the correct orientation
void render(openglframework::Shader& shader);
};
// Return the pointer to the rigid body
inline rp3d::RigidBody* Box::getRigidBodyPointer() const {
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Box::getRigidBody() {
return mRigidBody;
}
#endif

49
examples/fallingcubes/CMakeLists.txt Executable file → Normal file
View File

@ -4,53 +4,14 @@ cmake_minimum_required(VERSION 2.6)
# Project configuration
PROJECT(FallingCubes)
# Find Glut or Freeglut
FIND_PACKAGE(GLUT)
if (NOT GLUT_FOUND)
# Find the Freeglut library
FIND_PATH(FREEGLUT_INCLUDE_DIR NAMES GL/freeglut.h
/usr/include/GL
)
FIND_LIBRARY(FREEGLUT_LIBRARY NAMES freeglut glut)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FREEGLUT DEFAULT_MSG FREEGLUT_LIBRARY FREEGLUT_INCLUDE_DIR)
IF(FREEGLUT_FOUND)
MESSAGE("Freeglut found")
SET(FREEGLUT_LIBRARIES ${FREEGLUT_LIBRARY})
SET(FREEGLUT_INCLUDE_DIRS ${FREEGLUT_INCLUDE_DIR})
else()
MESSAGE("Freeglut not found (required to build the examples)")
SET(FREEGLUT_LIBRARIES)
SET(FREEGLUT_INCLUDE_DIRS)
endif()
endif()
# Find OpenGL
FIND_PACKAGE(OpenGL)
if(OPENGL_FOUND)
MESSAGE("OpenGL found")
else()
MESSAGE("OpenGL not found")
endif()
# Copy the shaders used for the demo into the build directory
FILE(COPY "../opengl-framework/src/shaders/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/")
# Headers
if(GLUT_FOUND)
INCLUDE_DIRECTORIES(${REACTPHYSICS3D_SOURCE_DIR}/src ${GLUT_INCLUDE_DIR})
elseif(FREEGLUT_FOUND)
INCLUDE_DIRECTORIES(${REACTPHYSICS3D_SOURCE_DIR}/src ${FREEGLUT_INCLUDE_DIRS})
endif()
# Definitions
if (FREEGLUT_FOUND)
ADD_DEFINITIONS(-DUSE_FREEGLUT)
endif()
INCLUDE_DIRECTORIES("../opengl-framework/src/")
# Create the example executable using the
# compiled reactphysics3d static library
ADD_EXECUTABLE(fallingcubes main.cpp Box.cpp Box.h)
ADD_EXECUTABLE(fallingcubes main.cpp Scene.cpp Scene.h Box.cpp Box.h)
if(GLUT_FOUND)
TARGET_LINK_LIBRARIES(fallingcubes reactphysics3d ${GLUT_LIBRARY} ${OPENGL_LIBRARY})
elseif(FREEGLUT_FOUND)
TARGET_LINK_LIBRARIES(fallingcubes reactphysics3d ${FREEGLUT_LIBRARY} ${OPENGL_LIBRARY})
endif()
TARGET_LINK_LIBRARIES(fallingcubes reactphysics3d openglframework)

View File

@ -0,0 +1,169 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2010-2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "Scene.h"
// Namespaces
using namespace openglframework;
// Constructor
Scene::Scene(GlutViewer* viewer) : mViewer(viewer), mLight0(0),
mPhongShader("shaders/phong.vert",
"shaders/phong.frag"){
// Move the light 0
mLight0.translateWorld(Vector3(7, 15, 15));
// Compute the radius and the center of the scene
float radius = 10.0f;
openglframework::Vector3 center(0, 5, 0);
// Set the center of the scene
mViewer->setScenePosition(center, radius);
// Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, -9.81, 0);
// Time step for the physics simulation
rp3d::decimal timeStep = 1.0f / 80.0f;
// Create the dynamics world for the physics simulation
mDynamicsWorld = new rp3d::DynamicsWorld(gravity, timeStep);
// Create all the cubes of the scene
for (int i=0; i<NB_BOXES; i++) {
// Position of the cubes
openglframework::Vector3 position(0, 5 + i * (BOX_SIZE.y + 0.5f), 0);
// Create a cube and a corresponding rigid in the dynamics world
Box* cube = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld);
// The box is a moving rigid body
cube->getRigidBody()->setIsMotionEnabled(true);
// Set the bouncing factor of the box
cube->getRigidBody()->setRestitution(0.4);
// Add the box the list of box in the scene
mBoxes.push_back(cube);
}
// Create the floor
openglframework::Vector3 floorPosition(0, 0, 0);
mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld);
// The floor must be a non-moving rigid body
mFloor->getRigidBody()->setIsMotionEnabled(false);
// Set the bouncing factor of the floor
mFloor->getRigidBody()->setRestitution(0.3);
// Start the simulation
mDynamicsWorld->start();
}
// Destructor
Scene::~Scene() {
// Stop the physics simulation
mDynamicsWorld->stop();
// Destroy the shader
mPhongShader.destroy();
// Destroy all the cubes of the scene
for (std::vector<Box*>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) {
// Destroy the corresponding rigid body from the dynamics world
mDynamicsWorld->destroyRigidBody((*it)->getRigidBody());
// Destroy the cube
delete (*it);
}
// Destroy the rigid body of the floor
mDynamicsWorld->destroyRigidBody(mFloor->getRigidBody());
// Destroy the floor
delete mFloor;
// Destroy the dynamics world
delete mDynamicsWorld;
}
// Take a step for the simulation
void Scene::simulate() {
// Take a simulation step
mDynamicsWorld->update();
// Update the position and orientation of the boxes
for (std::vector<Box*>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
}
mFloor->updateTransform();
}
// Render the scene
void Scene::render() {
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
// Bind the shader
mPhongShader.bind();
// Set the variables of the shader
const Camera& camera = mViewer->getCamera();
Matrix4 matrixIdentity;
matrixIdentity.setToIdentity();
mPhongShader.setVector3Uniform("cameraWorldPosition", mViewer->getCamera().getOrigin());
mPhongShader.setMatrix4x4Uniform("worldToCameraMatrix", camera.getTransformMatrix().getInverse());
mPhongShader.setMatrix4x4Uniform("projectionMatrix", camera.getProjectionMatrix());
mPhongShader.setVector3Uniform("lightWorldPosition", mLight0.getOrigin());
mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f));
Color& diffCol = mLight0.getDiffuseColor();
Color& specCol = mLight0.getSpecularColor();
mPhongShader.setVector3Uniform("lightDiffuseColor", Vector3(diffCol.r, diffCol.g, diffCol.b));
mPhongShader.setVector3Uniform("lightSpecularColor", Vector3(specCol.r, specCol.g, specCol.b));
mPhongShader.setFloatUniform("shininess", 60.0f);
// Render all the cubes of the scene
for (std::vector<Box*>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) {
(*it)->render(mPhongShader);
}
// Render the floor
mFloor->render(mPhongShader);
// Unbind the shader
mPhongShader.unbind();
}

View File

@ -0,0 +1,83 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2010-2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef SCENE_H
#define SCENE_H
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
#include "Box.h"
// Constants
const int NB_BOXES = 10; // Number of boxes in the scene
const openglframework::Vector3 BOX_SIZE(2, 2, 2); // Box dimensions in meters
const openglframework::Vector3 FLOOR_SIZE(20, 0.5f, 20); // Floor dimensions in meters
const float BOX_MASS = 1.0f; // Box mass in kilograms
const float FLOOR_MASS = 100.0f; // Floor mass in kilograms
// Class Scene
class Scene {
private :
// -------------------- Attributes -------------------- //
// Pointer to the viewer
openglframework::GlutViewer* mViewer;
// Light 0
openglframework::Light mLight0;
// Phong shader
openglframework::Shader mPhongShader;
/// All the boxes of the scene
std::vector<Box*> mBoxes;
/// Box for the floor
Box* mFloor;
/// Dynamics world used for the physics simulation
rp3d::DynamicsWorld* mDynamicsWorld;
public:
// -------------------- Methods -------------------- //
/// Constructor
Scene(openglframework::GlutViewer* viewer);
/// Destructor
~Scene();
/// Take a step for the simulation
void simulate();
/// Render the scene
void render();
};
#endif

View File

@ -24,225 +24,166 @@
********************************************************************************/
// Libraries
#include <stdlib.h>
#include <reactphysics3d.h>
#include "Box.h"
#include "Scene.h"
#include <sstream>
// Prototypes
void init();
void display();
// Declarations
void simulate();
void clean();
void reshape(int w, int h);
void display();
void displayFPS();
void computeFPS();
void reshape(int width, int height);
void mouseButton(int button, int state, int x, int y);
void mouseMotion(int x, int y);
void keyboardSpecial(int key, int x, int y);
void init();
// Use the ReactPhysics3D namespace
using namespace reactphysics3d;
// Constants
const double FLOOR_SIZE = 20;
const double FLOOR_THICKNESS = 0.02;
// Namespaces
using namespace openglframework;
// Global variables
DynamicsWorld* dynamicsWorld; // Dynamics world
Box* boxes[2]; // Falling boxes
BoxShape* collisionShapeBox1; // Collision shape of the first box
BoxShape* collisionShapeBox2; // Collision shape of the second box
BoxShape* collisionShapeFloor; // Collision shape of the floor
RigidBody* floorRigidBody; // Rigid body corresponding the floor
// Simulation function
void simulate() {
// Update the physics simulation
dynamicsWorld->update();
// Display the scene
display();
}
GlutViewer* viewer;
Scene* scene;
int fps;
int nbFrames;
int currentTime;
int previousTime;
int width, height;
// Main function
int main(int argc, char** argv) {
// Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow("ReactPhysics3D Example - Falling Cubes");
// Create and initialize the Viewer
viewer = new GlutViewer();
Vector2 windowsSize = Vector2(800, 600);
Vector2 windowsPosition = Vector2(100, 100);
width = windowsSize.x;
height = windowsSize.y;
bool initOK = viewer->init(argc, argv, "ReactPhysics3D Examples - Falling Cubes", windowsSize, windowsPosition);
if (!initOK) return 1;
// Create the scene
scene = new Scene(viewer);
init();
nbFrames = 0;
// Glut Idle function that is continuously called
glutIdleFunc(simulate);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouseButton);
glutMotionFunc(mouseMotion);
glutSpecialFunc(keyboardSpecial);
// Glut main looop
glutMainLoop();
// Stop the physics simulation
dynamicsWorld->stop();
delete viewer;
delete scene;
clean();
return 0;
}
// Initialization function
void init() {
// Simulate function
void simulate() {
glClearColor(0.0, 0.0, 0.0, 0.0);
// Physics simulation
scene->simulate();
// Light
glShadeModel(GL_SMOOTH);
GLfloat light_position[] = {5.0f, 5.0f, 5.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
computeFPS();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
// Gravity vector of the physics world
Vector3 gravity(0.0, -9.81, 0.0);
// Timestep of the simulation
decimal timeStep = 1.0/60.0;
// Create the dynamics world
dynamicsWorld = new DynamicsWorld(gravity, timeStep);
// --- Create a falling box with a size of 1m and weight of 3kg --- //
float size = 1.0f;
// Initial position and orientation of the box
Vector3 positionBox1(-2.0f, 7.0f, 0.0f);
Quaternion orientationBox1(0.3, 1.0, 0.8, 0.0);
Transform initTransform(positionBox1, orientationBox1);
// Create a box collision shape for the box (used for collision detection)
collisionShapeBox1 = new BoxShape(Vector3(size/2.0f, size/2.0f, size/2.0f));
// Compute the inertia tensor of the box using the collision shape
Matrix3x3 inertiaTensorBox1;
float massBox1 = 3.0f;
collisionShapeBox1->computeLocalInertiaTensor(inertiaTensorBox1, massBox1);
// Create the rigid body associated with the box in the dynamics world
RigidBody* rigidBody = dynamicsWorld->createRigidBody(initTransform, massBox1,
inertiaTensorBox1, collisionShapeBox1);
// Set the contact velocity restitution factor of the rigid body
rigidBody->setRestitution(0.5f);
// Create the box object (used for display)
boxes[0] = new Box(size, rigidBody);
// --- Create a second falling box with a size of 1.5m and weight of 4.5kg --- //
size = 1.5;
// Initial position and orientation of the box
Vector3 positionBox2(2.0, 4.0, 0.0);
Quaternion orientationBox2(1.0, 1.0, 0.5, 0.0);
Transform initTransform2(positionBox2, orientationBox2);
// Create a box collision shape for the box (used for collision detection)
collisionShapeBox2 = new BoxShape(Vector3(size/2.0f, size/2.0f, size/2.0f));
// Compute the inertia tensor using the collision shape
Matrix3x3 inertiaTensorBox2;
float massBox2 = 4.5f;
collisionShapeBox2->computeLocalInertiaTensor(inertiaTensorBox2, massBox2);
// Create the rigid body associated with the box in the dynamcis world
RigidBody* rigidBody2 = dynamicsWorld->createRigidBody(initTransform2, massBox2,
inertiaTensorBox2, collisionShapeBox2);
// Set the contact velocity restitution factor of the rigid body
rigidBody2->setRestitution(0.5);
// Create the box object (used for display)
boxes[1] = new Box(size, rigidBody2);
// --- Create the rigid body corresponding to the floor --- //
// Initial position and orientation of the floor
Vector3 positionFloor(0.0, 0.0, 0.0);
Quaternion orientationFloor(0.0, 1.0, 0.0, 0.0);
Transform initTransformFloor(positionFloor, orientationFloor);
// Create a box collision shape for the floor (used for collision detection)
collisionShapeFloor = new BoxShape(Vector3(FLOOR_SIZE, FLOOR_THICKNESS, FLOOR_SIZE));
// Compute the inertia tensor of the floor using the collision shape
float massFloor = 100.0f;
rp3d::Matrix3x3 inertiaTensorFloor;
collisionShapeFloor->computeLocalInertiaTensor(inertiaTensorFloor, massFloor);
// Create the rigid body associated with the floor in the dynamcis world
floorRigidBody = dynamicsWorld->createRigidBody(initTransformFloor, massFloor,
inertiaTensorFloor, collisionShapeFloor);
// The floor is a rigid body that cannot move
floorRigidBody->setIsMotionEnabled(false);
// Set the contact velocity restitution factor of the floor
floorRigidBody->setRestitution(0.5);
// Start the dynamics simulation
dynamicsWorld->start();
// Ask GLUT to render the scene
glutPostRedisplay ();
}
// Display function
void display() {
// Initialization
void init() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Display each falling box of the scene
for (int i=0; i<2; i++) {
boxes[i]->draw();
}
// Display the plane for the floor
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-FLOOR_SIZE/2, 0.0, -FLOOR_SIZE/2);
glVertex3f(-FLOOR_SIZE/2, 0.0, FLOOR_SIZE/2);
glVertex3f(FLOOR_SIZE/2, 0.0, FLOOR_SIZE/2);
glVertex3f(FLOOR_SIZE/2, 0.0, -FLOOR_SIZE/2);
glEnd();
glutSwapBuffers();
// Define the background color (black)
glClearColor(0.0, 0.0, 0.0, 1.0);
}
// Reshape function
void reshape(int w, int h) {
float ratio = ((float)w / h);
void reshape(int newWidth, int newHeight) {
viewer->reshape(newWidth, newHeight);
width = newWidth;
height = newHeight;
}
// Called when a mouse button event occurs
void mouseButton(int button, int state, int x, int y) {
viewer->mouseButtonEvent(button, state, x, y);
}
// Called when a mouse motion event occurs
void mouseMotion(int x, int y) {
viewer->mouseMotionEvent(x, y);
}
// Called when the user hits a special key on the keyboard
void keyboardSpecial(int key, int x, int y) {
/*
if(key=='0')
exit(0);
if(key== GLUT_KEY_RIGHT) {
*/
}
// Display the scene
void display() {
// Render the scene
scene->render();
// Display the FPS
displayFPS();
// Swap the buffers
glutSwapBuffers();
// Check the OpenGL errors
GlutViewer::checkOpenGLErrors();
}
// Compute the FPS
void computeFPS() {
nbFrames++;
// Get the number of milliseconds since glutInit called
currentTime = glutGet(GLUT_ELAPSED_TIME);
// Calculate time passed
int timeInterval = currentTime - previousTime;
// Update the FPS counter each second
if(timeInterval > 1000){
// calculate the number of frames per second
fps = nbFrames / (timeInterval / 1000.0f);
// Set time
previousTime = currentTime;
// Reset frame count
nbFrames = 0;
}
}
// Display the FPS
void displayFPS() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45, ratio,1,1000);
glOrtho(0, width, height, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(20.0, 4.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
// Clean the memory allocation
void clean() {
// Destroy the rigid bodies from the dynamics world
dynamicsWorld->destroyRigidBody(boxes[0]->getRigidBodyPointer());
dynamicsWorld->destroyRigidBody(boxes[1]->getRigidBodyPointer());
dynamicsWorld->destroyRigidBody(floorRigidBody);
// Destroy the dynamics world
delete dynamicsWorld;
// Destroy the boxes
delete boxes[0];
delete boxes[1];
// Destroy the collision shapes
delete collisionShapeBox1;
delete collisionShapeBox2;
delete collisionShapeFloor;
glRasterPos2i(10, 20);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
std::stringstream ss;
ss << "FPS : " << fps;
glutBitmapString(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)ss.str().c_str());
}

View File

@ -0,0 +1,55 @@
# Minimum cmake version required
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
# Project configuration
PROJECT(OPENGLFRAMEWORK)
# Where to find the module to find special packages/libraries
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
# Find OpenGL
FIND_PACKAGE(OpenGL REQUIRED)
if(OPENGL_FOUND)
MESSAGE("OpenGL found")
else()
MESSAGE("OpenGL not found")
endif()
# Find the GLEW library
FIND_PACKAGE(GLEW REQUIRED)
if(GLEW_FOUND)
MESSAGE("GLEW found")
else()
MESSAGE("GLEW not found")
endif()
# Find the LIBJPEG library
FIND_PACKAGE(JPEG REQUIRED)
if(JPEG_FOUND)
MESSAGE("LIBJPEG found")
else()
MESSAGE("LIBJPEG not found")
endif()
# Freeglut
add_subdirectory(freeglut)
# Headers
INCLUDE_DIRECTORIES(src freeglut ${JPEG_INCLUDE_DIR})
# Library configuration
file (
GLOB_RECURSE
OPENGLFRAMEWORK_SOURCES_FILES
src/*
)
# Require the opengl-framework code to be compiled in a static library
ADD_LIBRARY (
openglframework
STATIC
${OPENGLFRAMEWORK_SOURCES_FILES}
)
TARGET_LINK_LIBRARIES(openglframework ${GLEW_LIBRARIES} ${OPENGL_LIBRARY} freeglut_static)

View File

@ -0,0 +1,24 @@
add_definitions( -DFREEGLUT_EXPORTS -DFREEGLUT_STATIC -D_CRT_SECURE_NO_WARNINGS )
if(APPLE)
include_directories( /usr/X11/include )
endif(APPLE)
if(UNIX)
add_definitions( -D__unix__ -DHAVE_FCNTL_H -DHAVE_GETTIMEOFDAY )
endif(UNIX)
file (
GLOB_RECURSE
FREEGLUT_SOURCES
./*
)
include_directories (
${OPENGL_INCLUDE_DIR}
.
)
add_library(freeglut_static
${FREEGLUT_SOURCES}
)

View File

@ -0,0 +1,27 @@
Freeglut Copyright
------------------
Freeglut code without an explicit copyright is covered by the following
copyright:
Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Pawel W. Olszta shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Pawel W. Olszta.

View File

@ -0,0 +1,22 @@
#ifndef __FREEGLUT_H__
#define __FREEGLUT_H__
/*
* freeglut.h
*
* The freeglut library include file
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "freeglut_std.h"
#include "freeglut_ext.h"
/*** END OF FILE ***/
#endif /* __FREEGLUT_H__ */

View File

@ -0,0 +1,236 @@
#ifndef __FREEGLUT_EXT_H__
#define __FREEGLUT_EXT_H__
/*
* freeglut_ext.h
*
* The non-GLUT-compatible extensions to the freeglut library include file
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 2 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* Additional GLUT Key definitions for the Special key function
*/
#define GLUT_KEY_NUM_LOCK 0x006D
#define GLUT_KEY_BEGIN 0x006E
#define GLUT_KEY_DELETE 0x006F
#define GLUT_KEY_SHIFT_L 0x0070
#define GLUT_KEY_SHIFT_R 0x0071
#define GLUT_KEY_CTRL_L 0x0072
#define GLUT_KEY_CTRL_R 0x0073
#define GLUT_KEY_ALT_L 0x0074
#define GLUT_KEY_ALT_R 0x0075
/*
* GLUT API Extension macro definitions -- behaviour when the user clicks on an "x" to close a window
*/
#define GLUT_ACTION_EXIT 0
#define GLUT_ACTION_GLUTMAINLOOP_RETURNS 1
#define GLUT_ACTION_CONTINUE_EXECUTION 2
/*
* Create a new rendering context when the user opens a new window?
*/
#define GLUT_CREATE_NEW_CONTEXT 0
#define GLUT_USE_CURRENT_CONTEXT 1
/*
* Direct/Indirect rendering context options (has meaning only in Unix/X11)
*/
#define GLUT_FORCE_INDIRECT_CONTEXT 0
#define GLUT_ALLOW_DIRECT_CONTEXT 1
#define GLUT_TRY_DIRECT_CONTEXT 2
#define GLUT_FORCE_DIRECT_CONTEXT 3
/*
* GLUT API Extension macro definitions -- the glutGet parameters
*/
#define GLUT_INIT_STATE 0x007C
#define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9
#define GLUT_WINDOW_BORDER_WIDTH 0x01FA
#define GLUT_WINDOW_HEADER_HEIGHT 0x01FB
#define GLUT_VERSION 0x01FC
#define GLUT_RENDERING_CONTEXT 0x01FD
#define GLUT_DIRECT_RENDERING 0x01FE
#define GLUT_FULL_SCREEN 0x01FF
/*
* New tokens for glutInitDisplayMode.
* Only one GLUT_AUXn bit may be used at a time.
* Value 0x0400 is defined in OpenGLUT.
*/
#define GLUT_AUX 0x1000
#define GLUT_AUX1 0x1000
#define GLUT_AUX2 0x2000
#define GLUT_AUX3 0x4000
#define GLUT_AUX4 0x8000
/*
* Context-related flags, see freeglut_state.c
*/
#define GLUT_INIT_MAJOR_VERSION 0x0200
#define GLUT_INIT_MINOR_VERSION 0x0201
#define GLUT_INIT_FLAGS 0x0202
#define GLUT_INIT_PROFILE 0x0203
/*
* Flags for glutInitContextFlags, see freeglut_init.c
*/
#define GLUT_DEBUG 0x0001
#define GLUT_FORWARD_COMPATIBLE 0x0002
/*
* Flags for glutInitContextProfile, see freeglut_init.c
*/
#define GLUT_CORE_PROFILE 0x0001
#define GLUT_COMPATIBILITY_PROFILE 0x0002
/*
* Process loop function, see freeglut_main.c
*/
FGAPI void FGAPIENTRY glutMainLoopEvent( void );
FGAPI void FGAPIENTRY glutLeaveMainLoop( void );
FGAPI void FGAPIENTRY glutExit ( void );
/*
* Window management functions, see freeglut_window.c
*/
FGAPI void FGAPIENTRY glutFullScreenToggle( void );
FGAPI void FGAPIENTRY glutLeaveFullScreen( void );
/*
* Window-specific callback functions, see freeglut_callbacks.c
*/
FGAPI void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) );
FGAPI void FGAPIENTRY glutCloseFunc( void (* callback)( void ) );
FGAPI void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) );
/* A. Donev: Also a destruction callback for menus */
FGAPI void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) );
/*
* State setting and retrieval functions, see freeglut_state.c
*/
FGAPI void FGAPIENTRY glutSetOption ( GLenum option_flag, int value );
FGAPI int * FGAPIENTRY glutGetModeValues(GLenum mode, int * size);
/* A.Donev: User-data manipulation */
FGAPI void* FGAPIENTRY glutGetWindowData( void );
FGAPI void FGAPIENTRY glutSetWindowData(void* data);
FGAPI void* FGAPIENTRY glutGetMenuData( void );
FGAPI void FGAPIENTRY glutSetMenuData(void* data);
/*
* Font stuff, see freeglut_font.c
*/
FGAPI int FGAPIENTRY glutBitmapHeight( void* font );
FGAPI GLfloat FGAPIENTRY glutStrokeHeight( void* font );
FGAPI void FGAPIENTRY glutBitmapString( void* font, const unsigned char *string );
FGAPI void FGAPIENTRY glutStrokeString( void* font, const unsigned char *string );
/*
* Geometry functions, see freeglut_geometry.c
*/
FGAPI void FGAPIENTRY glutWireRhombicDodecahedron( void );
FGAPI void FGAPIENTRY glutSolidRhombicDodecahedron( void );
FGAPI void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale );
FGAPI void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale );
FGAPI void FGAPIENTRY glutWireCylinder( GLdouble radius, GLdouble height, GLint slices, GLint stacks);
FGAPI void FGAPIENTRY glutSolidCylinder( GLdouble radius, GLdouble height, GLint slices, GLint stacks);
/*
* Extension functions, see freeglut_ext.c
*/
typedef void (*GLUTproc)();
FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName );
/*
* Multi-touch/multi-pointer extensions
*/
#define GLUT_HAS_MULTI 1
FGAPI void FGAPIENTRY glutMultiEntryFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutMultiButtonFunc( void (* callback)( int, int, int, int, int ) );
FGAPI void FGAPIENTRY glutMultiMotionFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutMultiPassiveFunc( void (* callback)( int, int, int ) );
/*
* Joystick functions, see freeglut_joystick.c
*/
/* USE OF THESE FUNCTIONS IS DEPRECATED !!!!! */
/* If you have a serious need for these functions in your application, please either
* contact the "freeglut" developer community at freeglut-developer@lists.sourceforge.net,
* switch to the OpenGLUT library, or else port your joystick functionality over to PLIB's
* "js" library.
*/
int glutJoystickGetNumAxes( int ident );
int glutJoystickGetNumButtons( int ident );
int glutJoystickNotWorking( int ident );
float glutJoystickGetDeadBand( int ident, int axis );
void glutJoystickSetDeadBand( int ident, int axis, float db );
float glutJoystickGetSaturation( int ident, int axis );
void glutJoystickSetSaturation( int ident, int axis, float st );
void glutJoystickSetMinRange( int ident, float *axes );
void glutJoystickSetMaxRange( int ident, float *axes );
void glutJoystickSetCenter( int ident, float *axes );
void glutJoystickGetMinRange( int ident, float *axes );
void glutJoystickGetMaxRange( int ident, float *axes );
void glutJoystickGetCenter( int ident, float *axes );
/*
* Initialization functions, see freeglut_init.c
*/
FGAPI void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion );
FGAPI void FGAPIENTRY glutInitContextFlags( int flags );
FGAPI void FGAPIENTRY glutInitContextProfile( int profile );
/* to get the typedef for va_list */
#include <stdarg.h>
FGAPI void FGAPIENTRY glutInitErrorFunc( void (* vError)( const char *fmt, va_list ap ) );
FGAPI void FGAPIENTRY glutInitWarningFunc( void (* vWarning)( const char *fmt, va_list ap ) );
/*
* GLUT API macro definitions -- the display mode definitions
*/
#define GLUT_CAPTIONLESS 0x0400
#define GLUT_BORDERLESS 0x0800
#define GLUT_SRGB 0x1000
#ifdef __cplusplus
}
#endif
/*** END OF FILE ***/
#endif /* __FREEGLUT_EXT_H__ */

View File

@ -0,0 +1,628 @@
#ifndef __FREEGLUT_STD_H__
#define __FREEGLUT_STD_H__
/*
* freeglut_std.h
*
* The GLUT-compatible part of the freeglut library include file
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 2 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* Under windows, we have to differentiate between static and dynamic libraries
*/
#ifdef _WIN32
/* #pragma may not be supported by some compilers.
* Discussion by FreeGLUT developers suggests that
* Visual C++ specific code involving pragmas may
* need to move to a separate header. 24th Dec 2003
*/
/* Define FREEGLUT_LIB_PRAGMAS to 1 to include library
* pragmas or to 0 to exclude library pragmas.
* The default behavior depends on the compiler/platform.
*/
# ifndef FREEGLUT_LIB_PRAGMAS
# if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(_WIN32_WCE)
# define FREEGLUT_LIB_PRAGMAS 1
# else
# define FREEGLUT_LIB_PRAGMAS 0
# endif
# endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN 1
# endif
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
/* Windows static library */
# ifdef FREEGLUT_STATIC
# define FGAPI
# define FGAPIENTRY
/* Link with Win32 static freeglut lib */
# if FREEGLUT_LIB_PRAGMAS
# pragma comment (lib, "freeglut_static.lib")
# endif
/* Windows shared library (DLL) */
# else
# define FGAPIENTRY __stdcall
# if defined(FREEGLUT_EXPORTS)
# define FGAPI __declspec(dllexport)
# else
# define FGAPI __declspec(dllimport)
/* Link with Win32 shared freeglut lib */
# if FREEGLUT_LIB_PRAGMAS
# pragma comment (lib, "freeglut.lib")
# endif
# endif
# endif
/* Drag in other Windows libraries as required by FreeGLUT */
# if FREEGLUT_LIB_PRAGMAS
# pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib */
# pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib */
# pragma comment (lib, "gdi32.lib") /* link Windows GDI lib */
# pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib */
# pragma comment (lib, "user32.lib") /* link Windows user lib */
# endif
#else
/* Non-Windows definition of FGAPI and FGAPIENTRY */
# define FGAPI
# define FGAPIENTRY
#endif
/*
* The freeglut and GLUT API versions
*/
#define FREEGLUT 1
#define GLUT_API_VERSION 4
#define FREEGLUT_VERSION_2_0 1
#define GLUT_XLIB_IMPLEMENTATION 13
/*
* Always include OpenGL and GLU headers
*/
#include <GL/gl.h>
#include <GL/glu.h>
/*
* GLUT API macro definitions -- the special key codes:
*/
#define GLUT_KEY_F1 0x0001
#define GLUT_KEY_F2 0x0002
#define GLUT_KEY_F3 0x0003
#define GLUT_KEY_F4 0x0004
#define GLUT_KEY_F5 0x0005
#define GLUT_KEY_F6 0x0006
#define GLUT_KEY_F7 0x0007
#define GLUT_KEY_F8 0x0008
#define GLUT_KEY_F9 0x0009
#define GLUT_KEY_F10 0x000A
#define GLUT_KEY_F11 0x000B
#define GLUT_KEY_F12 0x000C
#define GLUT_KEY_LEFT 0x0064
#define GLUT_KEY_UP 0x0065
#define GLUT_KEY_RIGHT 0x0066
#define GLUT_KEY_DOWN 0x0067
#define GLUT_KEY_PAGE_UP 0x0068
#define GLUT_KEY_PAGE_DOWN 0x0069
#define GLUT_KEY_HOME 0x006A
#define GLUT_KEY_END 0x006B
#define GLUT_KEY_INSERT 0x006C
/*
* GLUT API macro definitions -- mouse state definitions
*/
#define GLUT_LEFT_BUTTON 0x0000
#define GLUT_MIDDLE_BUTTON 0x0001
#define GLUT_RIGHT_BUTTON 0x0002
#define GLUT_DOWN 0x0000
#define GLUT_UP 0x0001
#define GLUT_LEFT 0x0000
#define GLUT_ENTERED 0x0001
/*
* GLUT API macro definitions -- the display mode definitions
*/
#define GLUT_RGB 0x0000
#define GLUT_RGBA 0x0000
#define GLUT_INDEX 0x0001
#define GLUT_SINGLE 0x0000
#define GLUT_DOUBLE 0x0002
#define GLUT_ACCUM 0x0004
#define GLUT_ALPHA 0x0008
#define GLUT_DEPTH 0x0010
#define GLUT_STENCIL 0x0020
#define GLUT_MULTISAMPLE 0x0080
#define GLUT_STEREO 0x0100
#define GLUT_LUMINANCE 0x0200
/*
* GLUT API macro definitions -- windows and menu related definitions
*/
#define GLUT_MENU_NOT_IN_USE 0x0000
#define GLUT_MENU_IN_USE 0x0001
#define GLUT_NOT_VISIBLE 0x0000
#define GLUT_VISIBLE 0x0001
#define GLUT_HIDDEN 0x0000
#define GLUT_FULLY_RETAINED 0x0001
#define GLUT_PARTIALLY_RETAINED 0x0002
#define GLUT_FULLY_COVERED 0x0003
/*
* GLUT API macro definitions -- fonts definitions
*
* Steve Baker suggested to make it binary compatible with GLUT:
*/
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WATCOMC__)
# define GLUT_STROKE_ROMAN ((void *)0x0000)
# define GLUT_STROKE_MONO_ROMAN ((void *)0x0001)
# define GLUT_BITMAP_9_BY_15 ((void *)0x0002)
# define GLUT_BITMAP_8_BY_13 ((void *)0x0003)
# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *)0x0004)
# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *)0x0005)
# define GLUT_BITMAP_HELVETICA_10 ((void *)0x0006)
# define GLUT_BITMAP_HELVETICA_12 ((void *)0x0007)
# define GLUT_BITMAP_HELVETICA_18 ((void *)0x0008)
#else
/*
* I don't really know if it's a good idea... But here it goes:
*/
extern void* glutStrokeRoman;
extern void* glutStrokeMonoRoman;
extern void* glutBitmap9By15;
extern void* glutBitmap8By13;
extern void* glutBitmapTimesRoman10;
extern void* glutBitmapTimesRoman24;
extern void* glutBitmapHelvetica10;
extern void* glutBitmapHelvetica12;
extern void* glutBitmapHelvetica18;
/*
* Those pointers will be used by following definitions:
*/
# define GLUT_STROKE_ROMAN ((void *) &glutStrokeRoman)
# define GLUT_STROKE_MONO_ROMAN ((void *) &glutStrokeMonoRoman)
# define GLUT_BITMAP_9_BY_15 ((void *) &glutBitmap9By15)
# define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13)
# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *) &glutBitmapTimesRoman10)
# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *) &glutBitmapTimesRoman24)
# define GLUT_BITMAP_HELVETICA_10 ((void *) &glutBitmapHelvetica10)
# define GLUT_BITMAP_HELVETICA_12 ((void *) &glutBitmapHelvetica12)
# define GLUT_BITMAP_HELVETICA_18 ((void *) &glutBitmapHelvetica18)
#endif
/*
* GLUT API macro definitions -- the glutGet parameters
*/
#define GLUT_WINDOW_X 0x0064
#define GLUT_WINDOW_Y 0x0065
#define GLUT_WINDOW_WIDTH 0x0066
#define GLUT_WINDOW_HEIGHT 0x0067
#define GLUT_WINDOW_BUFFER_SIZE 0x0068
#define GLUT_WINDOW_STENCIL_SIZE 0x0069
#define GLUT_WINDOW_DEPTH_SIZE 0x006A
#define GLUT_WINDOW_RED_SIZE 0x006B
#define GLUT_WINDOW_GREEN_SIZE 0x006C
#define GLUT_WINDOW_BLUE_SIZE 0x006D
#define GLUT_WINDOW_ALPHA_SIZE 0x006E
#define GLUT_WINDOW_ACCUM_RED_SIZE 0x006F
#define GLUT_WINDOW_ACCUM_GREEN_SIZE 0x0070
#define GLUT_WINDOW_ACCUM_BLUE_SIZE 0x0071
#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 0x0072
#define GLUT_WINDOW_DOUBLEBUFFER 0x0073
#define GLUT_WINDOW_RGBA 0x0074
#define GLUT_WINDOW_PARENT 0x0075
#define GLUT_WINDOW_NUM_CHILDREN 0x0076
#define GLUT_WINDOW_COLORMAP_SIZE 0x0077
#define GLUT_WINDOW_NUM_SAMPLES 0x0078
#define GLUT_WINDOW_STEREO 0x0079
#define GLUT_WINDOW_CURSOR 0x007A
#define GLUT_SCREEN_WIDTH 0x00C8
#define GLUT_SCREEN_HEIGHT 0x00C9
#define GLUT_SCREEN_WIDTH_MM 0x00CA
#define GLUT_SCREEN_HEIGHT_MM 0x00CB
#define GLUT_MENU_NUM_ITEMS 0x012C
#define GLUT_DISPLAY_MODE_POSSIBLE 0x0190
#define GLUT_INIT_WINDOW_X 0x01F4
#define GLUT_INIT_WINDOW_Y 0x01F5
#define GLUT_INIT_WINDOW_WIDTH 0x01F6
#define GLUT_INIT_WINDOW_HEIGHT 0x01F7
#define GLUT_INIT_DISPLAY_MODE 0x01F8
#define GLUT_ELAPSED_TIME 0x02BC
#define GLUT_WINDOW_FORMAT_ID 0x007B
/*
* GLUT API macro definitions -- the glutDeviceGet parameters
*/
#define GLUT_HAS_KEYBOARD 0x0258
#define GLUT_HAS_MOUSE 0x0259
#define GLUT_HAS_SPACEBALL 0x025A
#define GLUT_HAS_DIAL_AND_BUTTON_BOX 0x025B
#define GLUT_HAS_TABLET 0x025C
#define GLUT_NUM_MOUSE_BUTTONS 0x025D
#define GLUT_NUM_SPACEBALL_BUTTONS 0x025E
#define GLUT_NUM_BUTTON_BOX_BUTTONS 0x025F
#define GLUT_NUM_DIALS 0x0260
#define GLUT_NUM_TABLET_BUTTONS 0x0261
#define GLUT_DEVICE_IGNORE_KEY_REPEAT 0x0262
#define GLUT_DEVICE_KEY_REPEAT 0x0263
#define GLUT_HAS_JOYSTICK 0x0264
#define GLUT_OWNS_JOYSTICK 0x0265
#define GLUT_JOYSTICK_BUTTONS 0x0266
#define GLUT_JOYSTICK_AXES 0x0267
#define GLUT_JOYSTICK_POLL_RATE 0x0268
/*
* GLUT API macro definitions -- the glutLayerGet parameters
*/
#define GLUT_OVERLAY_POSSIBLE 0x0320
#define GLUT_LAYER_IN_USE 0x0321
#define GLUT_HAS_OVERLAY 0x0322
#define GLUT_TRANSPARENT_INDEX 0x0323
#define GLUT_NORMAL_DAMAGED 0x0324
#define GLUT_OVERLAY_DAMAGED 0x0325
/*
* GLUT API macro definitions -- the glutVideoResizeGet parameters
*/
#define GLUT_VIDEO_RESIZE_POSSIBLE 0x0384
#define GLUT_VIDEO_RESIZE_IN_USE 0x0385
#define GLUT_VIDEO_RESIZE_X_DELTA 0x0386
#define GLUT_VIDEO_RESIZE_Y_DELTA 0x0387
#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 0x0388
#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 0x0389
#define GLUT_VIDEO_RESIZE_X 0x038A
#define GLUT_VIDEO_RESIZE_Y 0x038B
#define GLUT_VIDEO_RESIZE_WIDTH 0x038C
#define GLUT_VIDEO_RESIZE_HEIGHT 0x038D
/*
* GLUT API macro definitions -- the glutUseLayer parameters
*/
#define GLUT_NORMAL 0x0000
#define GLUT_OVERLAY 0x0001
/*
* GLUT API macro definitions -- the glutGetModifiers parameters
*/
#define GLUT_ACTIVE_SHIFT 0x0001
#define GLUT_ACTIVE_CTRL 0x0002
#define GLUT_ACTIVE_ALT 0x0004
/*
* GLUT API macro definitions -- the glutSetCursor parameters
*/
#define GLUT_CURSOR_RIGHT_ARROW 0x0000
#define GLUT_CURSOR_LEFT_ARROW 0x0001
#define GLUT_CURSOR_INFO 0x0002
#define GLUT_CURSOR_DESTROY 0x0003
#define GLUT_CURSOR_HELP 0x0004
#define GLUT_CURSOR_CYCLE 0x0005
#define GLUT_CURSOR_SPRAY 0x0006
#define GLUT_CURSOR_WAIT 0x0007
#define GLUT_CURSOR_TEXT 0x0008
#define GLUT_CURSOR_CROSSHAIR 0x0009
#define GLUT_CURSOR_UP_DOWN 0x000A
#define GLUT_CURSOR_LEFT_RIGHT 0x000B
#define GLUT_CURSOR_TOP_SIDE 0x000C
#define GLUT_CURSOR_BOTTOM_SIDE 0x000D
#define GLUT_CURSOR_LEFT_SIDE 0x000E
#define GLUT_CURSOR_RIGHT_SIDE 0x000F
#define GLUT_CURSOR_TOP_LEFT_CORNER 0x0010
#define GLUT_CURSOR_TOP_RIGHT_CORNER 0x0011
#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 0x0012
#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 0x0013
#define GLUT_CURSOR_INHERIT 0x0064
#define GLUT_CURSOR_NONE 0x0065
#define GLUT_CURSOR_FULL_CROSSHAIR 0x0066
/*
* GLUT API macro definitions -- RGB color component specification definitions
*/
#define GLUT_RED 0x0000
#define GLUT_GREEN 0x0001
#define GLUT_BLUE 0x0002
/*
* GLUT API macro definitions -- additional keyboard and joystick definitions
*/
#define GLUT_KEY_REPEAT_OFF 0x0000
#define GLUT_KEY_REPEAT_ON 0x0001
#define GLUT_KEY_REPEAT_DEFAULT 0x0002
#define GLUT_JOYSTICK_BUTTON_A 0x0001
#define GLUT_JOYSTICK_BUTTON_B 0x0002
#define GLUT_JOYSTICK_BUTTON_C 0x0004
#define GLUT_JOYSTICK_BUTTON_D 0x0008
/*
* GLUT API macro definitions -- game mode definitions
*/
#define GLUT_GAME_MODE_ACTIVE 0x0000
#define GLUT_GAME_MODE_POSSIBLE 0x0001
#define GLUT_GAME_MODE_WIDTH 0x0002
#define GLUT_GAME_MODE_HEIGHT 0x0003
#define GLUT_GAME_MODE_PIXEL_DEPTH 0x0004
#define GLUT_GAME_MODE_REFRESH_RATE 0x0005
#define GLUT_GAME_MODE_DISPLAY_CHANGED 0x0006
/*
* Initialization functions, see fglut_init.c
*/
FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv );
FGAPI void FGAPIENTRY glutInitWindowPosition( int x, int y );
FGAPI void FGAPIENTRY glutInitWindowSize( int width, int height );
FGAPI void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode );
FGAPI void FGAPIENTRY glutInitDisplayString( const char* displayMode );
/*
* Process loop function, see freeglut_main.c
*/
FGAPI void FGAPIENTRY glutMainLoop( void );
/*
* Window management functions, see freeglut_window.c
*/
FGAPI int FGAPIENTRY glutCreateWindow( const char* title );
FGAPI int FGAPIENTRY glutCreateSubWindow( int window, int x, int y, int width, int height );
FGAPI void FGAPIENTRY glutDestroyWindow( int window );
FGAPI void FGAPIENTRY glutSetWindow( int window );
FGAPI int FGAPIENTRY glutGetWindow( void );
FGAPI void FGAPIENTRY glutSetWindowTitle( const char* title );
FGAPI void FGAPIENTRY glutSetIconTitle( const char* title );
FGAPI void FGAPIENTRY glutReshapeWindow( int width, int height );
FGAPI void FGAPIENTRY glutPositionWindow( int x, int y );
FGAPI void FGAPIENTRY glutShowWindow( void );
FGAPI void FGAPIENTRY glutHideWindow( void );
FGAPI void FGAPIENTRY glutIconifyWindow( void );
FGAPI void FGAPIENTRY glutPushWindow( void );
FGAPI void FGAPIENTRY glutPopWindow( void );
FGAPI void FGAPIENTRY glutFullScreen( void );
/*
* Display-connected functions, see freeglut_display.c
*/
FGAPI void FGAPIENTRY glutPostWindowRedisplay( int window );
FGAPI void FGAPIENTRY glutPostRedisplay( void );
FGAPI void FGAPIENTRY glutSwapBuffers( void );
/*
* Mouse cursor functions, see freeglut_cursor.c
*/
FGAPI void FGAPIENTRY glutWarpPointer( int x, int y );
FGAPI void FGAPIENTRY glutSetCursor( int cursor );
/*
* Overlay stuff, see freeglut_overlay.c
*/
FGAPI void FGAPIENTRY glutEstablishOverlay( void );
FGAPI void FGAPIENTRY glutRemoveOverlay( void );
FGAPI void FGAPIENTRY glutUseLayer( GLenum layer );
FGAPI void FGAPIENTRY glutPostOverlayRedisplay( void );
FGAPI void FGAPIENTRY glutPostWindowOverlayRedisplay( int window );
FGAPI void FGAPIENTRY glutShowOverlay( void );
FGAPI void FGAPIENTRY glutHideOverlay( void );
/*
* Menu stuff, see freeglut_menu.c
*/
FGAPI int FGAPIENTRY glutCreateMenu( void (* callback)( int menu ) );
FGAPI void FGAPIENTRY glutDestroyMenu( int menu );
FGAPI int FGAPIENTRY glutGetMenu( void );
FGAPI void FGAPIENTRY glutSetMenu( int menu );
FGAPI void FGAPIENTRY glutAddMenuEntry( const char* label, int value );
FGAPI void FGAPIENTRY glutAddSubMenu( const char* label, int subMenu );
FGAPI void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value );
FGAPI void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int value );
FGAPI void FGAPIENTRY glutRemoveMenuItem( int item );
FGAPI void FGAPIENTRY glutAttachMenu( int button );
FGAPI void FGAPIENTRY glutDetachMenu( int button );
/*
* Global callback functions, see freeglut_callbacks.c
*/
FGAPI void FGAPIENTRY glutTimerFunc( unsigned int time, void (* callback)( int ), int value );
FGAPI void FGAPIENTRY glutIdleFunc( void (* callback)( void ) );
/*
* Window-specific callback functions, see freeglut_callbacks.c
*/
FGAPI void FGAPIENTRY glutKeyboardFunc( void (* callback)( unsigned char, int, int ) );
FGAPI void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) );
FGAPI void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) );
FGAPI void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) );
FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutEntryFunc( void (* callback)( int ) );
FGAPI void FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) );
FGAPI void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval );
FGAPI void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) );
FGAPI void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) );
FGAPI void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) );
FGAPI void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) );
/*
* State setting and retrieval functions, see freeglut_state.c
*/
FGAPI int FGAPIENTRY glutGet( GLenum query );
FGAPI int FGAPIENTRY glutDeviceGet( GLenum query );
FGAPI int FGAPIENTRY glutGetModifiers( void );
FGAPI int FGAPIENTRY glutLayerGet( GLenum query );
/*
* Font stuff, see freeglut_font.c
*/
FGAPI void FGAPIENTRY glutBitmapCharacter( void* font, int character );
FGAPI int FGAPIENTRY glutBitmapWidth( void* font, int character );
FGAPI void FGAPIENTRY glutStrokeCharacter( void* font, int character );
FGAPI int FGAPIENTRY glutStrokeWidth( void* font, int character );
FGAPI int FGAPIENTRY glutBitmapLength( void* font, const unsigned char* string );
FGAPI int FGAPIENTRY glutStrokeLength( void* font, const unsigned char* string );
/*
* Geometry functions, see freeglut_geometry.c
*/
FGAPI void FGAPIENTRY glutWireCube( GLdouble size );
FGAPI void FGAPIENTRY glutSolidCube( GLdouble size );
FGAPI void FGAPIENTRY glutWireSphere( GLdouble radius, GLint slices, GLint stacks );
FGAPI void FGAPIENTRY glutSolidSphere( GLdouble radius, GLint slices, GLint stacks );
FGAPI void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks );
FGAPI void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks );
FGAPI void FGAPIENTRY glutWireTorus( GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings );
FGAPI void FGAPIENTRY glutSolidTorus( GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings );
FGAPI void FGAPIENTRY glutWireDodecahedron( void );
FGAPI void FGAPIENTRY glutSolidDodecahedron( void );
FGAPI void FGAPIENTRY glutWireOctahedron( void );
FGAPI void FGAPIENTRY glutSolidOctahedron( void );
FGAPI void FGAPIENTRY glutWireTetrahedron( void );
FGAPI void FGAPIENTRY glutSolidTetrahedron( void );
FGAPI void FGAPIENTRY glutWireIcosahedron( void );
FGAPI void FGAPIENTRY glutSolidIcosahedron( void );
/*
* Teapot rendering functions, found in freeglut_teapot.c
*/
FGAPI void FGAPIENTRY glutWireTeapot( GLdouble size );
FGAPI void FGAPIENTRY glutSolidTeapot( GLdouble size );
/*
* Game mode functions, see freeglut_gamemode.c
*/
FGAPI void FGAPIENTRY glutGameModeString( const char* string );
FGAPI int FGAPIENTRY glutEnterGameMode( void );
FGAPI void FGAPIENTRY glutLeaveGameMode( void );
FGAPI int FGAPIENTRY glutGameModeGet( GLenum query );
/*
* Video resize functions, see freeglut_videoresize.c
*/
FGAPI int FGAPIENTRY glutVideoResizeGet( GLenum query );
FGAPI void FGAPIENTRY glutSetupVideoResizing( void );
FGAPI void FGAPIENTRY glutStopVideoResizing( void );
FGAPI void FGAPIENTRY glutVideoResize( int x, int y, int width, int height );
FGAPI void FGAPIENTRY glutVideoPan( int x, int y, int width, int height );
/*
* Colormap functions, see freeglut_misc.c
*/
FGAPI void FGAPIENTRY glutSetColor( int color, GLfloat red, GLfloat green, GLfloat blue );
FGAPI GLfloat FGAPIENTRY glutGetColor( int color, int component );
FGAPI void FGAPIENTRY glutCopyColormap( int window );
/*
* Misc keyboard and joystick functions, see freeglut_misc.c
*/
FGAPI void FGAPIENTRY glutIgnoreKeyRepeat( int ignore );
FGAPI void FGAPIENTRY glutSetKeyRepeat( int repeatMode );
FGAPI void FGAPIENTRY glutForceJoystickFunc( void );
/*
* Misc functions, see freeglut_misc.c
*/
FGAPI int FGAPIENTRY glutExtensionSupported( const char* extension );
FGAPI void FGAPIENTRY glutReportErrors( void );
/* Comment from glut.h of classic GLUT:
Win32 has an annoying issue where there are multiple C run-time
libraries (CRTs). If the executable is linked with a different CRT
from the GLUT DLL, the GLUT DLL will not share the same CRT static
data seen by the executable. In particular, atexit callbacks registered
in the executable will not be called if GLUT calls its (different)
exit routine). GLUT is typically built with the
"/MD" option (the CRT with multithreading DLL support), but the Visual
C++ linker default is "/ML" (the single threaded CRT).
One workaround to this issue is requiring users to always link with
the same CRT as GLUT is compiled with. That requires users supply a
non-standard option. GLUT 3.7 has its own built-in workaround where
the executable's "exit" function pointer is covertly passed to GLUT.
GLUT then calls the executable's exit function pointer to ensure that
any "atexit" calls registered by the application are called if GLUT
needs to exit.
Note that the __glut*WithExit routines should NEVER be called directly.
To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */
/* to get the prototype for exit() */
#include <stdlib.h>
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__)
FGAPI void FGAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int));
FGAPI int FGAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int));
FGAPI int FGAPIENTRY __glutCreateMenuWithExit(void (* func)(int), void (__cdecl *exitfunc)(int));
#ifndef FREEGLUT_BUILDING_LIB
#if defined(__GNUC__)
#define FGUNUSED __attribute__((unused))
#else
#define FGUNUSED
#endif
static void FGAPIENTRY FGUNUSED glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
#define glutInit glutInit_ATEXIT_HACK
static int FGAPIENTRY FGUNUSED glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); }
#define glutCreateWindow glutCreateWindow_ATEXIT_HACK
static int FGAPIENTRY FGUNUSED glutCreateMenu_ATEXIT_HACK(void (* func)(int)) { return __glutCreateMenuWithExit(func, exit); }
#define glutCreateMenu glutCreateMenu_ATEXIT_HACK
#endif
#endif
#ifdef __cplusplus
}
#endif
/*** END OF FILE ***/
#endif /* __FREEGLUT_STD_H__ */

View File

@ -0,0 +1,21 @@
#ifndef __GLUT_H__
#define __GLUT_H__
/*
* glut.h
*
* The freeglut library include file
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "freeglut_std.h"
/*** END OF FILE ***/
#endif /* __GLUT_H__ */

View File

@ -0,0 +1 @@
2.8.0

View File

@ -0,0 +1,412 @@
/*
* freeglut_callbacks.c
*
* The callbacks setting methods.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Fri Dec 3 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* All of the callbacks setting methods can be generalized to this:
*/
#define SET_CALLBACK(a) \
do \
{ \
if( fgStructure.CurrentWindow == NULL ) \
return; \
SET_WCB( ( *( fgStructure.CurrentWindow ) ), a, callback ); \
} while( 0 )
/*
* Sets the Display callback for the current window
*/
void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDisplayFunc" );
if( !callback )
fgError( "Fatal error in program. NULL display callback not "
"permitted in GLUT 3.0+ or freeglut 2.0.1+" );
SET_CALLBACK( Display );
}
/*
* Sets the Reshape callback for the current window
*/
void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeFunc" );
SET_CALLBACK( Reshape );
}
/*
* Sets the Keyboard callback for the current window
*/
void FGAPIENTRY glutKeyboardFunc( void (* callback)
( unsigned char, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardFunc" );
SET_CALLBACK( Keyboard );
}
/*
* Sets the Special callback for the current window
*/
void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialFunc" );
SET_CALLBACK( Special );
}
/*
* Sets the global idle callback
*/
void FGAPIENTRY glutIdleFunc( void (* callback)( void ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIdleFunc" );
fgState.IdleCallback = callback;
}
/*
* Sets the Timer callback for the current window
*/
void FGAPIENTRY glutTimerFunc( unsigned int timeOut, void (* callback)( int ),
int timerID )
{
SFG_Timer *timer, *node;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTimerFunc" );
if( (timer = fgState.FreeTimers.Last) )
{
fgListRemove( &fgState.FreeTimers, &timer->Node );
}
else
{
if( ! (timer = malloc(sizeof(SFG_Timer))) )
fgError( "Fatal error: "
"Memory allocation failure in glutTimerFunc()" );
}
timer->Callback = callback;
timer->ID = timerID;
timer->TriggerTime = fgElapsedTime() + timeOut;
for( node = fgState.Timers.First; node; node = node->Node.Next )
{
if( node->TriggerTime > timer->TriggerTime )
break;
}
fgListInsert( &fgState.Timers, &node->Node, &timer->Node );
}
/*
* Sets the Visibility callback for the current window.
*/
static void fghVisibility( int status )
{
int glut_status = GLUT_VISIBLE;
FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Visibility Callback" );
freeglut_return_if_fail( fgStructure.CurrentWindow );
if( ( GLUT_HIDDEN == status ) || ( GLUT_FULLY_COVERED == status ) )
glut_status = GLUT_NOT_VISIBLE;
INVOKE_WCB( *( fgStructure.CurrentWindow ), Visibility, ( glut_status ) );
}
void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutVisibilityFunc" );
SET_CALLBACK( Visibility );
if( callback )
glutWindowStatusFunc( fghVisibility );
else
glutWindowStatusFunc( NULL );
}
/*
* Sets the keyboard key release callback for the current window
*/
void FGAPIENTRY glutKeyboardUpFunc( void (* callback)
( unsigned char, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutKeyboardUpFunc" );
SET_CALLBACK( KeyboardUp );
}
/*
* Sets the special key release callback for the current window
*/
void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpecialUpFunc" );
SET_CALLBACK( SpecialUp );
}
/*
* Sets the joystick callback and polling rate for the current window
*/
void FGAPIENTRY glutJoystickFunc( void (* callback)
( unsigned int, int, int, int ),
int pollInterval )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutJoystickFunc" );
fgInitialiseJoysticks ();
if ( ( ( fgStructure.CurrentWindow->State.JoystickPollRate < 0 ) ||
!FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) && /* Joystick callback was disabled */
( callback && ( pollInterval >= 0 ) ) ) /* but is now enabled */
++fgState.NumActiveJoysticks;
else if ( ( ( fgStructure.CurrentWindow->State.JoystickPollRate >= 0 ) &&
FETCH_WCB(*fgStructure.CurrentWindow,Joystick) ) && /* Joystick callback was enabled */
( !callback || ( pollInterval < 0 ) ) ) /* but is now disabled */
--fgState.NumActiveJoysticks;
SET_CALLBACK( Joystick );
fgStructure.CurrentWindow->State.JoystickPollRate = pollInterval;
fgStructure.CurrentWindow->State.JoystickLastPoll =
fgElapsedTime() - fgStructure.CurrentWindow->State.JoystickPollRate;
if( fgStructure.CurrentWindow->State.JoystickLastPoll < 0 )
fgStructure.CurrentWindow->State.JoystickLastPoll = 0;
}
/*
* Sets the mouse callback for the current window
*/
void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseFunc" );
SET_CALLBACK( Mouse );
}
/*
* Sets the mouse wheel callback for the current window
*/
void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMouseWheelFunc" );
SET_CALLBACK( MouseWheel );
}
/*
* Sets the mouse motion callback for the current window (one or more buttons
* are pressed)
*/
void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMotionFunc" );
SET_CALLBACK( Motion );
}
/*
* Sets the passive mouse motion callback for the current window (no mouse
* buttons are pressed)
*/
void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPassiveMotionFunc" );
SET_CALLBACK( Passive );
}
/*
* Window mouse entry/leave callback
*/
void FGAPIENTRY glutEntryFunc( void (* callback)( int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEntryFunc" );
SET_CALLBACK( Entry );
}
/*
* Window destruction callbacks
*/
void FGAPIENTRY glutCloseFunc( void (* callback)( void ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCloseFunc" );
SET_CALLBACK( Destroy );
}
void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWMCloseFunc" );
glutCloseFunc( callback );
}
/* A. Donev: Destruction callback for menus */
void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuDestroyFunc" );
if( fgStructure.CurrentMenu )
fgStructure.CurrentMenu->Destroy = callback;
}
/*
* Deprecated version of glutMenuStatusFunc callback setting method
*/
void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStateFunc" );
fgState.MenuStateCallback = callback;
}
/*
* Sets the global menu status callback for the current window
*/
void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMenuStatusFunc" );
fgState.MenuStatusCallback = callback;
}
/*
* Sets the overlay display callback for the current window
*/
void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutOverlayDisplayFunc" );
SET_CALLBACK( OverlayDisplay );
}
/*
* Sets the window status callback for the current window
*/
void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWindowStatusFunc" );
SET_CALLBACK( WindowStatus );
}
/*
* Sets the spaceball motion callback for the current window
*/
void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballMotionFunc" );
fgInitialiseSpaceball();
SET_CALLBACK( SpaceMotion );
}
/*
* Sets the spaceball rotate callback for the current window
*/
void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballRotateFunc" );
fgInitialiseSpaceball();
SET_CALLBACK( SpaceRotation );
}
/*
* Sets the spaceball button callback for the current window
*/
void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSpaceballButtonFunc" );
fgInitialiseSpaceball();
SET_CALLBACK( SpaceButton );
}
/*
* Sets the button box callback for the current window
*/
void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutButtonBoxFunc" );
SET_CALLBACK( ButtonBox );
}
/*
* Sets the dials box callback for the current window
*/
void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDialsFunc" );
SET_CALLBACK( Dials );
}
/*
* Sets the tablet motion callback for the current window
*/
void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletMotionFunc" );
SET_CALLBACK( TabletMotion );
}
/*
* Sets the tablet buttons callback for the current window
*/
void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutTabletButtonFunc" );
SET_CALLBACK( TabletButton );
}
/*
* Sets the multi-pointer entry callback for the current window
*/
void FGAPIENTRY glutMultiEntryFunc( void (* callback)(int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiEntryFunc" );
SET_CALLBACK( MultiEntry );
}
/*
* Sets the multi-pointer button callback for the current window
*/
void FGAPIENTRY glutMultiButtonFunc( void (* callback)(int, int, int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiButtonFunc" );
SET_CALLBACK( MultiButton );
}
/*
* Sets the multi-pointer motion callback for the current window
*/
void FGAPIENTRY glutMultiMotionFunc( void (* callback)(int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiMotionFunc" );
SET_CALLBACK( MultiMotion );
}
/*
* Sets the multi-pointer passive motion callback for the current window
*/
void FGAPIENTRY glutMultiPassiveFunc( void (* callback)(int, int, int ) )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMultiPassiveFunc" );
SET_CALLBACK( MultiPassive );
}
/*** END OF FILE ***/

View File

@ -0,0 +1,282 @@
/*
* freeglut_cursor.c
*
* The mouse cursor related stuff.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 16 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/*
* TODO BEFORE THE STABLE RELEASE:
* glutSetCursor() -- Win32 mappings are incomplete.
*
* It would be good to use custom mouse cursor shapes, and introduce
* an option to display them using glBitmap() and/or texture mapping,
* apart from the windowing system version.
*/
/* -- PRIVATE FUNCTIONS --------------------------------------------------- */
#if TARGET_HOST_POSIX_X11 || TARGET_HOST_MAC_OSX || TARGET_HOST_SOLARIS
#include <X11/cursorfont.h>
/*
* A factory method for an empty cursor
*/
static Cursor getEmptyCursor( void )
{
static Cursor cursorNone = None;
if( cursorNone == None ) {
char cursorNoneBits[ 32 ];
XColor dontCare;
Pixmap cursorNonePixmap;
memset( cursorNoneBits, 0, sizeof( cursorNoneBits ) );
memset( &dontCare, 0, sizeof( dontCare ) );
cursorNonePixmap = XCreateBitmapFromData ( fgDisplay.Display,
fgDisplay.RootWindow,
cursorNoneBits, 16, 16 );
if( cursorNonePixmap != None ) {
cursorNone = XCreatePixmapCursor( fgDisplay.Display,
cursorNonePixmap, cursorNonePixmap,
&dontCare, &dontCare, 0, 0 );
XFreePixmap( fgDisplay.Display, cursorNonePixmap );
}
}
return cursorNone;
}
typedef struct tag_cursorCacheEntry cursorCacheEntry;
struct tag_cursorCacheEntry {
unsigned int cursorShape; /* an XC_foo value */
Cursor cachedCursor; /* None if the corresponding cursor has
not been created yet */
};
/*
* Note: The arrangement of the table below depends on the fact that
* the "normal" GLUT_CURSOR_* values start a 0 and are consecutive.
*/
static cursorCacheEntry cursorCache[] = {
{ XC_arrow, None }, /* GLUT_CURSOR_RIGHT_ARROW */
{ XC_top_left_arrow, None }, /* GLUT_CURSOR_LEFT_ARROW */
{ XC_hand1, None }, /* GLUT_CURSOR_INFO */
{ XC_pirate, None }, /* GLUT_CURSOR_DESTROY */
{ XC_question_arrow, None }, /* GLUT_CURSOR_HELP */
{ XC_exchange, None }, /* GLUT_CURSOR_CYCLE */
{ XC_spraycan, None }, /* GLUT_CURSOR_SPRAY */
{ XC_watch, None }, /* GLUT_CURSOR_WAIT */
{ XC_xterm, None }, /* GLUT_CURSOR_TEXT */
{ XC_crosshair, None }, /* GLUT_CURSOR_CROSSHAIR */
{ XC_sb_v_double_arrow, None }, /* GLUT_CURSOR_UP_DOWN */
{ XC_sb_h_double_arrow, None }, /* GLUT_CURSOR_LEFT_RIGHT */
{ XC_top_side, None }, /* GLUT_CURSOR_TOP_SIDE */
{ XC_bottom_side, None }, /* GLUT_CURSOR_BOTTOM_SIDE */
{ XC_left_side, None }, /* GLUT_CURSOR_LEFT_SIDE */
{ XC_right_side, None }, /* GLUT_CURSOR_RIGHT_SIDE */
{ XC_top_left_corner, None }, /* GLUT_CURSOR_TOP_LEFT_CORNER */
{ XC_top_right_corner, None }, /* GLUT_CURSOR_TOP_RIGHT_CORNER */
{ XC_bottom_right_corner, None }, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */
{ XC_bottom_left_corner, None } /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */
};
static void fghSetCursor ( SFG_Window *window, int cursorID )
{
Cursor cursor;
/*
* XXX FULL_CROSSHAIR demotes to plain CROSSHAIR. Old GLUT allows
* for this, but if there is a system that easily supports a full-
* window (or full-screen) crosshair, we might consider it.
*/
int cursorIDToUse =
( cursorID == GLUT_CURSOR_FULL_CROSSHAIR ) ? GLUT_CURSOR_CROSSHAIR : cursorID;
if( ( cursorIDToUse >= 0 ) &&
( cursorIDToUse < sizeof( cursorCache ) / sizeof( cursorCache[0] ) ) ) {
cursorCacheEntry *entry = &cursorCache[ cursorIDToUse ];
if( entry->cachedCursor == None ) {
entry->cachedCursor =
XCreateFontCursor( fgDisplay.Display, entry->cursorShape );
}
cursor = entry->cachedCursor;
} else {
switch( cursorIDToUse )
{
case GLUT_CURSOR_NONE:
cursor = getEmptyCursor( );
break;
case GLUT_CURSOR_INHERIT:
cursor = None;
break;
default:
fgError( "Unknown cursor type: %d", cursorIDToUse );
return;
}
}
if ( cursorIDToUse == GLUT_CURSOR_INHERIT ) {
XUndefineCursor( fgDisplay.Display, window->Window.Handle );
} else if ( cursor != None ) {
XDefineCursor( fgDisplay.Display, window->Window.Handle, cursor );
} else if ( cursorIDToUse != GLUT_CURSOR_NONE ) {
fgError( "Failed to create cursor" );
}
}
static void fghWarpPointer ( int x, int y )
{
XWarpPointer(
fgDisplay.Display,
None,
fgStructure.CurrentWindow->Window.Handle,
0, 0, 0, 0,
x, y
);
/* Make the warp visible immediately. */
XFlush( fgDisplay.Display );
}
#endif
#if TARGET_HOST_MS_WINDOWS
static void fghSetCursor ( SFG_Window *window, int cursorID )
{
/*
* Joe Krahn is re-writing the following code.
*/
/* Set the cursor AND change it for this window class. */
#if !defined(__MINGW64__) && _MSC_VER <= 1200
# define MAP_CURSOR(a,b) \
case a: \
SetCursor( LoadCursor( NULL, b ) ); \
SetClassLong( window->Window.Handle, \
GCL_HCURSOR, \
( LONG )LoadCursor( NULL, b ) ); \
break;
/* Nuke the cursor AND change it for this window class. */
# define ZAP_CURSOR(a,b) \
case a: \
SetCursor( NULL ); \
SetClassLong( window->Window.Handle, \
GCL_HCURSOR, ( LONG )NULL ); \
break;
#else
# define MAP_CURSOR(a,b) \
case a: \
SetCursor( LoadCursor( NULL, b ) ); \
SetClassLongPtr( window->Window.Handle, \
GCLP_HCURSOR, \
( LONG )( LONG_PTR )LoadCursor( NULL, b ) ); \
break;
/* Nuke the cursor AND change it for this window class. */
# define ZAP_CURSOR(a,b) \
case a: \
SetCursor( NULL ); \
SetClassLongPtr( window->Window.Handle, \
GCLP_HCURSOR, ( LONG )( LONG_PTR )NULL ); \
break;
#endif
switch( cursorID )
{
MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW );
MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW );
MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HELP );
MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS );
MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP );
MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL );
MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS );
MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_IBEAM );
MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_SIZENS );
MAP_CURSOR( GLUT_CURSOR_LEFT_RIGHT, IDC_SIZEWE );
MAP_CURSOR( GLUT_CURSOR_TOP_SIDE, IDC_ARROW ); /* XXX ToDo */
MAP_CURSOR( GLUT_CURSOR_BOTTOM_SIDE, IDC_ARROW ); /* XXX ToDo */
MAP_CURSOR( GLUT_CURSOR_LEFT_SIDE, IDC_ARROW ); /* XXX ToDo */
MAP_CURSOR( GLUT_CURSOR_RIGHT_SIDE, IDC_ARROW ); /* XXX ToDo */
MAP_CURSOR( GLUT_CURSOR_TOP_LEFT_CORNER, IDC_SIZENWSE );
MAP_CURSOR( GLUT_CURSOR_TOP_RIGHT_CORNER, IDC_SIZENESW );
MAP_CURSOR( GLUT_CURSOR_BOTTOM_RIGHT_CORNER, IDC_SIZENWSE );
MAP_CURSOR( GLUT_CURSOR_BOTTOM_LEFT_CORNER, IDC_SIZENESW );
MAP_CURSOR( GLUT_CURSOR_INHERIT, IDC_ARROW ); /* XXX ToDo */
ZAP_CURSOR( GLUT_CURSOR_NONE, NULL );
MAP_CURSOR( GLUT_CURSOR_FULL_CROSSHAIR, IDC_CROSS ); /* XXX ToDo */
default:
fgError( "Unknown cursor type: %d", cursorID );
break;
}
}
static void fghWarpPointer ( int x, int y )
{
POINT coords;
coords.x = x;
coords.y = y;
/* ClientToScreen() translates {coords} for us. */
ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords );
SetCursorPos( coords.x, coords.y );
}
#endif
/* -- INTERNAL FUNCTIONS ---------------------------------------------------- */
void fgSetCursor ( SFG_Window *window, int cursorID )
{
fghSetCursor ( window, cursorID );
}
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* Set the cursor image to be used for the current window
*/
void FGAPIENTRY glutSetCursor( int cursorID )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetCursor" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetCursor" );
fghSetCursor ( fgStructure.CurrentWindow, cursorID );
fgStructure.CurrentWindow->State.Cursor = cursorID;
}
/*
* Moves the mouse pointer to given window coordinates
*/
void FGAPIENTRY glutWarpPointer( int x, int y )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWarpPointer" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutWarpPointer" );
fghWarpPointer ( x, y );
}
/*** END OF FILE ***/

View File

@ -0,0 +1,103 @@
/*
* freeglut_display.c
*
* Display message posting, context buffer swapping.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Fri Dec 3 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* Marks the current window to have the redisplay performed when possible...
*/
void FGAPIENTRY glutPostRedisplay( void )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPostRedisplay" );
if ( ! fgStructure.CurrentWindow )
{
fgError ( " ERROR: Function <%s> called"
" with no current window defined.", "glutPostRedisplay" ) ;
}
fgStructure.CurrentWindow->State.Redisplay = GL_TRUE;
}
/*
* Swaps the buffers for the current window (if any)
*/
void FGAPIENTRY glutSwapBuffers( void )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSwapBuffers" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSwapBuffers" );
/*
* "glXSwapBuffers" already performs an implicit call to "glFlush". What
* about "SwapBuffers"?
*/
glFlush( );
if( ! fgStructure.CurrentWindow->Window.DoubleBuffered )
return;
#if TARGET_HOST_POSIX_X11
glXSwapBuffers( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
#elif TARGET_HOST_MS_WINDOWS
SwapBuffers( fgStructure.CurrentWindow->Window.Device );
#endif
/* GLUT_FPS env var support */
if( fgState.FPSInterval )
{
GLint t = glutGet( GLUT_ELAPSED_TIME );
fgState.SwapCount++;
if( fgState.SwapTime == 0 )
fgState.SwapTime = t;
else if( t - fgState.SwapTime > fgState.FPSInterval )
{
float time = 0.001f * ( t - fgState.SwapTime );
float fps = ( float )fgState.SwapCount / time;
fprintf( stderr,
"freeglut: %d frames in %.2f seconds = %.2f FPS\n",
fgState.SwapCount, time, fps );
fgState.SwapTime = t;
fgState.SwapCount = 0;
}
}
}
/*
* Mark appropriate window to be displayed
*/
void FGAPIENTRY glutPostWindowRedisplay( int windowID )
{
SFG_Window* window;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPostWindowRedisplay" );
window = fgWindowByID( windowID );
freeglut_return_if_fail( window );
window->State.Redisplay = GL_TRUE;
}
/*** END OF FILE ***/

View File

@ -0,0 +1,233 @@
/*
* freeglut_ext.c
*
* Functions related to OpenGL extensions.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 9 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define GLX_GLXEXT_PROTOTYPES
#include <GL/freeglut.h>
#include "freeglut_internal.h"
static GLUTproc fghGetGLUTProcAddress( const char* procName )
{
/* optimization: quick initial check */
if( strncmp( procName, "glut", 4 ) != 0 )
return NULL;
#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x;
CHECK_NAME(glutInit);
CHECK_NAME(glutInitDisplayMode);
CHECK_NAME(glutInitDisplayString);
CHECK_NAME(glutInitWindowPosition);
CHECK_NAME(glutInitWindowSize);
CHECK_NAME(glutMainLoop);
CHECK_NAME(glutExit);
CHECK_NAME(glutCreateWindow);
CHECK_NAME(glutCreateSubWindow);
CHECK_NAME(glutDestroyWindow);
CHECK_NAME(glutPostRedisplay);
CHECK_NAME(glutPostWindowRedisplay);
CHECK_NAME(glutSwapBuffers);
CHECK_NAME(glutGetWindow);
CHECK_NAME(glutSetWindow);
CHECK_NAME(glutSetWindowTitle);
CHECK_NAME(glutSetIconTitle);
CHECK_NAME(glutPositionWindow);
CHECK_NAME(glutReshapeWindow);
CHECK_NAME(glutPopWindow);
CHECK_NAME(glutPushWindow);
CHECK_NAME(glutIconifyWindow);
CHECK_NAME(glutShowWindow);
CHECK_NAME(glutHideWindow);
CHECK_NAME(glutFullScreen);
CHECK_NAME(glutSetCursor);
CHECK_NAME(glutWarpPointer);
CHECK_NAME(glutEstablishOverlay);
CHECK_NAME(glutRemoveOverlay);
CHECK_NAME(glutUseLayer);
CHECK_NAME(glutPostOverlayRedisplay);
CHECK_NAME(glutPostWindowOverlayRedisplay);
CHECK_NAME(glutShowOverlay);
CHECK_NAME(glutHideOverlay);
CHECK_NAME(glutCreateMenu);
CHECK_NAME(glutDestroyMenu);
CHECK_NAME(glutGetMenu);
CHECK_NAME(glutSetMenu);
CHECK_NAME(glutAddMenuEntry);
CHECK_NAME(glutAddSubMenu);
CHECK_NAME(glutChangeToMenuEntry);
CHECK_NAME(glutChangeToSubMenu);
CHECK_NAME(glutRemoveMenuItem);
CHECK_NAME(glutAttachMenu);
CHECK_NAME(glutDetachMenu);
CHECK_NAME(glutDisplayFunc);
CHECK_NAME(glutReshapeFunc);
CHECK_NAME(glutKeyboardFunc);
CHECK_NAME(glutMouseFunc);
CHECK_NAME(glutMultiEntryFunc);
CHECK_NAME(glutMultiMotionFunc);
CHECK_NAME(glutMultiButtonFunc);
CHECK_NAME(glutMultiPassiveFunc);
CHECK_NAME(glutMotionFunc);
CHECK_NAME(glutPassiveMotionFunc);
CHECK_NAME(glutEntryFunc);
CHECK_NAME(glutVisibilityFunc);
CHECK_NAME(glutIdleFunc);
CHECK_NAME(glutTimerFunc);
CHECK_NAME(glutMenuStateFunc);
CHECK_NAME(glutSpecialFunc);
CHECK_NAME(glutSpaceballMotionFunc);
CHECK_NAME(glutSpaceballRotateFunc);
CHECK_NAME(glutSpaceballButtonFunc);
CHECK_NAME(glutButtonBoxFunc);
CHECK_NAME(glutDialsFunc);
CHECK_NAME(glutTabletMotionFunc);
CHECK_NAME(glutTabletButtonFunc);
CHECK_NAME(glutMenuStatusFunc);
CHECK_NAME(glutOverlayDisplayFunc);
CHECK_NAME(glutWindowStatusFunc);
CHECK_NAME(glutKeyboardUpFunc);
CHECK_NAME(glutSpecialUpFunc);
#if !defined(_WIN32_WCE)
CHECK_NAME(glutJoystickFunc);
#endif /* !defined(_WIN32_WCE) */
CHECK_NAME(glutSetColor);
CHECK_NAME(glutGetColor);
CHECK_NAME(glutCopyColormap);
CHECK_NAME(glutGet);
CHECK_NAME(glutDeviceGet);
CHECK_NAME(glutExtensionSupported);
CHECK_NAME(glutGetModifiers);
CHECK_NAME(glutLayerGet);
CHECK_NAME(glutBitmapCharacter);
CHECK_NAME(glutBitmapWidth);
CHECK_NAME(glutStrokeCharacter);
CHECK_NAME(glutStrokeWidth);
CHECK_NAME(glutBitmapLength);
CHECK_NAME(glutStrokeLength);
CHECK_NAME(glutWireSphere);
CHECK_NAME(glutSolidSphere);
CHECK_NAME(glutWireCone);
CHECK_NAME(glutSolidCone);
CHECK_NAME(glutWireCube);
CHECK_NAME(glutSolidCube);
CHECK_NAME(glutWireTorus);
CHECK_NAME(glutSolidTorus);
CHECK_NAME(glutWireDodecahedron);
CHECK_NAME(glutSolidDodecahedron);
CHECK_NAME(glutWireTeapot);
CHECK_NAME(glutSolidTeapot);
CHECK_NAME(glutWireOctahedron);
CHECK_NAME(glutSolidOctahedron);
CHECK_NAME(glutWireTetrahedron);
CHECK_NAME(glutSolidTetrahedron);
CHECK_NAME(glutWireIcosahedron);
CHECK_NAME(glutSolidIcosahedron);
CHECK_NAME(glutVideoResizeGet);
CHECK_NAME(glutSetupVideoResizing);
CHECK_NAME(glutStopVideoResizing);
CHECK_NAME(glutVideoResize);
CHECK_NAME(glutVideoPan);
CHECK_NAME(glutReportErrors);
CHECK_NAME(glutIgnoreKeyRepeat);
CHECK_NAME(glutSetKeyRepeat);
#if !defined(_WIN32_WCE)
CHECK_NAME(glutForceJoystickFunc);
CHECK_NAME(glutGameModeString);
CHECK_NAME(glutEnterGameMode);
CHECK_NAME(glutLeaveGameMode);
CHECK_NAME(glutGameModeGet);
#endif /* !defined(_WIN32_WCE) */
/* freeglut extensions */
CHECK_NAME(glutMainLoopEvent);
CHECK_NAME(glutLeaveMainLoop);
CHECK_NAME(glutCloseFunc);
CHECK_NAME(glutWMCloseFunc);
CHECK_NAME(glutMenuDestroyFunc);
CHECK_NAME(glutFullScreenToggle);
CHECK_NAME(glutLeaveFullScreen);
CHECK_NAME(glutSetOption);
CHECK_NAME(glutGetModeValues);
CHECK_NAME(glutSetWindowData);
CHECK_NAME(glutGetWindowData);
CHECK_NAME(glutSetMenuData);
CHECK_NAME(glutGetMenuData);
CHECK_NAME(glutBitmapHeight);
CHECK_NAME(glutStrokeHeight);
CHECK_NAME(glutBitmapString);
CHECK_NAME(glutStrokeString);
CHECK_NAME(glutWireRhombicDodecahedron);
CHECK_NAME(glutSolidRhombicDodecahedron);
CHECK_NAME(glutWireSierpinskiSponge);
CHECK_NAME(glutSolidSierpinskiSponge);
CHECK_NAME(glutWireCylinder);
CHECK_NAME(glutSolidCylinder);
CHECK_NAME(glutGetProcAddress);
CHECK_NAME(glutMouseWheelFunc);
CHECK_NAME(glutJoystickGetNumAxes);
CHECK_NAME(glutJoystickGetNumButtons);
CHECK_NAME(glutJoystickNotWorking);
CHECK_NAME(glutJoystickGetDeadBand);
CHECK_NAME(glutJoystickSetDeadBand);
CHECK_NAME(glutJoystickGetSaturation);
CHECK_NAME(glutJoystickSetSaturation);
CHECK_NAME(glutJoystickSetMinRange);
CHECK_NAME(glutJoystickSetMaxRange);
CHECK_NAME(glutJoystickSetCenter);
CHECK_NAME(glutJoystickGetMinRange);
CHECK_NAME(glutJoystickGetMaxRange);
CHECK_NAME(glutJoystickGetCenter);
CHECK_NAME(glutInitContextVersion);
CHECK_NAME(glutInitContextFlags);
CHECK_NAME(glutInitContextProfile);
CHECK_NAME(glutInitErrorFunc);
CHECK_NAME(glutInitWarningFunc);
#undef CHECK_NAME
return NULL;
}
SFG_Proc fghGetProcAddress( const char *procName )
{
#if TARGET_HOST_MS_WINDOWS
return (SFG_Proc)wglGetProcAddress( ( LPCSTR )procName );
#elif TARGET_HOST_POSIX_X11 && defined( GLX_ARB_get_proc_address )
return (SFG_Proc)glXGetProcAddressARB( ( const GLubyte * )procName );
#else
return NULL;
#endif
}
GLUTproc FGAPIENTRY
glutGetProcAddress( const char *procName )
{
GLUTproc p;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetProcAddress" );
/* Try GLUT functions first, then core GL functions */
p = fghGetGLUTProcAddress( procName );
return ( p != NULL ) ? p : fghGetProcAddress( procName );
}

View File

@ -0,0 +1,384 @@
/*
* freeglut_font.c
*
* Bitmap and stroke fonts displaying.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 16 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/*
* TODO BEFORE THE STABLE RELEASE:
*
* Test things out ...
*/
/* -- IMPORT DECLARATIONS -------------------------------------------------- */
/*
* These are the font faces defined in freeglut_font_data.c file:
*/
extern SFG_Font fgFontFixed8x13;
extern SFG_Font fgFontFixed9x15;
extern SFG_Font fgFontHelvetica10;
extern SFG_Font fgFontHelvetica12;
extern SFG_Font fgFontHelvetica18;
extern SFG_Font fgFontTimesRoman10;
extern SFG_Font fgFontTimesRoman24;
extern SFG_StrokeFont fgStrokeRoman;
extern SFG_StrokeFont fgStrokeMonoRoman;
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
/*
* Matches a font ID with a SFG_Font structure pointer.
* This was changed to match the GLUT header style.
*/
static SFG_Font* fghFontByID( void* font )
{
if( font == GLUT_BITMAP_8_BY_13 )
return &fgFontFixed8x13;
if( font == GLUT_BITMAP_9_BY_15 )
return &fgFontFixed9x15;
if( font == GLUT_BITMAP_HELVETICA_10 )
return &fgFontHelvetica10;
if( font == GLUT_BITMAP_HELVETICA_12 )
return &fgFontHelvetica12;
if( font == GLUT_BITMAP_HELVETICA_18 )
return &fgFontHelvetica18;
if( font == GLUT_BITMAP_TIMES_ROMAN_10 )
return &fgFontTimesRoman10;
if( font == GLUT_BITMAP_TIMES_ROMAN_24 )
return &fgFontTimesRoman24;
fgWarning( "font 0x%08x not found", font );
return 0;
}
/*
* Matches a font ID with a SFG_StrokeFont structure pointer.
* This was changed to match the GLUT header style.
*/
static SFG_StrokeFont* fghStrokeByID( void* font )
{
if( font == GLUT_STROKE_ROMAN )
return &fgStrokeRoman;
if( font == GLUT_STROKE_MONO_ROMAN )
return &fgStrokeMonoRoman;
fgWarning( "stroke font 0x%08x not found", font );
return 0;
}
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* Draw a bitmap character
*/
void FGAPIENTRY glutBitmapCharacter( void* fontID, int character )
{
const GLubyte* face;
SFG_Font* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapCharacter" );
font = fghFontByID( fontID );
freeglut_return_if_fail( ( character >= 1 )&&( character < 256 ) );
freeglut_return_if_fail( font );
/*
* Find the character we want to draw (???)
*/
face = font->Characters[ character ];
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glBitmap(
face[ 0 ], font->Height, /* The bitmap's width and height */
font->xorig, font->yorig, /* The origin in the font glyph */
( float )( face[ 0 ] ), 0.0, /* The raster advance -- inc. x,y */
( face + 1 ) /* The packed bitmap data... */
);
glPopClientAttrib( );
}
void FGAPIENTRY glutBitmapString( void* fontID, const unsigned char *string )
{
unsigned char c;
float x = 0.0f ;
SFG_Font* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapString" );
font = fghFontByID( fontID );
freeglut_return_if_fail( font );
if ( !string || ! *string )
return;
glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
/*
* Step through the string, drawing each character.
* A newline will simply translate the next character's insertion
* point back to the start of the line and down one line.
*/
while( ( c = *string++) )
if( c == '\n' )
{
glBitmap ( 0, 0, 0, 0, -x, (float) -font->Height, NULL );
x = 0.0f;
}
else /* Not an EOL, draw the bitmap character */
{
const GLubyte* face = font->Characters[ c ];
glBitmap(
face[ 0 ], font->Height, /* Bitmap's width and height */
font->xorig, font->yorig, /* The origin in the font glyph */
( float )( face[ 0 ] ), 0.0, /* The raster advance; inc. x,y */
( face + 1 ) /* The packed bitmap data... */
);
x += ( float )( face[ 0 ] );
}
glPopClientAttrib( );
}
/*
* Returns the width in pixels of a font's character
*/
int FGAPIENTRY glutBitmapWidth( void* fontID, int character )
{
SFG_Font* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapWidth" );
font = fghFontByID( fontID );
freeglut_return_val_if_fail( character > 0 && character < 256, 0 );
freeglut_return_val_if_fail( font, 0 );
return *( font->Characters[ character ] );
}
/*
* Return the width of a string drawn using a bitmap font
*/
int FGAPIENTRY glutBitmapLength( void* fontID, const unsigned char* string )
{
unsigned char c;
int length = 0, this_line_length = 0;
SFG_Font* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapLength" );
font = fghFontByID( fontID );
freeglut_return_val_if_fail( font, 0 );
if ( !string || ! *string )
return 0;
while( ( c = *string++) )
{
if( c != '\n' )/* Not an EOL, increment length of line */
this_line_length += *( font->Characters[ c ]);
else /* EOL; reset the length of this line */
{
if( length < this_line_length )
length = this_line_length;
this_line_length = 0;
}
}
if ( length < this_line_length )
length = this_line_length;
return length;
}
/*
* Returns the height of a bitmap font
*/
int FGAPIENTRY glutBitmapHeight( void* fontID )
{
SFG_Font* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutBitmapHeight" );
font = fghFontByID( fontID );
freeglut_return_val_if_fail( font, 0 );
return font->Height;
}
/*
* Draw a stroke character
*/
void FGAPIENTRY glutStrokeCharacter( void* fontID, int character )
{
const SFG_StrokeChar *schar;
const SFG_StrokeStrip *strip;
int i, j;
SFG_StrokeFont* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeCharacter" );
font = fghStrokeByID( fontID );
freeglut_return_if_fail( character >= 0 );
freeglut_return_if_fail( character < font->Quantity );
freeglut_return_if_fail( font );
schar = font->Characters[ character ];
freeglut_return_if_fail( schar );
strip = schar->Strips;
for( i = 0; i < schar->Number; i++, strip++ )
{
glBegin( GL_LINE_STRIP );
for( j = 0; j < strip->Number; j++ )
glVertex2f( strip->Vertices[ j ].X, strip->Vertices[ j ].Y );
glEnd( );
glBegin( GL_POINTS );
for( j = 0; j < strip->Number; j++ )
glVertex2f( strip->Vertices[ j ].X, strip->Vertices[ j ].Y );
glEnd( );
}
glTranslatef( schar->Right, 0.0, 0.0 );
}
void FGAPIENTRY glutStrokeString( void* fontID, const unsigned char *string )
{
unsigned char c;
int i, j;
float length = 0.0;
SFG_StrokeFont* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeString" );
font = fghStrokeByID( fontID );
freeglut_return_if_fail( font );
if ( !string || ! *string )
return;
/*
* Step through the string, drawing each character.
* A newline will simply translate the next character's insertion
* point back to the start of the line and down one line.
*/
while( ( c = *string++) )
if( c < font->Quantity )
{
if( c == '\n' )
{
glTranslatef ( -length, -( float )( font->Height ), 0.0 );
length = 0.0;
}
else /* Not an EOL, draw the bitmap character */
{
const SFG_StrokeChar *schar = font->Characters[ c ];
if( schar )
{
const SFG_StrokeStrip *strip = schar->Strips;
for( i = 0; i < schar->Number; i++, strip++ )
{
glBegin( GL_LINE_STRIP );
for( j = 0; j < strip->Number; j++ )
glVertex2f( strip->Vertices[ j ].X,
strip->Vertices[ j ].Y);
glEnd( );
}
length += schar->Right;
glTranslatef( schar->Right, 0.0, 0.0 );
}
}
}
}
/*
* Return the width in pixels of a stroke character
*/
int FGAPIENTRY glutStrokeWidth( void* fontID, int character )
{
const SFG_StrokeChar *schar;
SFG_StrokeFont* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeWidth" );
font = fghStrokeByID( fontID );
freeglut_return_val_if_fail( ( character >= 0 ) &&
( character < font->Quantity ),
0
);
freeglut_return_val_if_fail( font, 0 );
schar = font->Characters[ character ];
freeglut_return_val_if_fail( schar, 0 );
return ( int )( schar->Right + 0.5 );
}
/*
* Return the width of a string drawn using a stroke font
*/
int FGAPIENTRY glutStrokeLength( void* fontID, const unsigned char* string )
{
unsigned char c;
float length = 0.0;
float this_line_length = 0.0;
SFG_StrokeFont* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeLength" );
font = fghStrokeByID( fontID );
freeglut_return_val_if_fail( font, 0 );
if ( !string || ! *string )
return 0;
while( ( c = *string++) )
if( c < font->Quantity )
{
if( c == '\n' ) /* EOL; reset the length of this line */
{
if( length < this_line_length )
length = this_line_length;
this_line_length = 0.0;
}
else /* Not an EOL, increment the length of this line */
{
const SFG_StrokeChar *schar = font->Characters[ c ];
if( schar )
this_line_length += schar->Right;
}
}
if( length < this_line_length )
length = this_line_length;
return( int )( length + 0.5 );
}
/*
* Returns the height of a stroke font
*/
GLfloat FGAPIENTRY glutStrokeHeight( void* fontID )
{
SFG_StrokeFont* font;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutStrokeHeight" );
font = fghStrokeByID( fontID );
freeglut_return_val_if_fail( font, 0.0 );
return font->Height;
}
/*** END OF FILE ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,819 @@
/*
* freeglut_gamemode.c
*
* The game mode handling code.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 16 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/*
* TODO BEFORE THE STABLE RELEASE:
*
* glutGameModeString() -- missing
* glutEnterGameMode() -- X11 version
* glutLeaveGameMode() -- is that correct?
* glutGameModeGet() -- is that correct?
*/
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
#if TARGET_HOST_POSIX_X11
static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
{
#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
int event_base, error_base, ver_major, ver_minor, use_rate;
XRRScreenConfiguration *xrr_config = 0;
Status result = -1;
/* must check at runtime for the availability of the extension */
if(!XRRQueryExtension(fgDisplay.Display, &event_base, &error_base)) {
return -1;
}
XRRQueryVersion(fgDisplay.Display, &ver_major, &ver_minor);
/* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and
* the user actually cares about it (rate > 0)
*/
use_rate = ( rate > 0 ) && ( ( ver_major >= 1 ) ||
( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) );
/* this loop is only so that the whole thing will be repeated if someone
* else changes video mode between our query of the current information and
* the attempt to change it.
*/
do {
XRRScreenSize *ssizes;
short *rates;
Rotation rot;
int i, ssizes_count, rates_count, curr, res_idx = -1;
Time timestamp, cfg_timestamp;
if(xrr_config) {
XRRFreeScreenConfigInfo(xrr_config);
}
if(!(xrr_config = XRRGetScreenInfo(fgDisplay.Display, fgDisplay.RootWindow))) {
fgWarning("XRRGetScreenInfo failed");
break;
}
ssizes = XRRConfigSizes(xrr_config, &ssizes_count);
curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp);
/* if either of xsz or ysz are unspecified, use the current values */
if(xsz <= 0)
xsz = fgState.GameModeSize.X = ssizes[curr].width;
if(ysz <= 0)
ysz = fgState.GameModeSize.Y = ssizes[curr].height;
if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) {
/* no need to switch, we're already in the requested resolution */
res_idx = curr;
} else {
for(i=0; i<ssizes_count; i++) {
if(ssizes[i].width == xsz && ssizes[i].height == ysz) {
res_idx = i;
break; /* found it */
}
}
}
if(res_idx == -1)
break; /* no matching resolution */
#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
if(use_rate) {
rate = fgState.GameModeRefresh;
/* for the selected resolution, let's find out if there is
* a matching refresh rate available.
*/
rates = XRRConfigRates(xrr_config, res_idx, &rates_count);
for(i=0; i<rates_count; i++) {
if(rates[i] == rate) {
break;
}
}
if(i == rates_count) {
break; /* no matching rate */
}
}
#endif
if(just_checking) {
result = 0;
break;
}
#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
if(use_rate)
result = XRRSetScreenConfigAndRate(fgDisplay.Display, xrr_config,
fgDisplay.RootWindow, res_idx, rot, rate, timestamp);
else
#endif
result = XRRSetScreenConfig(fgDisplay.Display, xrr_config,
fgDisplay.RootWindow, res_idx, rot, timestamp);
} while(result == RRSetConfigInvalidTime);
if(xrr_config) {
XRRFreeScreenConfigInfo(xrr_config);
}
if(result == 0) {
return 0;
}
#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */
return -1;
}
#endif /* TARGET_HOST_POSIX_X11 */
/*
* Remembers the current visual settings, so that
* we can change them and restore later...
*/
static void fghRememberState( void )
{
#if TARGET_HOST_POSIX_X11
int event_base, error_base;
/*
* Remember the current pointer location before going fullscreen
* for restoring it later:
*/
Window junk_window;
unsigned int junk_mask;
XQueryPointer(fgDisplay.Display, fgDisplay.RootWindow,
&junk_window, &junk_window,
&fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY,
&fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY, &junk_mask);
# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
if(XRRQueryExtension(fgDisplay.Display, &event_base, &error_base)) {
XRRScreenConfiguration *xrr_config;
XRRScreenSize *ssizes;
Rotation rot;
int ssize_count, curr;
if((xrr_config = XRRGetScreenInfo(fgDisplay.Display, fgDisplay.RootWindow))) {
ssizes = XRRConfigSizes(xrr_config, &ssize_count);
curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
fgDisplay.prev_xsz = ssizes[curr].width;
fgDisplay.prev_ysz = ssizes[curr].height;
fgDisplay.prev_refresh = -1;
# if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
if(fgState.GameModeRefresh != -1) {
fgDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config);
}
# endif
fgDisplay.prev_size_valid = 1;
XRRFreeScreenConfigInfo(xrr_config);
}
}
# endif
/*
* This highly depends on the XFree86 extensions,
* not approved as X Consortium standards
*/
# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
if(!XF86VidModeQueryExtension(fgDisplay.Display, &event_base, &error_base)) {
return;
}
/*
* Remember the current ViewPort location of the screen to be able to
* restore the ViewPort on LeaveGameMode():
*/
if( !XF86VidModeGetViewPort(
fgDisplay.Display,
fgDisplay.Screen,
&fgDisplay.DisplayViewPortX,
&fgDisplay.DisplayViewPortY ) )
fgWarning( "XF86VidModeGetViewPort failed" );
/* Query the current display settings: */
fgDisplay.DisplayModeValid =
XF86VidModeGetModeLine(
fgDisplay.Display,
fgDisplay.Screen,
&fgDisplay.DisplayModeClock,
&fgDisplay.DisplayMode
);
if( !fgDisplay.DisplayModeValid )
fgWarning( "XF86VidModeGetModeLine failed" );
# endif
#elif TARGET_HOST_MS_WINDOWS
/* DEVMODE devMode; */
/* Grab the current desktop settings... */
/* hack to get around my stupid cross-gcc headers */
#define FREEGLUT_ENUM_CURRENT_SETTINGS -1
EnumDisplaySettings( fgDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS,
&fgDisplay.DisplayMode );
/* Make sure we will be restoring all settings needed */
fgDisplay.DisplayMode.dmFields |=
DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
#endif
}
/*
* Restores the previously remembered visual settings
*/
static void fghRestoreState( void )
{
#if TARGET_HOST_POSIX_X11
/* Restore the remembered pointer position: */
XWarpPointer(
fgDisplay.Display, None, fgDisplay.RootWindow, 0, 0, 0, 0,
fgDisplay.DisplayPointerX, fgDisplay.DisplayPointerY
);
# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
if(fgDisplay.prev_size_valid) {
if(xrandr_resize(fgDisplay.prev_xsz, fgDisplay.prev_ysz, fgDisplay.prev_refresh, 0) != -1) {
fgDisplay.prev_size_valid = 0;
# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
fgDisplay.DisplayModeValid = 0;
# endif
return;
}
}
# endif
# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
/*
* This highly depends on the XFree86 extensions,
* not approved as X Consortium standards
*/
if( fgDisplay.DisplayModeValid )
{
XF86VidModeModeInfo** displayModes;
int i, displayModesCount;
if( !XF86VidModeGetAllModeLines(
fgDisplay.Display,
fgDisplay.Screen,
&displayModesCount,
&displayModes ) )
{
fgWarning( "XF86VidModeGetAllModeLines failed" );
return;
}
/*
* Check every of the modes looking for one that matches our demands.
* If we find one, switch to it and restore the remembered viewport.
*/
for( i = 0; i < displayModesCount; i++ )
{
if(displayModes[ i ]->hdisplay == fgDisplay.DisplayMode.hdisplay &&
displayModes[ i ]->vdisplay == fgDisplay.DisplayMode.vdisplay &&
displayModes[ i ]->dotclock == fgDisplay.DisplayModeClock )
{
if( !XF86VidModeSwitchToMode(
fgDisplay.Display,
fgDisplay.Screen,
displayModes[ i ] ) )
{
fgWarning( "XF86VidModeSwitchToMode failed" );
break;
}
if( !XF86VidModeSetViewPort(
fgDisplay.Display,
fgDisplay.Screen,
fgDisplay.DisplayViewPortX,
fgDisplay.DisplayViewPortY ) )
fgWarning( "XF86VidModeSetViewPort failed" );
/*
* For the case this would be the last X11 call the application
* calls exit() we've to flush the X11 output queue to have the
* commands sent to the X server before the application exits.
*/
XFlush( fgDisplay.Display );
fgDisplay.DisplayModeValid = 0;
# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
fgDisplay.prev_size_valid = 0;
# endif
break;
}
}
XFree( displayModes );
}
# endif
#elif TARGET_HOST_MS_WINDOWS
/* Restore the previously remembered desktop display settings */
ChangeDisplaySettingsEx( fgDisplay.DisplayName,&fgDisplay.DisplayMode, 0,0,0 );
#endif
}
#if TARGET_HOST_POSIX_X11
#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
/*
* Checks a single display mode settings against user's preferences.
*/
static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
{
/* The desired values should be stored in fgState structure... */
return ( width == fgState.GameModeSize.X ) &&
( height == fgState.GameModeSize.Y ) &&
( depth == fgState.GameModeDepth ) &&
( refresh == fgState.GameModeRefresh );
}
/*
* Checks all display modes settings against user's preferences.
* Returns the mode number found or -1 if none could be found.
*/
static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes )
{
int i;
for( i = 0; i < displayModesCount; i++ )
{
/* Compute the displays refresh rate, dotclock comes in kHz. */
int refresh = ( displayModes[ i ]->dotclock * 1000 ) /
( displayModes[ i ]->htotal * displayModes[ i ]->vtotal );
if( fghCheckDisplayMode( displayModes[ i ]->hdisplay,
displayModes[ i ]->vdisplay,
fgState.GameModeDepth,
( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) {
if (!exactMatch)
{
/* Update the chosen refresh rate, otherwise a
* glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not
* return the right values
*/
fgState.GameModeRefresh = refresh;
}
return i;
}
}
return -1;
}
#endif
#endif
/*
* Changes the current display mode to match user's settings
*/
static GLboolean fghChangeDisplayMode( GLboolean haveToTest )
{
GLboolean success = GL_FALSE;
#if TARGET_HOST_POSIX_X11
/* first try to use XRandR, then fallback to XF86VidMode */
# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y,
fgState.GameModeRefresh, haveToTest) != -1) {
return GL_TRUE;
}
# endif
/*
* This highly depends on the XFree86 extensions,
* not approved as X Consortium standards
*/
# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
/*
* This is also used by applications which check modes by calling
* glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:
*/
if( haveToTest || fgDisplay.DisplayModeValid )
{
XF86VidModeModeInfo** displayModes;
int i, displayModesCount;
/* If we don't have a valid modeline in the display structure, which
* can happen if this is called from glutGameModeGet instead of
* glutEnterGameMode, then we need to query the current mode, to make
* unspecified settings to default to their current values.
*/
if(!fgDisplay.DisplayModeValid) {
if(!XF86VidModeGetModeLine(fgDisplay.Display, fgDisplay.Screen,
&fgDisplay.DisplayModeClock, &fgDisplay.DisplayMode)) {
return success;
}
}
if (fgState.GameModeSize.X == -1)
{
fgState.GameModeSize.X = fgDisplay.DisplayMode.hdisplay;
}
if (fgState.GameModeSize.Y == -1)
{
fgState.GameModeSize.Y = fgDisplay.DisplayMode.vdisplay;
}
if (fgState.GameModeDepth == -1)
{
/* can't get color depth from this, nor can we change it, do nothing
* TODO: get with XGetVisualInfo()? but then how to set?
*/
}
if (fgState.GameModeRefresh == -1)
{
/* Compute the displays refresh rate, dotclock comes in kHz. */
int refresh = ( fgDisplay.DisplayModeClock * 1000 ) /
( fgDisplay.DisplayMode.htotal * fgDisplay.DisplayMode.vtotal );
fgState.GameModeRefresh = refresh;
}
/* query all possible display modes */
if( !XF86VidModeGetAllModeLines(
fgDisplay.Display,
fgDisplay.Screen,
&displayModesCount,
&displayModes ) )
{
fgWarning( "XF86VidModeGetAllModeLines failed" );
return success;
}
/*
* Check every of the modes looking for one that matches our demands,
* ignoring the refresh rate if no exact match could be found.
*/
i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes );
if( i < 0 ) {
i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes );
}
success = ( i < 0 ) ? GL_FALSE : GL_TRUE;
if( !haveToTest && success ) {
if( !XF86VidModeSwitchToMode(
fgDisplay.Display,
fgDisplay.Screen,
displayModes[ i ] ) )
fgWarning( "XF86VidModeSwitchToMode failed" );
}
XFree( displayModes );
}
# endif
#elif TARGET_HOST_MS_WINDOWS
DEVMODE devMode;
char *fggmstr = NULL;
char displayMode[300];
success = GL_FALSE;
EnumDisplaySettings( fgDisplay.DisplayName, -1, &devMode );
devMode.dmFields = 0;
if (fgState.GameModeSize.X!=-1)
{
devMode.dmPelsWidth = fgState.GameModeSize.X;
devMode.dmFields |= DM_PELSWIDTH;
}
if (fgState.GameModeSize.Y!=-1)
{
devMode.dmPelsHeight = fgState.GameModeSize.Y;
devMode.dmFields |= DM_PELSHEIGHT;
}
if (fgState.GameModeDepth!=-1)
{
devMode.dmBitsPerPel = fgState.GameModeDepth;
devMode.dmFields |= DM_BITSPERPEL;
}
if (fgState.GameModeRefresh!=-1)
{
devMode.dmDisplayFrequency = fgState.GameModeRefresh;
devMode.dmFields |= DM_DISPLAYFREQUENCY;
}
switch ( ChangeDisplaySettingsEx(fgDisplay.DisplayName, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) )
{
case DISP_CHANGE_SUCCESSFUL:
success = GL_TRUE;
if (!haveToTest)
{
/* update vars in case if windows switched to proper mode */
EnumDisplaySettings( fgDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode );
fgState.GameModeSize.X = devMode.dmPelsWidth;
fgState.GameModeSize.Y = devMode.dmPelsHeight;
fgState.GameModeDepth = devMode.dmBitsPerPel;
fgState.GameModeRefresh = devMode.dmDisplayFrequency;
}
break;
case DISP_CHANGE_RESTART:
fggmstr = "The computer must be restarted for the graphics mode to work.";
break;
case DISP_CHANGE_BADFLAGS:
fggmstr = "An invalid set of flags was passed in.";
break;
case DISP_CHANGE_BADPARAM:
fggmstr = "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
break;
case DISP_CHANGE_FAILED:
fggmstr = "The display driver failed the specified graphics mode.";
break;
case DISP_CHANGE_BADMODE:
fggmstr = "The graphics mode is not supported.";
break;
default:
fggmstr = "Unknown error in graphics mode???"; /* dunno if it is possible,MSDN does not mention any other error */
break;
}
if ( !success )
{
/* I'd rather get info whats going on in my program than wonder about */
/* magic happenings behind my back, its lib for devels at last ;) */
/* append display mode to error to make things more informative */
sprintf(displayMode,"%s Problem with requested mode: %ix%i:%i@%i", fggmstr, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel, devMode.dmDisplayFrequency);
fgWarning(displayMode);
}
#endif
return success;
}
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* Sets the game mode display string
*/
void FGAPIENTRY glutGameModeString( const char* string )
{
int width = -1, height = -1, depth = -1, refresh = -1;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeString" );
/*
* This one seems a bit easier than glutInitDisplayString. The bad thing
* about it that I was unable to find the game mode string definition, so
* that I assumed it is: "[width]x[height]:[depth]@[refresh rate]", which
* appears in all GLUT game mode programs I have seen to date.
*/
if( sscanf( string, "%ix%i:%i@%i", &width, &height, &depth, &refresh ) !=
4 )
if( sscanf( string, "%ix%i:%i", &width, &height, &depth ) != 3 )
if( sscanf( string, "%ix%i@%i", &width, &height, &refresh ) != 3 )
if( sscanf( string, "%ix%i", &width, &height ) != 2 )
if( sscanf( string, ":%i@%i", &depth, &refresh ) != 2 )
if( sscanf( string, ":%i", &depth ) != 1 )
if( sscanf( string, "@%i", &refresh ) != 1 )
fgWarning(
"unable to parse game mode string `%s'",
string
);
/* All values not specified are now set to -1, which means those
* aspects of the current display mode are not changed in
* fghChangeDisplayMode() above.
*/
fgState.GameModeSize.X = width;
fgState.GameModeSize.Y = height;
fgState.GameModeDepth = depth;
fgState.GameModeRefresh = refresh;
}
/*
* Enters the game mode
*/
int FGAPIENTRY glutEnterGameMode( void )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutEnterGameMode" );
if( fgStructure.GameModeWindow )
fgAddToWindowDestroyList( fgStructure.GameModeWindow );
else
fghRememberState( );
if( ! fghChangeDisplayMode( GL_FALSE ) )
{
fgWarning( "failed to change screen settings" );
return 0;
}
fgStructure.GameModeWindow = fgCreateWindow(
NULL, "FREEGLUT", GL_TRUE, 0, 0,
GL_TRUE, fgState.GameModeSize.X, fgState.GameModeSize.Y,
GL_TRUE, GL_FALSE
);
fgStructure.GameModeWindow->State.Width = fgState.GameModeSize.X;
fgStructure.GameModeWindow->State.Height = fgState.GameModeSize.Y;
fgStructure.GameModeWindow->State.NeedToResize = GL_TRUE;
#if TARGET_HOST_POSIX_X11
/*
* Sync needed to avoid a real race, the Xserver must have really created
* the window before we can grab the pointer into it:
*/
XSync( fgDisplay.Display, False );
/*
* Grab the pointer to confine it into the window after the calls to
* XWrapPointer() which ensure that the pointer really enters the window.
*
* We also need to wait here until XGrabPointer() returns GrabSuccess,
* otherwise the new window is not viewable yet and if the next function
* (XSetInputFocus) is called with a not yet viewable window, it will exit
* the application which we have to aviod, so wait until it's viewable:
*/
while( GrabSuccess != XGrabPointer(
fgDisplay.Display, fgStructure.GameModeWindow->Window.Handle,
TRUE,
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
| PointerMotionMask,
GrabModeAsync, GrabModeAsync,
fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) )
usleep( 100 );
/*
* Change input focus to the new window. This will exit the application
* if the new window is not viewable yet, see the XGrabPointer loop above.
*/
XSetInputFocus(
fgDisplay.Display,
fgStructure.GameModeWindow->Window.Handle,
RevertToNone,
CurrentTime
);
/* Move the Pointer to the middle of the fullscreen window */
XWarpPointer(
fgDisplay.Display,
None,
fgDisplay.RootWindow,
0, 0, 0, 0,
fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
);
# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
if( fgDisplay.DisplayModeValid )
{
int x, y;
Window child;
/* Change to viewport to the window topleft edge: */
if( !XF86VidModeSetViewPort( fgDisplay.Display, fgDisplay.Screen, 0, 0 ) )
fgWarning( "XF86VidModeSetViewPort failed" );
/*
* Final window repositioning: It could be avoided using an undecorated
* window using override_redirect, but this * would possily require
* more changes and investigation.
*/
/* Get the current postion of the drawable area on screen */
XTranslateCoordinates(
fgDisplay.Display,
fgStructure.CurrentWindow->Window.Handle,
fgDisplay.RootWindow,
0, 0, &x, &y,
&child
);
/* Move the decorataions out of the topleft corner of the display */
XMoveWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
-x, -y);
}
#endif
/* Grab the keyboard, too */
XGrabKeyboard(
fgDisplay.Display,
fgStructure.GameModeWindow->Window.Handle,
FALSE,
GrabModeAsync, GrabModeAsync,
CurrentTime
);
#endif
return fgStructure.GameModeWindow->ID;
}
/*
* Leaves the game mode
*/
void FGAPIENTRY glutLeaveGameMode( void )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLeaveGameMode" );
freeglut_return_if_fail( fgStructure.GameModeWindow );
fgAddToWindowDestroyList( fgStructure.GameModeWindow );
fgStructure.GameModeWindow = NULL;
#if TARGET_HOST_POSIX_X11
XUngrabPointer( fgDisplay.Display, CurrentTime );
XUngrabKeyboard( fgDisplay.Display, CurrentTime );
#endif
fghRestoreState();
}
/*
* Returns information concerning the freeglut game mode
*/
int FGAPIENTRY glutGameModeGet( GLenum eWhat )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGameModeGet" );
switch( eWhat )
{
case GLUT_GAME_MODE_ACTIVE:
return !!fgStructure.GameModeWindow;
case GLUT_GAME_MODE_POSSIBLE:
return fghChangeDisplayMode( GL_TRUE );
case GLUT_GAME_MODE_WIDTH:
return fgState.GameModeSize.X;
case GLUT_GAME_MODE_HEIGHT:
return fgState.GameModeSize.Y;
case GLUT_GAME_MODE_PIXEL_DEPTH:
return fgState.GameModeDepth;
case GLUT_GAME_MODE_REFRESH_RATE:
return fgState.GameModeRefresh;
case GLUT_GAME_MODE_DISPLAY_CHANGED:
/*
* This is true if the game mode has been activated successfully..
*/
return !!fgStructure.GameModeWindow;
}
fgWarning( "Unknown gamemode get: %d", eWhat );
return -1;
}
/*** END OF FILE ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
/*
* freeglut_glutfont_definitions.c
*
* Bitmap and stroke fonts displaying.
*
* Copyright (c) 2003 Stephen J. Baker (whether he wants it or not).
* All Rights Reserved.
* Written by John F. Fay <fayjf@sourceforge.net>, who releases the
* copyright over to the "freeglut" project lead.
* Creation date: Mon July 21 2003
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* This file is necessary for the *nix version of "freeglut" because the
* original GLUT defined its font variables in rather an unusual way.
* Publicly, in "glut.h", they were defined as "void *". Privately,
* in one of the source code files, they were defined as pointers to a
* structure. Most compilers and linkers are satisfied with the "void *"
* and don't go any farther, but some of them balked. In particular,
* when compiling with "freeglut" and then trying to run using the GLUT
* ".so" library, some of them would give an error. So we are having to
* create this file to define the variables as pointers to an unusual
* structure to match GLUT.
*/
/*
* freeglut_internal.h uses some GL types, but including the GL header portably
* is a bit tricky, so we include freeglut_std.h here, which contains the
* necessary machinery. But this poses another problem, caused by the ugly
* original defintion of the font constants in "classic" GLUT: They are defined
* as void* externally, so we move them temporarily out of the way by AN EXTREME
* CPP HACK.
*/
#define glutStrokeRoman glutStrokeRomanIGNOREME
#define glutStrokeMonoRoman glutStrokeMonoRomanIGNOREME
#define glutBitmap9By15 glutBitmap9By15IGNOREME
#define glutBitmap8By13 glutBitmap8By13IGNOREME
#define glutBitmapTimesRoman10 glutBitmapTimesRoman10IGNOREME
#define glutBitmapTimesRoman24 glutBitmapTimesRoman24IGNOREME
#define glutBitmapHelvetica10 glutBitmapHelvetica10IGNOREME
#define glutBitmapHelvetica12 glutBitmapHelvetica12IGNOREME
#define glutBitmapHelvetica18 glutBitmapHelvetica18IGNOREME
#include <GL/freeglut_std.h>
#undef glutStrokeRoman
#undef glutStrokeMonoRoman
#undef glutBitmap9By15
#undef glutBitmap8By13
#undef glutBitmapTimesRoman10
#undef glutBitmapTimesRoman24
#undef glutBitmapHelvetica10
#undef glutBitmapHelvetica12
#undef glutBitmapHelvetica18
#include "freeglut_internal.h"
#if TARGET_HOST_POSIX_X11
struct freeglutStrokeFont
{
const char *name ;
int num_chars ;
void *ch ;
float top ;
float bottom ;
};
struct freeglutBitmapFont
{
const char *name ;
const int num_chars ;
const int first ;
const void *ch ;
};
struct freeglutStrokeFont glutStrokeRoman ;
struct freeglutStrokeFont glutStrokeMonoRoman ;
struct freeglutBitmapFont glutBitmap9By15 ;
struct freeglutBitmapFont glutBitmap8By13 ;
struct freeglutBitmapFont glutBitmapTimesRoman10 ;
struct freeglutBitmapFont glutBitmapTimesRoman24 ;
struct freeglutBitmapFont glutBitmapHelvetica10 ;
struct freeglutBitmapFont glutBitmapHelvetica12 ;
struct freeglutBitmapFont glutBitmapHelvetica18 ;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
/*
* freeglut_input_devices.c
*
* Handles miscellaneous input devices via direct serial-port access.
* Proper X11 XInput device support is not yet supported.
* Also lacks Mac support.
*
* Written by Joe Krahn <krahn@niehs.nih.gov> 2005
*
* Copyright (c) 2005 Stephen J. Baker. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA OR STEPHEN J. BAKER BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <GL/freeglut.h>
#include "freeglut_internal.h"
#if TARGET_HOST_POSIX_X11
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <fcntl.h>
typedef struct {
int fd;
struct termios termio, termio_save;
} SERIALPORT;
#elif TARGET_HOST_MS_WINDOWS
#include <sys/types.h>
#include <winbase.h>
typedef struct {
HANDLE fh;
COMMTIMEOUTS timeouts_save;
DCB dcb_save;
} SERIALPORT;
#endif
/********************* Dialbox definitions ***********************/
#define DIAL_NUM_VALUATORS 8
/* dial parser state machine states */
#define DIAL_NEW (-1)
#define DIAL_WHICH_DEVICE 0
#define DIAL_VALUE_HIGH 1
#define DIAL_VALUE_LOW 2
/* dial/button box commands */
#define DIAL_INITIALIZE 0x20
#define DIAL_SET_LEDS 0x75
#define DIAL_SET_TEXT 0x61
#define DIAL_SET_AUTO_DIALS 0x50
#define DIAL_SET_AUTO_DELTA_DIALS 0x51
#define DIAL_SET_FILTER 0x53
#define DIAL_SET_BUTTONS_MOM_TYPE 0x71
#define DIAL_SET_AUTO_MOM_BUTTONS 0x73
#define DIAL_SET_ALL_LEDS 0x4b
#define DIAL_CLEAR_ALL_LEDS 0x4c
/* dial/button box replies and events */
#define DIAL_INITIALIZED 0x20
#define DIAL_BASE 0x30
#define DIAL_DELTA_BASE 0x40
#define DIAL_PRESS_BASE 0xc0
#define DIAL_RELEASE_BASE 0xe0
/* macros to determine reply type */
#define IS_DIAL_EVENT(ch) (((ch)>=DIAL_BASE)&&((ch)<DIAL_BASE+DIAL_NUM_VALUATORS))
#define IS_KEY_PRESS(ch) (((ch)>=DIAL_PRESS_BASE)&&((ch)<DIAL_PRESS_BASE+DIAL_NUM_BUTTONS))
#define IS_KEY_RELEASE(ch) (((ch)>=DIAL_RELEASE_BASE)&&((ch)<DIAL_RELEASE_BASE+DIAL_NUM_BUTTONS))
#define IS_INIT_EVENT(ch) ((ch)==DIAL_INITIALIZED)
/*****************************************************************/
static SERIALPORT *serial_open ( const char *device );
static void serial_close ( SERIALPORT *port );
static int serial_getchar ( SERIALPORT *port );
static int serial_putchar ( SERIALPORT *port, unsigned char ch );
static void serial_flush ( SERIALPORT *port );
static void send_dial_event(int dial, int value);
static void poll_dials(int id);
/* local variables */
static SERIALPORT *dialbox_port=NULL;
/*****************************************************************/
/*
* Implementation for glutDeviceGet(GLUT_HAS_DIAL_AND_BUTTON_BOX)
*/
int fgInputDeviceDetect( void )
{
fgInitialiseInputDevices ();
if ( !dialbox_port )
return 0;
if ( !fgState.InputDevsInitialised )
return 0;
return 1;
}
/*
* Try initializing the input device(s)
*/
void fgInitialiseInputDevices ( void )
{
if( !fgState.InputDevsInitialised )
{
const char *dial_device=NULL;
dial_device = getenv ( "GLUT_DIALS_SERIAL" );
#if TARGET_HOST_MS_WINDOWS
if (!dial_device){
static char devname[256];
DWORD size=sizeof(devname);
DWORD type = REG_SZ;
HKEY key;
if (RegOpenKeyA(HKEY_LOCAL_MACHINE,"SOFTWARE\\FreeGLUT",&key)==ERROR_SUCCESS) {
if (RegQueryValueExA(key,"DialboxSerialPort",NULL,&type,(LPBYTE)devname,&size)==ERROR_SUCCESS){
dial_device=devname;
}
RegCloseKey(key);
}
}
#endif
if ( !dial_device ) return;
if ( !( dialbox_port = serial_open ( dial_device ) ) ) return;
serial_putchar(dialbox_port,DIAL_INITIALIZE);
glutTimerFunc ( 10, poll_dials, 0 );
fgState.InputDevsInitialised = GL_TRUE;
}
}
/*
*
*/
void fgInputDeviceClose( void )
{
if ( fgState.InputDevsInitialised )
{
serial_close ( dialbox_port );
dialbox_port = NULL;
fgState.InputDevsInitialised = GL_FALSE;
}
}
/********************************************************************/
/* Check all windows for dialbox callbacks */
static void fghcbEnumDialCallbacks ( SFG_Window *window, SFG_Enumerator *enumerator )
{
/* Built-in to INVOKE_WCB(): if window->Callbacks[CB_Dials] */
INVOKE_WCB ( *window,Dials, ( ((int*)enumerator->data)[0], ((int*)enumerator->data)[1]) );
fgEnumSubWindows ( window, fghcbEnumDialCallbacks, enumerator );
}
static void send_dial_event ( int num, int value )
{
SFG_Enumerator enumerator;
int data[2];
data[0] = num;
data[1] = value;
enumerator.found = GL_FALSE;
enumerator.data = data;
fgEnumWindows ( fghcbEnumDialCallbacks, &enumerator );
}
/********************************************************************/
static void poll_dials ( int id )
{
int data;
static int dial_state = DIAL_NEW;
static int dial_which;
static int dial_value;
static int dials[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
if ( !dialbox_port ) return;
while ( (data=serial_getchar(dialbox_port)) != EOF )
{
if ( ( dial_state > DIAL_WHICH_DEVICE ) || IS_DIAL_EVENT ( data ) )
{
switch ( dial_state )
{
case DIAL_WHICH_DEVICE:
dial_which = data - DIAL_BASE;
dial_state++;
break;
case DIAL_VALUE_HIGH:
dial_value = ( data << 8 );
dial_state++;
break;
case DIAL_VALUE_LOW:
dial_value |= data;
if ( dial_value & 0x8000 ) dial_value -= 0x10000;
dials[dial_which] = dial_value;
send_dial_event ( dial_which + 1, dial_value * 360 / 256 );
dial_state = DIAL_WHICH_DEVICE;
break;
default:
/* error: Impossible state value! */
break;
}
}
else if ( data == DIAL_INITIALIZED )
{
fgState.InputDevsInitialised = GL_TRUE;
dial_state = DIAL_WHICH_DEVICE;
serial_putchar(dialbox_port,DIAL_SET_AUTO_DIALS);
serial_putchar(dialbox_port,0xff);
serial_putchar(dialbox_port,0xff);
}
else /* Unknown data; try flushing. */
serial_flush(dialbox_port);
}
glutTimerFunc ( 2, poll_dials, 0 );
}
/******** OS Specific Serial I/O routines *******/
#if TARGET_HOST_POSIX_X11 /* ==> Linux/BSD/UNIX POSIX serial I/O */
static SERIALPORT *serial_open ( const char *device )
{
int fd;
struct termios termio;
SERIALPORT *port;
fd = open(device, O_RDWR | O_NONBLOCK );
if (fd <0) {
perror(device);
return NULL;
}
port = malloc(sizeof(SERIALPORT));
memset(port, 0, sizeof(SERIALPORT));
port->fd = fd;
/* save current port settings */
tcgetattr(fd,&port->termio_save);
memset(&termio, 0, sizeof(termio));
termio.c_cflag = CS8 | CREAD | HUPCL ;
termio.c_iflag = IGNPAR | IGNBRK ;
termio.c_cc[VTIME] = 0; /* inter-character timer */
termio.c_cc[VMIN] = 1; /* block read until 1 chars received, when blocking I/O */
cfsetispeed(&termio, B9600);
cfsetospeed(&termio, B9600);
tcsetattr(fd,TCSANOW,&termio);
serial_flush(port);
return port;
}
static void serial_close(SERIALPORT *port)
{
if (port)
{
/* restore old port settings */
tcsetattr(port->fd,TCSANOW,&port->termio_save);
close(port->fd);
free(port);
}
}
static int serial_getchar(SERIALPORT *port)
{
unsigned char ch;
if (!port) return EOF;
if (read(port->fd,&ch,1)) return ch;
return EOF;
}
static int serial_putchar(SERIALPORT *port, unsigned char ch){
if (!port) return 0;
return write(port->fd,&ch,1);
}
static void serial_flush ( SERIALPORT *port )
{
tcflush ( port->fd, TCIOFLUSH );
}
#elif TARGET_HOST_MS_WINDOWS
static SERIALPORT *serial_open(const char *device){
HANDLE fh;
DCB dcb={sizeof(DCB)};
COMMTIMEOUTS timeouts;
SERIALPORT *port;
fh = CreateFile(device,GENERIC_READ|GENERIC_WRITE,0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (!fh) return NULL;
port = malloc(sizeof(SERIALPORT));
ZeroMemory(port, sizeof(SERIALPORT));
port->fh = fh;
/* save current port settings */
GetCommState(fh,&port->dcb_save);
GetCommTimeouts(fh,&port->timeouts_save);
dcb.DCBlength=sizeof(DCB);
BuildCommDCB("96,n,8,1",&dcb);
SetCommState(fh,&dcb);
ZeroMemory(&timeouts,sizeof(timeouts));
timeouts.ReadTotalTimeoutConstant=1;
timeouts.WriteTotalTimeoutConstant=1;
SetCommTimeouts(fh,&timeouts);
serial_flush(port);
return port;
}
static void serial_close(SERIALPORT *port){
if (port){
/* restore old port settings */
SetCommState(port->fh,&port->dcb_save);
SetCommTimeouts(port->fh,&port->timeouts_save);
CloseHandle(port->fh);
free(port);
}
}
static int serial_getchar(SERIALPORT *port){
DWORD n;
unsigned char ch;
if (!port) return EOF;
if (!ReadFile(port->fh,&ch,1,&n,NULL)) return EOF;
if (n==1) return ch;
return EOF;
}
static int serial_putchar(SERIALPORT *port, unsigned char ch){
DWORD n;
if (!port) return 0;
return WriteFile(port->fh,&ch,1,&n,NULL);
}
static void serial_flush ( SERIALPORT *port )
{
FlushFileBuffers(port->fh);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,214 @@
/*
* freeglut_misc.c
*
* Functions that didn't fit anywhere else...
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 9 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/*
* TODO BEFORE THE STABLE RELEASE:
*
* glutSetColor() --
* glutGetColor() --
* glutCopyColormap() --
* glutSetKeyRepeat() -- this is evil and should be removed from API
*/
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* This functions checks if an OpenGL extension is supported or not
*
* XXX Wouldn't this be simpler and clearer if we used strtok()?
*/
int FGAPIENTRY glutExtensionSupported( const char* extension )
{
const char *extensions, *start;
const size_t len = strlen( extension );
/* Make sure there is a current window, and thus a current context available */
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutExtensionSupported" );
freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
if (strchr(extension, ' '))
return 0;
start = extensions = (const char *) glGetString(GL_EXTENSIONS);
/* XXX consider printing a warning to stderr that there's no current
* rendering context.
*/
freeglut_return_val_if_fail( extensions != NULL, 0 );
while (1) {
const char *p = strstr(extensions, extension);
if (!p)
return 0; /* not found */
/* check that the match isn't a super string */
if ((p == start || p[-1] == ' ') && (p[len] == ' ' || p[len] == 0))
return 1;
/* skip the false match and continue */
extensions = p + len;
}
return 0 ;
}
#ifndef GL_INVALID_FRAMEBUFFER_OPERATION
#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
#define GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
#else
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
#endif
#endif
#ifndef GL_TABLE_TOO_LARGE
#ifdef GL_TABLE_TOO_LARGE_EXT
#define GL_TABLE_TOO_LARGE GL_TABLE_TOO_LARGE_EXT
#else
#define GL_TABLE_TOO_LARGE 0x8031
#endif
#endif
#ifndef GL_TEXTURE_TOO_LARGE
#ifdef GL_TEXTURE_TOO_LARGE_EXT
#define GL_TEXTURE_TOO_LARGE GL_TEXTURE_TOO_LARGE_EXT
#else
#define GL_TEXTURE_TOO_LARGE 0x8065
#endif
#endif
/*
* A cut-down local version of gluErrorString to avoid depending on GLU.
*/
static const char* fghErrorString( GLenum error )
{
switch ( error ) {
case GL_INVALID_ENUM: return "invalid enumerant";
case GL_INVALID_VALUE: return "invalid value";
case GL_INVALID_OPERATION: return "invalid operation";
case GL_STACK_OVERFLOW: return "stack overflow";
case GL_STACK_UNDERFLOW: return "stack underflow";
case GL_OUT_OF_MEMORY: return "out of memory";
case GL_TABLE_TOO_LARGE: return "table too large";
case GL_INVALID_FRAMEBUFFER_OPERATION: return "invalid framebuffer operation";
case GL_TEXTURE_TOO_LARGE: return "texture too large";
default: return "unknown GL error";
}
}
/*
* This function reports all the OpenGL errors that happened till now
*/
void FGAPIENTRY glutReportErrors( void )
{
GLenum error;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReportErrors" );
while( ( error = glGetError() ) != GL_NO_ERROR )
fgWarning( "GL error: %s", fghErrorString( error ) );
}
/*
* Control the auto-repeat of keystrokes to the current window
*/
void FGAPIENTRY glutIgnoreKeyRepeat( int ignore )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIgnoreKeyRepeat" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIgnoreKeyRepeat" );
fgStructure.CurrentWindow->State.IgnoreKeyRepeat = ignore ? GL_TRUE : GL_FALSE;
}
/*
* Set global auto-repeat of keystrokes
*
* RepeatMode should be either:
* GLUT_KEY_REPEAT_OFF
* GLUT_KEY_REPEAT_ON
* GLUT_KEY_REPEAT_DEFAULT
*/
void FGAPIENTRY glutSetKeyRepeat( int repeatMode )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetKeyRepeat" );
switch( repeatMode )
{
case GLUT_KEY_REPEAT_OFF:
case GLUT_KEY_REPEAT_ON:
fgState.KeyRepeat = repeatMode;
break;
case GLUT_KEY_REPEAT_DEFAULT:
fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
break;
default:
fgError ("Invalid glutSetKeyRepeat mode: %d", repeatMode);
break;
}
}
/*
* Forces the joystick callback to be executed
*/
void FGAPIENTRY glutForceJoystickFunc( void )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutForceJoystickFunc" );
#if !defined(_WIN32_WCE)
freeglut_return_if_fail( fgStructure.CurrentWindow != NULL );
freeglut_return_if_fail( FETCH_WCB( *( fgStructure.CurrentWindow ), Joystick ) );
fgJoystickPollWindow( fgStructure.CurrentWindow );
#endif /* !defined(_WIN32_WCE) */
}
/*
*
*/
void FGAPIENTRY glutSetColor( int nColor, GLfloat red, GLfloat green, GLfloat blue )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetColor" );
/* We really need to do something here. */
}
/*
*
*/
GLfloat FGAPIENTRY glutGetColor( int color, int component )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetColor" );
/* We really need to do something here. */
return( 0.0f );
}
/*
*
*/
void FGAPIENTRY glutCopyColormap( int window )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCopyColormap" );
/* We really need to do something here. */
}
/*** END OF FILE ***/

View File

@ -0,0 +1,45 @@
/*
* freeglut_overlay.c
*
* Overlay management functions (as defined by GLUT API)
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 16 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/*
* NOTE: functions declared in this file probably will not be implemented.
*/
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
void FGAPIENTRY glutEstablishOverlay( void ) { /* Not implemented */ }
void FGAPIENTRY glutRemoveOverlay( void ) { /* Not implemented */ }
void FGAPIENTRY glutUseLayer( GLenum layer ) { /* Not implemented */ }
void FGAPIENTRY glutPostOverlayRedisplay( void ) { /* Not implemented */ }
void FGAPIENTRY glutPostWindowOverlayRedisplay( int ID ) { /* Not implemented */ }
void FGAPIENTRY glutShowOverlay( void ) { /* Not implemented */ }
void FGAPIENTRY glutHideOverlay( void ) { /* Not implemented */ }
/*** END OF FILE ***/

View File

@ -0,0 +1,471 @@
/* Spaceball support for Linux.
* Written by John Tsiombikas <nuclear@member.fsf.org>
*
* This code supports 3Dconnexion's 6-dof space-whatever devices.
* It can communicate with either the proprietary 3Dconnexion daemon (3dxsrv)
* free spacenavd (http://spacenav.sourceforge.net), through the "standard"
* magellan X-based protocol.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/* -- PRIVATE FUNCTIONS --------------------------------------------------- */
#if TARGET_HOST_POSIX_X11
#include <X11/Xlib.h>
enum {
SPNAV_EVENT_ANY, /* used by spnav_remove_events() */
SPNAV_EVENT_MOTION,
SPNAV_EVENT_BUTTON /* includes both press and release */
};
struct spnav_event_motion {
int type;
int x, y, z;
int rx, ry, rz;
unsigned int period;
int *data;
};
struct spnav_event_button {
int type;
int press;
int bnum;
};
typedef union spnav_event {
int type;
struct spnav_event_motion motion;
struct spnav_event_button button;
} spnav_event;
static int spnav_x11_open(Display *dpy, Window win);
static int spnav_x11_window(Window win);
static int spnav_x11_event(const XEvent *xev, spnav_event *event);
static int spnav_close(void);
static int spnav_fd(void);
static int spnav_remove_events(int type);
static SFG_Window *spnav_win;
#endif
/* Flag telling whether we have a spaceball:
* 0 - haven't tried initializing
* 1 - have successfully initialized
* -1 - have tried to initialize but not succeeded
*/
static int sball_initialized = 0;
void fgInitialiseSpaceball(void)
{
if(sball_initialized != 0) {
return;
}
#if TARGET_HOST_POSIX_X11
{
Window w;
if(!fgStructure.CurrentWindow)
{
sball_initialized = -1;
return;
}
w = fgStructure.CurrentWindow->Window.Handle;
if(spnav_x11_open(fgDisplay.Display, w) == -1)
{
sball_initialized = -1;
return;
}
}
#endif
sball_initialized = 1;
}
void fgSpaceballClose(void)
{
#if TARGET_HOST_POSIX_X11
spnav_close();
#endif
}
int fgHasSpaceball(void)
{
if(sball_initialized == 0) {
fgInitialiseSpaceball();
if(sball_initialized != 1) {
fgWarning("fgInitialiseSpaceball failed\n");
return 0;
}
}
#if TARGET_HOST_POSIX_X11
/* XXX this function should somehow query the driver if there's a device
* plugged in, as opposed to just checking if there's a driver to talk to.
*/
return spnav_fd() == -1 ? 0 : 1;
#else
return 0;
#endif
}
int fgSpaceballNumButtons(void)
{
if(sball_initialized == 0) {
fgInitialiseSpaceball();
if(sball_initialized != 1) {
fgWarning("fgInitialiseSpaceball failed\n");
return 0;
}
}
#if TARGET_HOST_POSIX_X11
return 2; /* TODO implement this properly */
#else
return 0;
#endif
}
void fgSpaceballSetWindow(SFG_Window *window)
{
if(sball_initialized == 0) {
fgInitialiseSpaceball();
if(sball_initialized != 1) {
return;
}
}
#if TARGET_HOST_POSIX_X11
if(spnav_win != window) {
spnav_x11_window(window->Window.Handle);
spnav_win = window;
}
#endif
}
#if TARGET_HOST_POSIX_X11
int fgIsSpaceballXEvent(const XEvent *xev)
{
spnav_event sev;
if(spnav_win != fgStructure.CurrentWindow) {
/* this will also initialize spaceball if needed (first call) */
fgSpaceballSetWindow(fgStructure.CurrentWindow);
}
if(sball_initialized != 1) {
return 0;
}
return spnav_x11_event(xev, &sev);
}
void fgSpaceballHandleXEvent(const XEvent *xev)
{
spnav_event sev;
if(sball_initialized == 0) {
fgInitialiseSpaceball();
if(sball_initialized != 1) {
return;
}
}
if(spnav_x11_event(xev, &sev)) {
switch(sev.type) {
case SPNAV_EVENT_MOTION:
if(sev.motion.x | sev.motion.y | sev.motion.z) {
INVOKE_WCB(*spnav_win, SpaceMotion, (sev.motion.x, sev.motion.y, sev.motion.z));
}
if(sev.motion.rx | sev.motion.ry | sev.motion.rz) {
INVOKE_WCB(*spnav_win, SpaceRotation, (sev.motion.rx, sev.motion.ry, sev.motion.rz));
}
spnav_remove_events(SPNAV_EVENT_MOTION);
break;
case SPNAV_EVENT_BUTTON:
INVOKE_WCB(*spnav_win, SpaceButton, (sev.button.bnum, sev.button.press ? GLUT_DOWN : GLUT_UP));
break;
default:
break;
}
}
}
/*
The following code is part of libspnav, part of the spacenav project (spacenav.sf.net)
Copyright (C) 2007-2009 John Tsiombikas <nuclear@member.fsf.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
static Window get_daemon_window(Display *dpy);
static int catch_badwin(Display *dpy, XErrorEvent *err);
static Display *dpy;
static Window app_win;
static Atom motion_event, button_press_event, button_release_event, command_event;
enum {
CMD_APP_WINDOW = 27695,
CMD_APP_SENS
};
#define IS_OPEN dpy
struct event_node {
spnav_event event;
struct event_node *next;
};
static int spnav_x11_open(Display *display, Window win)
{
if(IS_OPEN) {
return -1;
}
dpy = display;
motion_event = XInternAtom(dpy, "MotionEvent", True);
button_press_event = XInternAtom(dpy, "ButtonPressEvent", True);
button_release_event = XInternAtom(dpy, "ButtonReleaseEvent", True);
command_event = XInternAtom(dpy, "CommandEvent", True);
if(!motion_event || !button_press_event || !button_release_event || !command_event) {
dpy = 0;
return -1; /* daemon not started */
}
if(spnav_x11_window(win) == -1) {
dpy = 0;
return -1; /* daemon not started */
}
app_win = win;
return 0;
}
static int spnav_close(void)
{
if(dpy) {
spnav_x11_window(DefaultRootWindow(dpy));
app_win = 0;
dpy = 0;
return 0;
}
return -1;
}
static int spnav_x11_window(Window win)
{
int (*prev_xerr_handler)(Display*, XErrorEvent*);
XEvent xev;
Window daemon_win;
if(!IS_OPEN) {
return -1;
}
if(!(daemon_win = get_daemon_window(dpy))) {
return -1;
}
prev_xerr_handler = XSetErrorHandler(catch_badwin);
xev.type = ClientMessage;
xev.xclient.send_event = False;
xev.xclient.display = dpy;
xev.xclient.window = win;
xev.xclient.message_type = command_event;
xev.xclient.format = 16;
xev.xclient.data.s[0] = ((unsigned int)win & 0xffff0000) >> 16;
xev.xclient.data.s[1] = (unsigned int)win & 0xffff;
xev.xclient.data.s[2] = CMD_APP_WINDOW;
XSendEvent(dpy, daemon_win, False, 0, &xev);
XSync(dpy, False);
XSetErrorHandler(prev_xerr_handler);
return 0;
}
static int spnav_fd(void)
{
if(dpy) {
return ConnectionNumber(dpy);
}
return -1;
}
/*static int spnav_wait_event(spnav_event *event)
{
if(dpy) {
for(;;) {
XEvent xev;
XNextEvent(dpy, &xev);
if(spnav_x11_event(&xev, event) > 0) {
return event->type;
}
}
}
return 0;
}
static int spnav_poll_event(spnav_event *event)
{
if(dpy) {
if(XPending(dpy)) {
XEvent xev;
XNextEvent(dpy, &xev);
return spnav_x11_event(&xev, event);
}
}
return 0;
}*/
static Bool match_events(Display *dpy, XEvent *xev, char *arg)
{
int evtype = *(int*)arg;
if(xev->type != ClientMessage) {
return False;
}
if(xev->xclient.message_type == motion_event) {
return !evtype || evtype == SPNAV_EVENT_MOTION ? True : False;
}
if(xev->xclient.message_type == button_press_event ||
xev->xclient.message_type == button_release_event) {
return !evtype || evtype == SPNAV_EVENT_BUTTON ? True : False;
}
return False;
}
static int spnav_remove_events(int type)
{
int rm_count = 0;
if(dpy) {
XEvent xev;
while(XCheckIfEvent(dpy, &xev, match_events, (char*)&type)) {
rm_count++;
}
return rm_count;
}
return 0;
}
static int spnav_x11_event(const XEvent *xev, spnav_event *event)
{
int i;
int xmsg_type;
if(xev->type != ClientMessage) {
return 0;
}
xmsg_type = xev->xclient.message_type;
if(xmsg_type != motion_event && xmsg_type != button_press_event &&
xmsg_type != button_release_event) {
return 0;
}
if(xmsg_type == motion_event) {
event->type = SPNAV_EVENT_MOTION;
event->motion.data = &event->motion.x;
for(i=0; i<6; i++) {
event->motion.data[i] = xev->xclient.data.s[i + 2];
}
event->motion.period = xev->xclient.data.s[8];
} else {
event->type = SPNAV_EVENT_BUTTON;
event->button.press = xmsg_type == button_press_event ? 1 : 0;
event->button.bnum = xev->xclient.data.s[2];
}
return event->type;
}
static Window get_daemon_window(Display *dpy)
{
Window win, root_win;
XTextProperty wname;
Atom type;
int fmt;
unsigned long nitems, bytes_after;
unsigned char *prop;
root_win = DefaultRootWindow(dpy);
XGetWindowProperty(dpy, root_win, command_event, 0, 1, False, AnyPropertyType, &type, &fmt, &nitems, &bytes_after, &prop);
if(!prop) {
return 0;
}
win = *(Window*)prop;
XFree(prop);
if(!XGetWMName(dpy, win, &wname) || strcmp("Magellan Window", (char*)wname.value) != 0) {
return 0;
}
return win;
}
static int catch_badwin(Display *dpy, XErrorEvent *err)
{
char buf[256];
if(err->error_code == BadWindow) {
/* do nothing? */
} else {
XGetErrorText(dpy, err->error_code, buf, sizeof buf);
fprintf(stderr, "Caught unexpected X error: %s\n", buf);
}
return 0;
}
#endif /* TARGET_HOST_POSIX_X11 */

View File

@ -0,0 +1,887 @@
/*
* freeglut_state.c
*
* Freeglut state query methods.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 16 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/*
* TODO BEFORE THE STABLE RELEASE:
*
* glutGet() -- X11 tests passed, but check if all enums
* handled (what about Win32?)
* glutDeviceGet() -- X11 tests passed, but check if all enums
* handled (what about Win32?)
* glutGetModifiers() -- OK, but could also remove the limitation
* glutLayerGet() -- what about GLUT_NORMAL_DAMAGED?
*
* The fail-on-call policy will help adding the most needed things imho.
*/
/* -- LOCAL DEFINITIONS ---------------------------------------------------- */
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
#if TARGET_HOST_POSIX_X11
/*
* Queries the GL context about some attributes
*/
static int fghGetConfig( int attribute )
{
int returnValue = 0;
int result; /* Not checked */
if( fgStructure.CurrentWindow )
result = glXGetFBConfigAttrib( fgDisplay.Display,
*(fgStructure.CurrentWindow->Window.FBConfig),
attribute,
&returnValue );
return returnValue;
}
#endif
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* General settings assignment method
*/
void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetOption" );
/*
* XXX In chronological code add order. (WHY in that order?)
*/
switch( eWhat )
{
case GLUT_INIT_WINDOW_X:
fgState.Position.X = (GLint)value;
break;
case GLUT_INIT_WINDOW_Y:
fgState.Position.Y = (GLint)value;
break;
case GLUT_INIT_WINDOW_WIDTH:
fgState.Size.X = (GLint)value;
break;
case GLUT_INIT_WINDOW_HEIGHT:
fgState.Size.Y = (GLint)value;
break;
case GLUT_INIT_DISPLAY_MODE:
fgState.DisplayMode = (unsigned int)value;
break;
case GLUT_ACTION_ON_WINDOW_CLOSE:
fgState.ActionOnWindowClose = value;
break;
case GLUT_RENDERING_CONTEXT:
fgState.UseCurrentContext =
( value == GLUT_USE_CURRENT_CONTEXT ) ? GL_TRUE : GL_FALSE;
break;
case GLUT_DIRECT_RENDERING:
fgState.DirectContext = value;
break;
case GLUT_WINDOW_CURSOR:
if( fgStructure.CurrentWindow != NULL )
fgStructure.CurrentWindow->State.Cursor = value;
break;
case GLUT_AUX:
fgState.AuxiliaryBufferNumber = value;
break;
case GLUT_MULTISAMPLE:
fgState.SampleNumber = value;
break;
default:
fgWarning( "glutSetOption(): missing enum handle %d", eWhat );
break;
}
}
#if TARGET_HOST_MS_WINDOWS
/* The following include file is available from SGI but is not standard:
* #include <GL/wglext.h>
* So we copy the necessary parts out of it to support the multisampling query
*/
#define WGL_SAMPLES_ARB 0x2042
#endif
/*
* General settings query method
*/
int FGAPIENTRY glutGet( GLenum eWhat )
{
#if TARGET_HOST_MS_WINDOWS
int returnValue ;
GLboolean boolValue ;
#endif
int nsamples = 0;
switch (eWhat)
{
case GLUT_INIT_STATE:
return fgState.Initialised;
case GLUT_ELAPSED_TIME:
return fgElapsedTime();
}
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" );
/* XXX In chronological code add order. (WHY in that order?) */
switch( eWhat )
{
/* Following values are stored in fgState and fgDisplay global structures */
case GLUT_SCREEN_WIDTH: return fgDisplay.ScreenWidth ;
case GLUT_SCREEN_HEIGHT: return fgDisplay.ScreenHeight ;
case GLUT_SCREEN_WIDTH_MM: return fgDisplay.ScreenWidthMM ;
case GLUT_SCREEN_HEIGHT_MM: return fgDisplay.ScreenHeightMM;
case GLUT_INIT_WINDOW_X: return fgState.Position.Use ?
fgState.Position.X : -1 ;
case GLUT_INIT_WINDOW_Y: return fgState.Position.Use ?
fgState.Position.Y : -1 ;
case GLUT_INIT_WINDOW_WIDTH: return fgState.Size.Use ?
fgState.Size.X : -1 ;
case GLUT_INIT_WINDOW_HEIGHT: return fgState.Size.Use ?
fgState.Size.Y : -1 ;
case GLUT_INIT_DISPLAY_MODE: return fgState.DisplayMode ;
case GLUT_INIT_MAJOR_VERSION: return fgState.MajorVersion ;
case GLUT_INIT_MINOR_VERSION: return fgState.MinorVersion ;
case GLUT_INIT_FLAGS: return fgState.ContextFlags ;
case GLUT_INIT_PROFILE: return fgState.ContextProfile ;
#if TARGET_HOST_POSIX_X11
/*
* The window/context specific queries are handled mostly by
* fghGetConfig().
*/
case GLUT_WINDOW_NUM_SAMPLES:
#ifdef GLX_VERSION_1_3
glGetIntegerv(GL_SAMPLES, &nsamples);
#endif
return nsamples;
/*
* The rest of GLX queries under X are general enough to use a macro to
* check them
*/
# define GLX_QUERY(a,b) case a: return fghGetConfig( b );
GLX_QUERY( GLUT_WINDOW_RGBA, GLX_RGBA );
GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER, GLX_DOUBLEBUFFER );
GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE, GLX_BUFFER_SIZE );
GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE, GLX_STENCIL_SIZE );
GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE, GLX_DEPTH_SIZE );
GLX_QUERY( GLUT_WINDOW_RED_SIZE, GLX_RED_SIZE );
GLX_QUERY( GLUT_WINDOW_GREEN_SIZE, GLX_GREEN_SIZE );
GLX_QUERY( GLUT_WINDOW_BLUE_SIZE, GLX_BLUE_SIZE );
GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE, GLX_ALPHA_SIZE );
GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE, GLX_ACCUM_RED_SIZE );
GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE, GLX_ACCUM_GREEN_SIZE );
GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE, GLX_ACCUM_BLUE_SIZE );
GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE, GLX_ACCUM_ALPHA_SIZE );
GLX_QUERY( GLUT_WINDOW_STEREO, GLX_STEREO );
# undef GLX_QUERY
/* Colormap size is handled in a bit different way than all the rest */
case GLUT_WINDOW_COLORMAP_SIZE:
if( (fghGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) )
{
/*
* We've got a RGBA visual, so there is no colormap at all.
* The other possibility is that we have no current window set.
*/
return 0;
}
else
{
const GLXFBConfig * fbconfig =
fgStructure.CurrentWindow->Window.FBConfig;
XVisualInfo * visualInfo =
glXGetVisualFromFBConfig( fgDisplay.Display, *fbconfig );
const int result = visualInfo->visual->map_entries;
XFree(visualInfo);
return result;
}
/*
* Those calls are somewhat similiar, as they use XGetWindowAttributes()
* function
*/
case GLUT_WINDOW_X:
case GLUT_WINDOW_Y:
case GLUT_WINDOW_BORDER_WIDTH:
case GLUT_WINDOW_HEADER_HEIGHT:
{
int x, y;
Window w;
if( fgStructure.CurrentWindow == NULL )
return 0;
XTranslateCoordinates(
fgDisplay.Display,
fgStructure.CurrentWindow->Window.Handle,
fgDisplay.RootWindow,
0, 0, &x, &y, &w);
switch ( eWhat )
{
case GLUT_WINDOW_X: return x;
case GLUT_WINDOW_Y: return y;
}
if ( w == 0 )
return 0;
XTranslateCoordinates(
fgDisplay.Display,
fgStructure.CurrentWindow->Window.Handle,
w, 0, 0, &x, &y, &w);
switch ( eWhat )
{
case GLUT_WINDOW_BORDER_WIDTH: return x;
case GLUT_WINDOW_HEADER_HEIGHT: return y;
}
}
case GLUT_WINDOW_WIDTH:
case GLUT_WINDOW_HEIGHT:
{
XWindowAttributes winAttributes;
if( fgStructure.CurrentWindow == NULL )
return 0;
XGetWindowAttributes(
fgDisplay.Display,
fgStructure.CurrentWindow->Window.Handle,
&winAttributes
);
switch ( eWhat )
{
case GLUT_WINDOW_WIDTH: return winAttributes.width ;
case GLUT_WINDOW_HEIGHT: return winAttributes.height ;
}
}
/* I do not know yet if there will be a fgChooseVisual() function for Win32 */
case GLUT_DISPLAY_MODE_POSSIBLE:
{
/* We should not have to call fgChooseFBConfig again here. */
GLXFBConfig * fbconfig;
int isPossible;
fbconfig = fgChooseFBConfig(NULL);
if (fbconfig == NULL)
{
isPossible = 0;
}
else
{
isPossible = 1;
XFree(fbconfig);
}
return isPossible;
}
/* This is system-dependant */
case GLUT_WINDOW_FORMAT_ID:
if( fgStructure.CurrentWindow == NULL )
return 0;
return fghGetConfig( GLX_VISUAL_ID );
#elif TARGET_HOST_MS_WINDOWS
case GLUT_WINDOW_NUM_SAMPLES:
glGetIntegerv(WGL_SAMPLES_ARB, &nsamples);
return nsamples;
/* Handle the OpenGL inquiries */
case GLUT_WINDOW_RGBA:
#if defined(_WIN32_WCE)
boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
#else
glGetBooleanv ( GL_RGBA_MODE, &boolValue );
returnValue = boolValue ? 1 : 0;
#endif
return returnValue;
case GLUT_WINDOW_DOUBLEBUFFER:
#if defined(_WIN32_WCE)
boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
#else
glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
returnValue = boolValue ? 1 : 0;
#endif
return returnValue;
case GLUT_WINDOW_STEREO:
#if defined(_WIN32_WCE)
boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
#else
glGetBooleanv ( GL_STEREO, &boolValue );
returnValue = boolValue ? 1 : 0;
#endif
return returnValue;
case GLUT_WINDOW_RED_SIZE:
glGetIntegerv ( GL_RED_BITS, &returnValue );
return returnValue;
case GLUT_WINDOW_GREEN_SIZE:
glGetIntegerv ( GL_GREEN_BITS, &returnValue );
return returnValue;
case GLUT_WINDOW_BLUE_SIZE:
glGetIntegerv ( GL_BLUE_BITS, &returnValue );
return returnValue;
case GLUT_WINDOW_ALPHA_SIZE:
glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
return returnValue;
case GLUT_WINDOW_ACCUM_RED_SIZE:
#if defined(_WIN32_WCE)
returnValue = 0; /* WinCE doesn't support this feature */
#else
glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
#endif
return returnValue;
case GLUT_WINDOW_ACCUM_GREEN_SIZE:
#if defined(_WIN32_WCE)
returnValue = 0; /* WinCE doesn't support this feature */
#else
glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
#endif
return returnValue;
case GLUT_WINDOW_ACCUM_BLUE_SIZE:
#if defined(_WIN32_WCE)
returnValue = 0; /* WinCE doesn't support this feature */
#else
glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
#endif
return returnValue;
case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
#if defined(_WIN32_WCE)
returnValue = 0; /* WinCE doesn't support this feature */
#else
glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
#endif
return returnValue;
case GLUT_WINDOW_DEPTH_SIZE:
glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
return returnValue;
case GLUT_WINDOW_BUFFER_SIZE:
returnValue = 1 ; /* ????? */
return returnValue;
case GLUT_WINDOW_STENCIL_SIZE:
returnValue = 0 ; /* ????? */
return returnValue;
case GLUT_WINDOW_X:
case GLUT_WINDOW_Y:
case GLUT_WINDOW_WIDTH:
case GLUT_WINDOW_HEIGHT:
{
/*
* There is considerable confusion about the "right thing to
* do" concerning window size and position. GLUT itself is
* not consistent between Windows and UNIX/X11; since
* platform independence is a virtue for "freeglut", we
* decided to break with GLUT's behaviour.
*
* Under UNIX/X11, it is apparently not possible to get the
* window border sizes in order to subtract them off the
* window's initial position until some time after the window
* has been created. Therefore we decided on the following
* behaviour, both under Windows and under UNIX/X11:
* - When you create a window with position (x,y) and size
* (w,h), the upper left hand corner of the outside of the
* window is at (x,y) and the size of the drawable area is
* (w,h).
* - When you query the size and position of the window--as
* is happening here for Windows--"freeglut" will return
* the size of the drawable area--the (w,h) that you
* specified when you created the window--and the coordinates
* of the upper left hand corner of the drawable
* area--which is NOT the (x,y) you specified.
*/
RECT winRect;
freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
#if defined(_WIN32_WCE)
GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
#else
winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE);
#endif /* defined(_WIN32_WCE) */
switch( eWhat )
{
case GLUT_WINDOW_X: return winRect.left ;
case GLUT_WINDOW_Y: return winRect.top ;
case GLUT_WINDOW_WIDTH: return winRect.right - winRect.left;
case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
}
}
break;
case GLUT_WINDOW_BORDER_WIDTH :
case GLUT_WINDOW_HEADER_HEIGHT :
#if defined(_WIN32_WCE)
return 0;
#else
{
DWORD windowStyle;
if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
else
/* If no window, return sizes for a default window with title bar and border */
windowStyle = WS_OVERLAPPEDWINDOW;
switch( eWhat )
{
case GLUT_WINDOW_BORDER_WIDTH:
{
int xBorderWidth, yBorderWidth;
fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
return xBorderWidth;
}
case GLUT_WINDOW_HEADER_HEIGHT:
/* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
return (windowStyle & WS_MAXIMIZEBOX)? GetSystemMetrics( SM_CYCAPTION ) : 0;
}
}
#endif /* defined(_WIN32_WCE) */
case GLUT_DISPLAY_MODE_POSSIBLE:
#if defined(_WIN32_WCE)
return 0;
#else
return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
PFD_MAIN_PLANE );
#endif /* defined(_WIN32_WCE) */
case GLUT_WINDOW_FORMAT_ID:
#if !defined(_WIN32_WCE)
if( fgStructure.CurrentWindow != NULL )
return GetPixelFormat( fgStructure.CurrentWindow->Window.Device );
#endif /* defined(_WIN32_WCE) */
return 0;
#endif
/* The window structure queries */
case GLUT_WINDOW_PARENT:
if( fgStructure.CurrentWindow == NULL ) return 0;
if( fgStructure.CurrentWindow->Parent == NULL ) return 0;
return fgStructure.CurrentWindow->Parent->ID;
case GLUT_WINDOW_NUM_CHILDREN:
if( fgStructure.CurrentWindow == NULL )
return 0;
return fgListLength( &fgStructure.CurrentWindow->Children );
case GLUT_WINDOW_CURSOR:
if( fgStructure.CurrentWindow == NULL )
return 0;
return fgStructure.CurrentWindow->State.Cursor;
case GLUT_MENU_NUM_ITEMS:
if( fgStructure.CurrentMenu == NULL )
return 0;
return fgListLength( &fgStructure.CurrentMenu->Entries );
case GLUT_ACTION_ON_WINDOW_CLOSE:
return fgState.ActionOnWindowClose;
case GLUT_VERSION :
return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH;
case GLUT_RENDERING_CONTEXT:
return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT
: GLUT_CREATE_NEW_CONTEXT;
case GLUT_DIRECT_RENDERING:
return fgState.DirectContext;
case GLUT_FULL_SCREEN:
return fgStructure.CurrentWindow->State.IsFullscreen;
case GLUT_AUX:
return fgState.AuxiliaryBufferNumber;
case GLUT_MULTISAMPLE:
return fgState.SampleNumber;
default:
fgWarning( "glutGet(): missing enum handle %d", eWhat );
break;
}
return -1;
}
/*
* Returns various device information.
*/
int FGAPIENTRY glutDeviceGet( GLenum eWhat )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDeviceGet" );
/* XXX WARNING: we are mostly lying in this function. */
switch( eWhat )
{
case GLUT_HAS_KEYBOARD:
/*
* Win32 is assumed a keyboard, and this cannot be queried,
* except for WindowsCE.
*
* X11 has a core keyboard by definition, although it can
* be present as a virtual/dummy keyboard. For now, there
* is no reliable way to tell if a real keyboard is present.
*/
#if defined(_WIN32_CE)
return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0;
# if FREEGLUT_LIB_PRAGMAS
# pragma comment (lib,"Kbdui.lib")
# endif
#else
return 1;
#endif
#if TARGET_HOST_POSIX_X11
/* X11 has a mouse by definition */
case GLUT_HAS_MOUSE:
return 1 ;
case GLUT_NUM_MOUSE_BUTTONS:
/* We should be able to pass NULL when the last argument is zero,
* but at least one X server has a bug where this causes a segfault.
*
* In XFree86/Xorg servers, a mouse wheel is seen as two buttons
* rather than an Axis; "freeglut_main.c" expects this when
* checking for a wheel event.
*/
{
unsigned char map;
int nbuttons = XGetPointerMapping(fgDisplay.Display, &map,0);
return nbuttons;
}
#elif TARGET_HOST_MS_WINDOWS
case GLUT_HAS_MOUSE:
/*
* MS Windows can be booted without a mouse.
*/
return GetSystemMetrics( SM_MOUSEPRESENT );
case GLUT_NUM_MOUSE_BUTTONS:
# if defined(_WIN32_WCE)
return 1;
# else
return GetSystemMetrics( SM_CMOUSEBUTTONS );
# endif
#endif
case GLUT_HAS_JOYSTICK:
return fgJoystickDetect ();
case GLUT_OWNS_JOYSTICK:
return fgState.JoysticksInitialised;
case GLUT_JOYSTICK_POLL_RATE:
return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.JoystickPollRate : 0;
/* XXX The following two are only for Joystick 0 but this is an improvement */
case GLUT_JOYSTICK_BUTTONS:
return glutJoystickGetNumButtons ( 0 );
case GLUT_JOYSTICK_AXES:
return glutJoystickGetNumAxes ( 0 );
case GLUT_HAS_DIAL_AND_BUTTON_BOX:
return fgInputDeviceDetect ();
case GLUT_NUM_DIALS:
if ( fgState.InputDevsInitialised ) return 8;
return 0;
case GLUT_NUM_BUTTON_BOX_BUTTONS:
return 0;
case GLUT_HAS_SPACEBALL:
return fgHasSpaceball();
case GLUT_HAS_TABLET:
return 0;
case GLUT_NUM_SPACEBALL_BUTTONS:
return fgSpaceballNumButtons();
case GLUT_NUM_TABLET_BUTTONS:
return 0;
case GLUT_DEVICE_IGNORE_KEY_REPEAT:
return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.IgnoreKeyRepeat : 0;
case GLUT_DEVICE_KEY_REPEAT:
return fgState.KeyRepeat;
default:
fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
break;
}
/* And now -- the failure. */
return -1;
}
/*
* This should return the current state of ALT, SHIFT and CTRL keys.
*/
int FGAPIENTRY glutGetModifiers( void )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetModifiers" );
if( fgState.Modifiers == INVALID_MODIFIERS )
{
fgWarning( "glutGetModifiers() called outside an input callback" );
return 0;
}
return fgState.Modifiers;
}
/*
* Return the state of the GLUT API overlay subsystem. A misery ;-)
*/
int FGAPIENTRY glutLayerGet( GLenum eWhat )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLayerGet" );
/*
* This is easy as layers are not implemented ;-)
*
* XXX Can we merge the UNIX/X11 and WIN32 sections? Or
* XXX is overlay support planned?
*/
switch( eWhat )
{
#if TARGET_HOST_POSIX_X11
case GLUT_OVERLAY_POSSIBLE:
return 0;
case GLUT_LAYER_IN_USE:
return GLUT_NORMAL;
case GLUT_HAS_OVERLAY:
return 0;
case GLUT_TRANSPARENT_INDEX:
/*
* Return just anything, which is always defined as zero
*
* XXX HUH?
*/
return 0;
case GLUT_NORMAL_DAMAGED:
/* XXX Actually I do not know. Maybe. */
return 0;
case GLUT_OVERLAY_DAMAGED:
return -1;
#elif TARGET_HOST_MS_WINDOWS
case GLUT_OVERLAY_POSSIBLE:
/* return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
PFD_OVERLAY_PLANE ); */
return 0 ;
case GLUT_LAYER_IN_USE:
return GLUT_NORMAL;
case GLUT_HAS_OVERLAY:
return 0;
case GLUT_TRANSPARENT_INDEX:
/*
* Return just anything, which is always defined as zero
*
* XXX HUH?
*/
return 0;
case GLUT_NORMAL_DAMAGED:
/* XXX Actually I do not know. Maybe. */
return 0;
case GLUT_OVERLAY_DAMAGED:
return -1;
#endif
default:
fgWarning( "glutLayerGet(): missing enum handle %d", eWhat );
break;
}
/* And fail. That's good. Programs do love failing. */
return -1;
}
int * FGAPIENTRY glutGetModeValues(GLenum eWhat, int * size)
{
int * array;
#if TARGET_HOST_POSIX_X11
int attributes[9];
GLXFBConfig * fbconfigArray; /* Array of FBConfigs */
int fbconfigArraySize; /* Number of FBConfigs in the array */
int attribute_name = 0;
#endif
FREEGLUT_EXIT_IF_NOT_INITIALISED("glutGetModeValues");
array = NULL;
*size = 0;
switch (eWhat)
{
#if TARGET_HOST_POSIX_X11
case GLUT_AUX:
case GLUT_MULTISAMPLE:
attributes[0] = GLX_BUFFER_SIZE;
attributes[1] = GLX_DONT_CARE;
switch (eWhat)
{
case GLUT_AUX:
/*
FBConfigs are now sorted by increasing number of auxiliary
buffers. We want at least one buffer.
*/
attributes[2] = GLX_AUX_BUFFERS;
attributes[3] = 1;
attributes[4] = None;
attribute_name = GLX_AUX_BUFFERS;
break;
case GLUT_MULTISAMPLE:
attributes[2] = GLX_AUX_BUFFERS;
attributes[3] = GLX_DONT_CARE;
attributes[4] = GLX_SAMPLE_BUFFERS;
attributes[5] = 1;
/*
FBConfigs are now sorted by increasing number of samples per
pixel. We want at least one sample.
*/
attributes[6] = GLX_SAMPLES;
attributes[7] = 1;
attributes[8] = None;
attribute_name = GLX_SAMPLES;
break;
}
fbconfigArray = glXChooseFBConfig(fgDisplay.Display,
fgDisplay.Screen,
attributes,
&fbconfigArraySize);
if (fbconfigArray != NULL)
{
int * temp_array;
int result; /* Returned by glXGetFBConfigAttrib. Not checked. */
int previous_value;
int i;
temp_array = malloc(sizeof(int) * fbconfigArraySize);
previous_value = 0;
for (i = 0; i < fbconfigArraySize; i++)
{
int value;
result = glXGetFBConfigAttrib(fgDisplay.Display,
fbconfigArray[i],
attribute_name,
&value);
if (value > previous_value)
{
temp_array[*size] = value;
previous_value = value;
(*size)++;
}
}
array = malloc(sizeof(int) * (*size));
for (i = 0; i < *size; i++)
{
array[i] = temp_array[i];
}
free(temp_array);
XFree(fbconfigArray);
}
break;
#endif
default:
break;
}
return array;
}
/*** END OF FILE ***/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,598 @@
/*
* freeglut_structure.c
*
* Windows and menus need tree structure
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Sat Dec 18 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/* -- GLOBAL EXPORTS ------------------------------------------------------- */
/*
* The SFG_Structure container holds information about windows and menus
* created between glutInit() and glutMainLoop() return.
*/
SFG_Structure fgStructure = { { NULL, NULL }, /* The list of windows */
{ NULL, NULL }, /* The list of menus */
{ NULL, NULL }, /* Windows to Destroy list */
NULL, /* The current window */
NULL, /* The current menu */
NULL, /* The menu OpenGL context */
NULL, /* The game mode window */
0, /* The current new window ID */
0 }; /* The current new menu ID */
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
static void fghClearCallBacks( SFG_Window *window )
{
if( window )
{
int i;
for( i = 0; i < TOTAL_CALLBACKS; ++i )
window->CallBacks[ i ] = NULL;
}
}
/*
* This private function creates, opens and adds to the hierarchy
* a freeglut window complete with OpenGL context and stuff...
*
* If parent is set to NULL, the window created will be a topmost one.
*/
SFG_Window* fgCreateWindow( SFG_Window* parent, const char* title,
GLboolean positionUse, int x, int y,
GLboolean sizeUse, int w, int h,
GLboolean gameMode, GLboolean isMenu )
{
/* Have the window object created */
SFG_Window *window = (SFG_Window *)calloc( sizeof(SFG_Window), 1 );
#if TARGET_HOST_UNIX_X11
window->Window.FBConfig = NULL;
#endif
fghClearCallBacks( window );
/* Initialize the object properties */
window->ID = ++fgStructure.WindowID;
#if TARGET_HOST_POSIX_X11
window->State.OldHeight = window->State.OldWidth = -1;
#endif
fgListInit( &window->Children );
if( parent )
{
fgListAppend( &parent->Children, &window->Node );
window->Parent = parent;
}
else
fgListAppend( &fgStructure.Windows, &window->Node );
/* Set the default mouse cursor and reset the modifiers value */
window->State.Cursor = GLUT_CURSOR_INHERIT;
window->IsMenu = isMenu;
window->State.IgnoreKeyRepeat = GL_FALSE;
window->State.KeyRepeating = GL_FALSE;
window->State.IsFullscreen = GL_FALSE;
/*
* Open the window now. The fgOpenWindow() function is system
* dependant, and resides in freeglut_window.c. Uses fgState.
*/
fgOpenWindow( window, title, positionUse, x, y, sizeUse, w, h, gameMode,
(GLboolean)(parent ? GL_TRUE : GL_FALSE) );
return window;
}
/*
* This private function creates a menu and adds it to the menus list
*/
SFG_Menu* fgCreateMenu( FGCBMenu menuCallback )
{
int x = 100, y = 100, w = 1, h = 1;
SFG_Window *current_window = fgStructure.CurrentWindow;
/* Have the menu object created */
SFG_Menu* menu = (SFG_Menu *)calloc( sizeof(SFG_Menu), 1 );
menu->ParentWindow = NULL;
/* Create a window for the menu to reside in. */
fgCreateWindow( NULL, "freeglut menu", GL_TRUE, x, y, GL_TRUE, w, h,
GL_FALSE, GL_TRUE );
menu->Window = fgStructure.CurrentWindow;
glutDisplayFunc( fgDisplayMenu );
glutHideWindow( ); /* Hide the window for now */
fgSetWindow( current_window );
/* Initialize the object properties: */
menu->ID = ++fgStructure.MenuID;
menu->Callback = menuCallback;
menu->ActiveEntry = NULL;
fgListInit( &menu->Entries );
fgListAppend( &fgStructure.Menus, &menu->Node );
/* Newly created menus implicitly become current ones */
fgStructure.CurrentMenu = menu;
return menu;
}
/*
* Function to add a window to the linked list of windows to destroy.
* Subwindows are automatically added because they hang from the window
* structure.
*/
void fgAddToWindowDestroyList( SFG_Window* window )
{
SFG_WindowList *new_list_entry =
( SFG_WindowList* )malloc( sizeof(SFG_WindowList ) );
new_list_entry->window = window;
fgListAppend( &fgStructure.WindowsToDestroy, &new_list_entry->node );
/* Check if the window is the current one... */
if( fgStructure.CurrentWindow == window )
fgStructure.CurrentWindow = NULL;
/*
* Clear all window callbacks except Destroy, which will
* be invoked later. Right now, we are potentially carrying
* out a freeglut operation at the behest of a client callback,
* so we are reluctant to re-enter the client with the Destroy
* callback, right now. The others are all wiped out, however,
* to ensure that they are no longer called after this point.
*/
{
FGCBDestroy destroy = (FGCBDestroy)FETCH_WCB( *window, Destroy );
fghClearCallBacks( window );
SET_WCB( *window, Destroy, destroy );
}
}
/*
* Function to close down all the windows in the "WindowsToDestroy" list
*/
void fgCloseWindows( )
{
while( fgStructure.WindowsToDestroy.First )
{
SFG_WindowList *window_ptr = fgStructure.WindowsToDestroy.First;
fgDestroyWindow( window_ptr->window );
fgListRemove( &fgStructure.WindowsToDestroy, &window_ptr->node );
free( window_ptr );
}
}
/*
* This function destroys a window and all of its subwindows. Actually,
* another function, defined in freeglut_window.c is called, but this is
* a whole different story...
*/
void fgDestroyWindow( SFG_Window* window )
{
FREEGLUT_INTERNAL_ERROR_EXIT ( window, "Window destroy function called with null window",
"fgDestroyWindow" );
while( window->Children.First )
fgDestroyWindow( ( SFG_Window * )window->Children.First );
{
SFG_Window *activeWindow = fgStructure.CurrentWindow;
INVOKE_WCB( *window, Destroy, ( ) );
fgSetWindow( activeWindow );
}
if( window->Parent )
fgListRemove( &window->Parent->Children, &window->Node );
else
fgListRemove( &fgStructure.Windows, &window->Node );
if( window->ActiveMenu )
fgDeactivateMenu( window );
fghClearCallBacks( window );
fgCloseWindow( window );
free( window );
if( fgStructure.CurrentWindow == window )
fgStructure.CurrentWindow = NULL;
}
/*
* This is a helper static function that removes a menu (given its pointer)
* from any windows that can be accessed from a given parent...
*/
static void fghRemoveMenuFromWindow( SFG_Window* window, SFG_Menu* menu )
{
SFG_Window *subWindow;
int i;
/* Check whether this is the active menu in the window */
if ( menu == window->ActiveMenu )
window->ActiveMenu = NULL ;
/*
* Check if the menu is attached to the current window,
* if so, have it detached (by overwriting with a NULL):
*/
for( i = 0; i < FREEGLUT_MAX_MENUS; i++ )
if( window->Menu[ i ] == menu )
window->Menu[ i ] = NULL;
/* Call this function for all of the window's children recursively: */
for( subWindow = (SFG_Window *)window->Children.First;
subWindow;
subWindow = (SFG_Window *)subWindow->Node.Next)
fghRemoveMenuFromWindow( subWindow, menu );
}
/*
* This is a static helper function that removes menu references
* from another menu, given two pointers to them...
*/
static void fghRemoveMenuFromMenu( SFG_Menu* from, SFG_Menu* menu )
{
SFG_MenuEntry *entry;
for( entry = (SFG_MenuEntry *)from->Entries.First;
entry;
entry = ( SFG_MenuEntry * )entry->Node.Next )
if( entry->SubMenu == menu )
entry->SubMenu = NULL;
}
/*
* This function destroys a menu specified by the parameter. All menus
* and windows are updated to make sure no ill pointers hang around.
*/
void fgDestroyMenu( SFG_Menu* menu )
{
SFG_Window *window;
SFG_Menu *from;
FREEGLUT_INTERNAL_ERROR_EXIT ( menu, "Menu destroy function called with null menu",
"fgDestroyMenu" );
/* First of all, have all references to this menu removed from all windows: */
for( window = (SFG_Window *)fgStructure.Windows.First;
window;
window = (SFG_Window *)window->Node.Next )
fghRemoveMenuFromWindow( window, menu );
/* Now proceed with removing menu entries that lead to this menu */
for( from = ( SFG_Menu * )fgStructure.Menus.First;
from;
from = ( SFG_Menu * )from->Node.Next )
fghRemoveMenuFromMenu( from, menu );
/*
* If the programmer defined a destroy callback, call it
* A. Donev: But first make this the active menu
*/
if( menu->Destroy )
{
SFG_Menu *activeMenu=fgStructure.CurrentMenu;
fgStructure.CurrentMenu = menu;
menu->Destroy( );
fgStructure.CurrentMenu = activeMenu;
}
/*
* Now we are pretty sure the menu is not used anywhere
* and that we can remove all of its entries
*/
while( menu->Entries.First )
{
SFG_MenuEntry *entry = ( SFG_MenuEntry * ) menu->Entries.First;
fgListRemove( &menu->Entries, &entry->Node );
if( entry->Text )
free( entry->Text );
entry->Text = NULL;
free( entry );
}
if( fgStructure.CurrentWindow == menu->Window )
fgSetWindow( NULL );
fgDestroyWindow( menu->Window );
fgListRemove( &fgStructure.Menus, &menu->Node );
if( fgStructure.CurrentMenu == menu )
fgStructure.CurrentMenu = NULL;
free( menu );
}
/*
* This function should be called on glutInit(). It will prepare the internal
* structure of freeglut to be used in the application. The structure will be
* destroyed using fgDestroyStructure() on glutMainLoop() return. In that
* case further use of freeglut should be preceeded with a glutInit() call.
*/
void fgCreateStructure( void )
{
/*
* We will be needing two lists: the first containing windows,
* and the second containing the user-defined menus.
* Also, no current window/menu is set, as none has been created yet.
*/
fgListInit(&fgStructure.Windows);
fgListInit(&fgStructure.Menus);
fgListInit(&fgStructure.WindowsToDestroy);
fgStructure.CurrentWindow = NULL;
fgStructure.CurrentMenu = NULL;
fgStructure.MenuContext = NULL;
fgStructure.GameModeWindow = NULL;
fgStructure.WindowID = 0;
fgStructure.MenuID = 0;
}
/*
* This function is automatically called on glutMainLoop() return.
* It should deallocate and destroy all remnants of previous
* glutInit()-enforced structure initialization...
*/
void fgDestroyStructure( void )
{
/* Clean up the WindowsToDestroy list. */
fgCloseWindows( );
/* Make sure all windows and menus have been deallocated */
while( fgStructure.Menus.First )
fgDestroyMenu( ( SFG_Menu * )fgStructure.Menus.First );
while( fgStructure.Windows.First )
fgDestroyWindow( ( SFG_Window * )fgStructure.Windows.First );
}
/*
* Helper function to enumerate through all registered top-level windows
*/
void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
{
SFG_Window *window;
FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator,
"Enumerator or callback missing from window enumerator call",
"fgEnumWindows" );
/* Check every of the top-level windows */
for( window = ( SFG_Window * )fgStructure.Windows.First;
window;
window = ( SFG_Window * )window->Node.Next )
{
enumCallback( window, enumerator );
if( enumerator->found )
return;
}
}
/*
* Helper function to enumerate through all a window's subwindows
* (single level descent)
*/
void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
SFG_Enumerator* enumerator )
{
SFG_Window *child;
FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator,
"Enumerator or callback missing from subwindow enumerator call",
"fgEnumSubWindows" );
FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Window Enumeration" );
for( child = ( SFG_Window * )window->Children.First;
child;
child = ( SFG_Window * )child->Node.Next )
{
enumCallback( child, enumerator );
if( enumerator->found )
return;
}
}
/*
* A static helper function to look for a window given its handle
*/
static void fghcbWindowByHandle( SFG_Window *window,
SFG_Enumerator *enumerator )
{
if ( enumerator->found )
return;
/* Check the window's handle. Hope this works. Looks ugly. That's for sure. */
if( window->Window.Handle == (SFG_WindowHandleType) (enumerator->data) )
{
enumerator->found = GL_TRUE;
enumerator->data = window;
return;
}
/* Otherwise, check this window's children */
fgEnumSubWindows( window, fghcbWindowByHandle, enumerator );
}
/*
* fgWindowByHandle returns a (SFG_Window *) value pointing to the
* first window in the queue matching the specified window handle.
* The function is defined in freeglut_structure.c file.
*/
SFG_Window* fgWindowByHandle ( SFG_WindowHandleType hWindow )
{
SFG_Enumerator enumerator;
/* This is easy and makes use of the windows enumeration defined above */
enumerator.found = GL_FALSE;
enumerator.data = (void *)hWindow;
fgEnumWindows( fghcbWindowByHandle, &enumerator );
if( enumerator.found )
return( SFG_Window *) enumerator.data;
return NULL;
}
/*
* A static helper function to look for a window given its ID
*/
static void fghcbWindowByID( SFG_Window *window, SFG_Enumerator *enumerator )
{
/* Make sure we do not overwrite our precious results... */
if( enumerator->found )
return;
/* Check the window's handle. Hope this works. Looks ugly. That's for sure. */
if( window->ID == *( int *)(enumerator->data) )
{
enumerator->found = GL_TRUE;
enumerator->data = window;
return;
}
/* Otherwise, check this window's children */
fgEnumSubWindows( window, fghcbWindowByID, enumerator );
}
/*
* This function is similiar to the previous one, except it is
* looking for a specified (sub)window identifier. The function
* is defined in freeglut_structure.c file.
*/
SFG_Window* fgWindowByID( int windowID )
{
SFG_Enumerator enumerator;
/* Uses a method very similiar for fgWindowByHandle... */
enumerator.found = GL_FALSE;
enumerator.data = ( void * )&windowID;
fgEnumWindows( fghcbWindowByID, &enumerator );
if( enumerator.found )
return ( SFG_Window * )enumerator.data;
return NULL;
}
/*
* Looks up a menu given its ID. This is easier that fgWindowByXXX
* as all menus are placed in one doubly linked list...
*/
SFG_Menu* fgMenuByID( int menuID )
{
SFG_Menu *menu = NULL;
/* It's enough to check all entries in fgStructure.Menus... */
for( menu = (SFG_Menu *)fgStructure.Menus.First;
menu;
menu = (SFG_Menu *)menu->Node.Next )
if( menu->ID == menuID )
return menu;
return NULL;
}
/*
* List functions...
*/
void fgListInit(SFG_List *list)
{
list->First = NULL;
list->Last = NULL;
}
void fgListAppend(SFG_List *list, SFG_Node *node)
{
if ( list->Last )
{
SFG_Node *ln = (SFG_Node *) list->Last;
ln->Next = node;
node->Prev = ln;
}
else
{
node->Prev = NULL;
list->First = node;
}
node->Next = NULL;
list->Last = node;
}
void fgListRemove(SFG_List *list, SFG_Node *node)
{
if( node->Next )
( ( SFG_Node * )node->Next )->Prev = node->Prev;
if( node->Prev )
( ( SFG_Node * )node->Prev )->Next = node->Next;
if( ( ( SFG_Node * )list->First ) == node )
list->First = node->Next;
if( ( ( SFG_Node * )list->Last ) == node )
list->Last = node->Prev;
}
int fgListLength(SFG_List *list)
{
SFG_Node *node;
int length = 0;
for( node =( SFG_Node * )list->First;
node;
node = ( SFG_Node * )node->Next )
++length;
return length;
}
void fgListInsert(SFG_List *list, SFG_Node *next, SFG_Node *node)
{
SFG_Node *prev;
if( (node->Next = next) )
{
prev = next->Prev;
next->Prev = node;
}
else
{
prev = list->Last;
list->Last = node;
}
if( (node->Prev = prev) )
prev->Next = node;
else
list->First = node;
}
/*** END OF FILE ***/

View File

@ -0,0 +1,200 @@
/*
* freeglut_teapot.c
*
* Teapot(tm) rendering code.
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Fri Dec 24 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Original teapot code copyright follows:
*/
/*
* (c) Copyright 1993, Silicon Graphics, Inc.
*
* ALL RIGHTS RESERVED
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that
* both the copyright notice and this permission notice appear in
* supporting documentation, and that the name of Silicon
* Graphics, Inc. not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
* "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
* OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
* EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
* ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
* INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
* SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
* NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
* OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer
* Software clause at DFARS 252.227-7013 and/or in similar or
* successor clauses in the FAR or the DOD or NASA FAR
* Supplement. Unpublished-- rights reserved under the copyright
* laws of the United States. Contractor/manufacturer is Silicon
* Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
* 94039-7311.
*
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
#include "freeglut_teapot_data.h"
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
static void fghTeapot( GLint grid, GLdouble scale, GLenum type )
{
#if defined(_WIN32_WCE)
int i, numV=sizeof(strip_vertices)/4, numI=sizeof(strip_normals)/4;
#else
double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
long i, j, k, l;
#endif
glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT );
glEnable( GL_AUTO_NORMAL );
glEnable( GL_NORMALIZE );
glEnable( GL_MAP2_VERTEX_3 );
glEnable( GL_MAP2_TEXTURE_COORD_2 );
glPushMatrix();
glRotated( 270.0, 1.0, 0.0, 0.0 );
glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale );
glTranslated( 0.0, 0.0, -1.5 );
#if defined(_WIN32_WCE)
glRotated( 90.0, 1.0, 0.0, 0.0 );
glBegin( GL_TRIANGLE_STRIP );
for( i = 0; i < numV-1; i++ )
{
int vidx = strip_vertices[i],
nidx = strip_normals[i];
if( vidx != -1 )
{
glNormal3fv( normals[nidx] );
glVertex3fv( vertices[vidx] );
}
else
{
glEnd();
glBegin( GL_TRIANGLE_STRIP );
}
}
glEnd();
#else
for (i = 0; i < 10; i++) {
for (j = 0; j < 4; j++) {
for (k = 0; k < 4; k++) {
for (l = 0; l < 3; l++) {
p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 1)
q[j][k][l] *= -1.0;
if (i < 6) {
r[j][k][l] =
cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 0)
r[j][k][l] *= -1.0;
s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
if (l == 0)
s[j][k][l] *= -1.0;
if (l == 1)
s[j][k][l] *= -1.0;
}
}
}
}
glMap2d(GL_MAP2_TEXTURE_COORD_2, 0.0, 1.0, 2, 2, 0.0, 1.0, 4, 2,
&tex[0][0][0]);
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
&p[0][0][0]);
glMapGrid2d(grid, 0.0, 1.0, grid, 0.0, 1.0);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
&q[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
if (i < 6) {
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
&r[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
&s[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
}
}
#endif /* defined(_WIN32_WCE) */
glPopMatrix();
glPopAttrib();
}
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
/*
* Renders a beautiful wired teapot...
*/
void FGAPIENTRY glutWireTeapot( GLdouble size )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTeapot" );
/* We will use the general teapot rendering code */
fghTeapot( 10, size, GL_LINE );
}
/*
* Renders a beautiful filled teapot...
*/
void FGAPIENTRY glutSolidTeapot( GLdouble size )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTeapot" );
/* We will use the general teapot rendering code */
fghTeapot( 7, size, GL_FILL );
}
/*** END OF FILE ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
/*
* freeglut_videoresize.c
*
* Video resize functions (as defined by GLUT API)
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 16 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <GL/freeglut.h>
#include "freeglut_internal.h"
/*
* NOTE: functions declared in this file probably will not be implemented.
*/
/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
int FGAPIENTRY glutVideoResizeGet( GLenum eWhat ) { return( 0x00 ); }
void FGAPIENTRY glutSetupVideoResizing( void ) { /* Not implemented */ }
void FGAPIENTRY glutStopVideoResizing( void ) { /* Not implemented */ }
void FGAPIENTRY glutVideoResize( int x, int y, int w, int h ) { /* Not implemented */ }
void FGAPIENTRY glutVideoPan( int x, int y, int w, int h ) { /* Not implemented */ }
/*** END OF FILE ***/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,219 @@
/* Written for XI1 by Nikolas Doerfler <doerflen@in.tum.de> (c) 2008 *
* Rewritten for XI2 by Florian Echtler <echtler@in.tum.de> (c) 2009 */
#include <GL/freeglut.h>
#include "freeglut_internal.h"
#if TARGET_HOST_POSIX_X11 && HAVE_X11_EXTENSIONS_XINPUT2_H
#include <errno.h>
#include <stdarg.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
/* import function from freeglut_main.c */
int fghGetXModifiers( int state );
/* extension opcode for XInput */
int xi_opcode = -1;
/**
* \brief Sets window up for XI2 events.
*/
void fgRegisterDevices( Display* dpy, Window* win ) {
XIEventMask mask;
unsigned char flags[2] = { 0, 0 };
int event, error;
/*Display* dpy = fgDisplay.Display;
Window* win = glutGetXWindow();*/
/* get XInput extension opcode */
if (!XQueryExtension( dpy, "XInputExtension", &xi_opcode, &event, &error )) { xi_opcode = -1; }
/* Select for motion events */
mask.deviceid = XIAllMasterDevices;
mask.mask_len = 2;
mask.mask = flags;
XISetMask(mask.mask, XI_Enter);
XISetMask(mask.mask, XI_Motion);
XISetMask(mask.mask, XI_ButtonPress);
XISetMask(mask.mask, XI_ButtonRelease);
XISetMask(mask.mask, XI_Leave);
/*XISetMask(mask.mask, XI_KeyPress);
XISetMask(mask.mask, XI_KeyRelease);
XISetMask(mask.mask, XI_DeviceChanged);
XISetMask(mask.mask, XI_RawEvent);
XISetMask(mask.mask, XI_FocusIn);
XISetMask(mask.mask, XI_FocusOut);
XISetMask(mask.mask, XI_HierarchyChanged);*/
XISelectEvents( dpy, *win, &mask, 1 );
}
void fgPrintXILeaveEvent(XILeaveEvent* event)
{
char* mode = "";
char* detail = "";
int i;
printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
event->root, event->event, event->child);
switch(event->mode)
{
case NotifyNormal: mode = "NotifyNormal"; break;
case NotifyGrab: mode = "NotifyGrab"; break;
case NotifyUngrab: mode = "NotifyUngrab"; break;
case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
}
switch (event->detail)
{
case NotifyAncestor: detail = "NotifyAncestor"; break;
case NotifyVirtual: detail = "NotifyVirtual"; break;
case NotifyInferior: detail = "NotifyInferior"; break;
case NotifyNonlinear: detail = "NotifyNonlinear"; break;
case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
case NotifyPointer: detail = "NotifyPointer"; break;
case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
case NotifyDetailNone: detail = "NotifyDetailNone"; break;
}
printf(" mode: %s (detail %s)\n", mode, detail);
printf(" flags: %s %s\n", event->focus ? "[focus]" : "",
event->same_screen ? "[same screen]" : "");
printf(" buttons:");
for (i = 0; i < event->buttons.mask_len * 8; i++)
if (XIMaskIsSet(event->buttons.mask, i))
printf(" %d", i);
printf("\n");
printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
event->mods.locked, event->mods.latched,
event->mods.base);
printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
event->group.locked, event->group.latched,
event->group.base);
printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
}
void fgPrintXIDeviceEvent(XIDeviceEvent* event)
{
double *val;
int i;
printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
printf(" detail: %d\n", event->detail);
printf(" buttons:");
for (i = 0; i < event->buttons.mask_len * 8; i++)
if (XIMaskIsSet(event->buttons.mask, i))
printf(" %d", i);
printf("\n");
printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
event->mods.locked, event->mods.latched,
event->mods.base);
printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
event->group.locked, event->group.latched,
event->group.base);
printf(" valuators:");
val = event->valuators.values;
for (i = 0; i < event->valuators.mask_len * 8; i++)
if (XIMaskIsSet(event->valuators.mask, i))
printf(" %d: %.2f", i, *val++);
printf("\n");
printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
event->root, event->event, event->child);
printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
}
/**
* \brief This function is called when an Extension Event is received
* and calls the corresponding callback functions for these events.
*/
void fgHandleExtensionEvents( XEvent* base_ev ) {
int i, button = 0;
XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
if ( XGetEventData( fgDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
/*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
SFG_Window* window = fgWindowByHandle( event->event );
if (!window) return;
switch (cookie->evtype) {
case XI_Enter:
case XI_Leave:
fgState.Modifiers = fghGetXModifiers( ((XIEnterEvent*)event)->mods.base );
INVOKE_WCB( *window, MultiEntry, (
event->deviceid,
(event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
));
#if _DEBUG
fgPrintXILeaveEvent((XILeaveEvent*)event);
#endif
break;
case XI_ButtonPress:
case XI_ButtonRelease:
fgState.Modifiers = fghGetXModifiers( event->mods.base );
INVOKE_WCB( *window, MultiButton, (
event->deviceid,
event->event_x,
event->event_y,
(event->detail)-1,
(event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
));
INVOKE_WCB( *window, Mouse, (
(event->detail)-1,
(event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP),
event->event_x,
event->event_y
));
break;
case XI_Motion:
fgState.Modifiers = fghGetXModifiers( event->mods.base );
for (i = 0; i < event->buttons.mask_len; i++) if (event->buttons.mask[i]) button = 1;
if (button) {
INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) );
INVOKE_WCB( *window, Motion, ( event->event_x, event->event_y ) );
} else {
INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
INVOKE_WCB( *window, Passive, ( event->event_x, event->event_y ) );
}
#if _DEBUG
fgPrintXIDeviceEvent(event);
#endif
break;
default:
#if _DEBUG
fgWarning( "Unknown XI2 device event:" );
fgPrintXIDeviceEvent( event );
#endif
break;
}
fgState.Modifiers = INVALID_MODIFIERS;
}
XFreeEventData( fgDisplay.Display, cookie );
}
#endif

View File

@ -0,0 +1,21 @@
#ifndef __GLUT_H__
#define __GLUT_H__
/*
* glut.h
*
* The freeglut library include file
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "freeglut_std.h"
/*** END OF FILE ***/
#endif /* __GLUT_H__ */

View File

@ -0,0 +1,97 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "Camera.h"
#include "definitions.h"
#include <cmath>
// Namespaces
using namespace openglframework;
// Constructor
Camera::Camera() : Object3D() {
// Set default values
mFieldOfView = 45.0f;
mSceneRadius = 1.0f;
mNearPlane = 0.1f;
mFarPlane = 10.0f;
mWidth = 1;
mHeight = 1;
// Update the projection matrix
updateProjectionMatrix();
}
// Destructor
Camera::~Camera() {
}
// Update the projection matrix
void Camera::updateProjectionMatrix() {
// Compute the aspect ratio
float aspect = float(mWidth) / float(mHeight);
float top = mNearPlane * tan((mFieldOfView / 2.0f) * (float(PI) / 180.0f));
float bottom = -top;
float left = bottom * aspect;
float right = top * aspect;
float fx = 2.0f * mNearPlane / (right - left);
float fy = 2.0f * mNearPlane / (top - bottom);
float fz = -(mFarPlane + mNearPlane) / (mFarPlane - mNearPlane);
float fw = -2.0f * mFarPlane * mNearPlane / (mFarPlane - mNearPlane);
// Recompute the projection matrix
mProjectionMatrix = Matrix4(fx, 0, 0, 0,
0, fy, 0, 0,
0, 0, fz, fw,
0, 0, -1, 0);
}
// Translate the camera go a given point using the dx, dy fraction
void Camera::translateCamera(float dx, float dy, const Vector3& worldPoint) {
// Transform the world point into camera coordinates
Vector3 pointCamera = mTransformMatrix.getInverse() * worldPoint;
// Get the depth
float z = -pointCamera.z;
// Find the scaling of dx and dy from windows coordinates to near plane coordinates
// and from there to camera coordinates at the object's depth
float aspect = float(mWidth) / float(mHeight);
float top = mNearPlane * tan(mFieldOfView * PI / 360.0f);
float right = top * aspect;
// Translate the camera
translateLocal(Vector3(2.0f * dx * right / mNearPlane * z,
-2.0f * dy * top / mNearPlane * z,
0.0f));
}

View File

@ -0,0 +1,181 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef CAMERA_H
#define CAMERA_H
// Libraries
#include "Object3D.h"
#include "definitions.h"
namespace openglframework {
// Class Camera
class Camera : public Object3D {
protected :
// ------------------- Attributes ------------------- //
// Field of view
float mFieldOfView;
// Radius of the scene
float mSceneRadius;
// Near plane
float mNearPlane;
// Far plane
float mFarPlane;
// Width of the camera
uint mWidth;
// Height of the camera
uint mHeight;
// Projection matrix
Matrix4 mProjectionMatrix;
// ------------------- Methods ------------------- //
// Update the projection matrix
void updateProjectionMatrix();
public:
// ------------------- Methods ------------------- //
// Constructor
Camera();
// Destructor
~Camera();
// Get the projection matrix
const Matrix4& getProjectionMatrix() const;
// Set the dimensions of the camera
void setDimensions(uint width, uint height);
// Get the radius of the scene the camera should capture
float getSceneRadius() const;
// Set the radius of the scene the camera should capture
// This will update the clipping planes accordingly
void setSceneRadius(float radius);
// Set the clipping planes
void setClippingPlanes(float near, float far);
// Set the field of view
void setFieldOfView(float fov);
// Set the zoom of the camera (a fraction between 0 and 1)
void setZoom(float fraction);
// Translate the camera go a given point using the dx, dy fraction
void translateCamera(float dx, float dy, const Vector3& worldPoint);
// Get the near clipping plane
float getNearClippingPlane() const;
// Get the far clipping plane
float getFarClippingPlane() const;
// Get the width
uint getWidth() const;
// Get the height
uint getHeight() const;
};
// Get the projection matrix
inline const Matrix4& Camera::getProjectionMatrix() const {
return mProjectionMatrix;
}
// Set the dimensions of the camera
inline void Camera::setDimensions(uint width, uint height) {
mWidth = width;
mHeight = height;
updateProjectionMatrix();
}
// Get the radius of the scene the camera should capture
inline float Camera::getSceneRadius() const {
return mSceneRadius;
}
// Set the radius of the scene the camera should capture
// This will update the clipping planes accordingly
inline void Camera::setSceneRadius(float radius) {
mSceneRadius = radius;
setClippingPlanes(0.01f * radius, 10.0f * radius);
}
// Set the clipping planes
inline void Camera::setClippingPlanes(float near, float far) {
mNearPlane = near;
mFarPlane = far;
updateProjectionMatrix();
}
// Set the field of view
inline void Camera::setFieldOfView(float fov) {
mFieldOfView = fov;
updateProjectionMatrix();
}
// Set the zoom of the camera (a fraction between 0 and 1)
inline void Camera::setZoom(float fraction) {
Vector3 zoomVector(0, 0, mSceneRadius * fraction * 3.0f);
translateLocal(zoomVector);
}
// Get the near clipping plane
inline float Camera::getNearClippingPlane() const {
return mNearPlane;
}
// Get the far clipping plane
inline float Camera::getFarClippingPlane() const {
return mFarPlane;
}
// Get the width
inline uint Camera::getWidth() const {
return mWidth;
}
// Get the height
inline uint Camera::getHeight() const {
return mHeight;
}
}
#endif

View File

@ -0,0 +1,115 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "FrameBufferObject.h"
#include <iostream>
using namespace openglframework;
using namespace std;
// Constructor
FrameBufferObject::FrameBufferObject() : mFrameBufferID(0), mRenderBufferID (0) {
}
// Destructor
FrameBufferObject::~FrameBufferObject() {
}
// Create the frame buffer object
bool FrameBufferObject::create(uint width, uint height, bool needRenderBuffer) {
// Destroy the current FBO
destroy();
// Check that the needed OpenGL extensions are available
bool isExtensionOK = checkOpenGLExtensions();
if (!isExtensionOK) {
std::cerr << "Error : Impossible to use Framebuffer Object on this platform" << std::endl;
assert(false);
return false;
}
// Generate a new FBO
glGenFramebuffersEXT(1, &mFrameBufferID);
assert(mFrameBufferID != 0);
// If we also need to create a render buffer
if (needRenderBuffer) {
// Generate the render buffer
glGenRenderbuffers(1, &mRenderBufferID);
assert(mRenderBufferID != 0);
glBindRenderbuffer(GL_RENDERBUFFER, mRenderBufferID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
mRenderBufferID);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Check the FBO status
GLenum statusFBO = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(statusFBO != GL_FRAMEBUFFER_COMPLETE) {
std::cerr << "Error : An error occured while creating the Frame Buffer Object !" << endl;
assert(false);
return false;
}
return true;
}
// Destroy the FBO
void FrameBufferObject::destroy() {
// Delete the frame buffer object
if (mFrameBufferID) {
glDeleteFramebuffers(1, &mFrameBufferID);
mFrameBufferID = 0;
}
// Delete the render buffer
if (mRenderBufferID) {
glDeleteRenderbuffers(1, &mRenderBufferID);
}
}
// Attach a texture to the frame buffer object
void FrameBufferObject::attachTexture(uint position, uint textureID) {
assert(mFrameBufferID);
// Bind the current FBO
glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID);
// Bind the texture
glFramebufferTexture2D(GL_FRAMEBUFFER, position, GL_TEXTURE_2D, textureID, 0);
// Unbind the current FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

View File

@ -0,0 +1,105 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef FRAME_BUFFER_OBJECT_H
#define FRAME_BUFFER_OBJECT_H
// Libraries
#include "definitions.h"
#include <GL/glew.h>
#include <cassert>
#include <iostream>
namespace openglframework {
// Class FrameBufferObject
class FrameBufferObject {
private:
// -------------------- Attributes -------------------- //
// Frame buffer ID
uint mFrameBufferID;
// Render buffer ID
uint mRenderBufferID;
public:
// -------------------- Methods -------------------- //
// Constructor
FrameBufferObject();
// Destructor
~FrameBufferObject();
// Create the frame buffer object
bool create(uint width, uint height, bool needRenderBuffer = true);
// Attach a texture to the frame buffer object
void attachTexture(uint position, uint textureID);
// Bind the FBO
void bind(uint position) const;
// Unbind the FBO
void unbind() const;
// Return true if the needed OpenGL extensions are available for FBO
static bool checkOpenGLExtensions();
// Destroy the FBO
void destroy();
};
// Bind the FBO
inline void FrameBufferObject::bind(uint position) const {
assert(mFrameBufferID != 0);
glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID);
glDrawBuffer(position);
glReadBuffer(position);
}
// Unbind the FBO
inline void FrameBufferObject::unbind() const {
assert(mFrameBufferID != 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Return true if the needed OpenGL extensions are available for FBO
inline bool FrameBufferObject::checkOpenGLExtensions() {
// Check that OpenGL version is at least 3.0 or there the framebuffer object extension exists
return (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object);
}
}
#endif

View File

@ -0,0 +1,260 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "GlutViewer.h"
#include <string>
// Namespaces
using namespace openglframework;
using namespace std;
// Constructor
GlutViewer::GlutViewer() {
// Initialize the state of the mouse buttons
for (int i=0; i<10; i++) {
mIsButtonDown[i] = false;
}
}
// Destructor
GlutViewer::~GlutViewer() {
}
// Initialize the viewer
bool GlutViewer::init(int argc, char** argv, const string& windowsTitle,
const Vector2& windowsSize, const Vector2& windowsPosition,
bool isMultisamplingActive) {
// Initialize the GLUT library
bool outputValue = initGLUT(argc, argv, windowsTitle, windowsSize,
windowsPosition, isMultisamplingActive);
// Active the multi-sampling by default
if (isMultisamplingActive) {
activateMultiSampling(true);
}
return outputValue;
}
// Initialize the GLUT library
bool GlutViewer::initGLUT(int argc, char** argv, const string& windowsTitle,
const Vector2& windowsSize, const Vector2& windowsPosition,
bool isMultisamplingActive) {
// Initialize GLUT
glutInit(&argc, argv);
uint modeWithoutMultiSampling = GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH;
uint modeWithMultiSampling = GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GL_MULTISAMPLE;
uint displayMode = isMultisamplingActive ? modeWithMultiSampling : modeWithoutMultiSampling;
glutInitDisplayMode(displayMode);
// Initialize the size of the GLUT windows
glutInitWindowSize(static_cast<int>(windowsSize.x),
static_cast<int>(windowsSize.y));
// Initialize the position of the GLUT windows
glutInitWindowPosition(static_cast<int>(windowsPosition.x),
static_cast<int>(windowsPosition.y));
// Create the GLUT windows
glutCreateWindow(windowsTitle.c_str());
// Initialize the GLEW library
GLenum error = glewInit();
if (error != GLEW_OK) {
// Problem: glewInit failed, something is wrong
cerr << "GLEW Error : " << glewGetErrorString(error) << std::endl;
assert(false);
return false;
}
return true;
}
// Set the camera so that we can view the whole scene
void GlutViewer::resetCameraToViewAll() {
// Move the camera to the origin of the scene
mCamera.translateWorld(-mCamera.getOrigin());
// Move the camera to the center of the scene
mCamera.translateWorld(mCenterScene);
// Set the zoom of the camera so that the scene center is
// in negative view direction of the camera
mCamera.setZoom(1.0);
}
// Called when a GLUT mouse button event occurs
void GlutViewer::mouseButtonEvent(int button, int state, int x, int y) {
// If the mouse button is pressed
if (state == GLUT_DOWN) {
mLastMouseX = x;
mLastMouseY = y;
mIsLastPointOnSphereValid = mapMouseCoordinatesToSphere(x, y, mLastPointOnSphere);
mIsButtonDown[button] = true;
}
else { // If the mouse button is released
mIsLastPointOnSphereValid = false;
mIsButtonDown[button] = false;
// If it is a mouse wheel click event
if (button == 3) {
zoom(0, (int) (y - 0.05f * mCamera.getWidth()));
}
else if (button == 4) {
zoom(0, (int) (y + 0.05f * mCamera.getHeight()));
}
}
mModifiers = glutGetModifiers();
// Notify GLUT to redisplay
glutPostRedisplay();
}
// Called when a GLUT mouse motion event occurs
void GlutViewer::mouseMotionEvent(int xMouse, int yMouse) {
// Zoom
if ((mIsButtonDown[GLUT_LEFT_BUTTON] && mIsButtonDown[GLUT_MIDDLE_BUTTON]) ||
(mIsButtonDown[GLUT_LEFT_BUTTON] && mModifiers == GLUT_ACTIVE_ALT)) {
zoom(xMouse, yMouse);
}
// Translation
else if (mIsButtonDown[GLUT_MIDDLE_BUTTON] || mIsButtonDown[GLUT_RIGHT_BUTTON] ||
(mIsButtonDown[GLUT_LEFT_BUTTON] && (mModifiers == GLUT_ACTIVE_ALT))) {
translate(xMouse, yMouse);
}
// Rotation
else if (mIsButtonDown[GLUT_LEFT_BUTTON]) {
rotate(xMouse, yMouse);
}
// Remember the mouse position
mLastMouseX = xMouse;
mLastMouseY = yMouse;
mIsLastPointOnSphereValid = mapMouseCoordinatesToSphere(xMouse, yMouse, mLastPointOnSphere);
// Notify GLUT to redisplay
glutPostRedisplay();
}
// Map the mouse x,y coordinates to a point on a sphere
bool GlutViewer::mapMouseCoordinatesToSphere(int xMouse, int yMouse, Vector3& spherePoint) const {
int width = mCamera.getWidth();
int height = mCamera.getHeight();
if ((xMouse >= 0) && (xMouse <= width) && (yMouse >= 0) && (yMouse <= height)) {
float x = float(xMouse - 0.5f * width) / float(width);
float y = float(0.5f * height - yMouse) / float(height);
float sinx = sin(PI * x * 0.5f);
float siny = sin(PI * y * 0.5f);
float sinx2siny2 = sinx * sinx + siny * siny;
// Compute the point on the sphere
spherePoint.x = sinx;
spherePoint.y = siny;
spherePoint.z = (sinx2siny2 < 1.0) ? sqrt(1.0f - sinx2siny2) : 0.0f;
return true;
}
return false;
}
// Zoom the camera
void GlutViewer::zoom(int xMouse, int yMouse) {
float dy = static_cast<float>(yMouse - mLastMouseY);
float h = static_cast<float>(mCamera.getHeight());
// Zoom the camera
mCamera.setZoom(-dy / h);
}
// Translate the camera
void GlutViewer::translate(int xMouse, int yMouse) {
float dx = static_cast<float>(xMouse - mLastMouseX);
float dy = static_cast<float>(yMouse - mLastMouseY);
// Translate the camera
mCamera.translateCamera(-dx / float(mCamera.getWidth()),
-dy / float(mCamera.getHeight()), mCenterScene);
}
// Rotate the camera
void GlutViewer::rotate(int xMouse, int yMouse) {
if (mIsLastPointOnSphereValid) {
Vector3 newPoint3D;
bool isNewPointOK = mapMouseCoordinatesToSphere(xMouse, yMouse, newPoint3D);
if (isNewPointOK) {
Vector3 axis = mLastPointOnSphere.cross(newPoint3D);
float cosAngle = mLastPointOnSphere.dot(newPoint3D);
float epsilon = std::numeric_limits<float>::epsilon();
if (fabs(cosAngle) < 1.0f && axis.length() > epsilon) {
axis.normalize();
float angle = 2.0f * acos(cosAngle);
// Rotate the camera around the center of the scene
mCamera.rotateAroundLocalPoint(axis, -angle, mCenterScene);
}
}
}
}
// Check the OpenGL errors
void GlutViewer::checkOpenGLErrors() {
GLenum glError;
// Get the OpenGL errors
glError = glGetError();
// While there are errors
while (glError != GL_NO_ERROR) {
// Get the error string
const GLubyte* stringError = gluErrorString(glError);
// Display the error
if (stringError)
cerr << "OpenGL Error #" << glError << "(" << gluErrorString(glError) << endl;
else
cerr << "OpenGL Error #" << glError << " (no message available)" << endl;
// Get the next error
glError = glGetError();
}
}

View File

@ -0,0 +1,160 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef GLUT_VIEWER_H
#define GLUT_VIEWER_H
// Libraries
#include "Shader.h"
#include "Camera.h"
#include "maths/Vector2.h"
#include <string>
#include <GL/glew.h>
#include "GL/freeglut.h"
namespace openglframework {
// Class Renderer
class GlutViewer {
private:
// -------------------- Attributes -------------------- //
// Camera
Camera mCamera;
// Center of the scene
Vector3 mCenterScene;
// Last mouse coordinates on the windows
int mLastMouseX, mLastMouseY;
// Last point computed on a sphere (for camera rotation)
Vector3 mLastPointOnSphere;
// True if the last point computed on a sphere (for camera rotation) is valid
bool mIsLastPointOnSphereValid;
// State of the mouse buttons
bool mIsButtonDown[10];
// GLUT keyboard modifiers
int mModifiers;
// -------------------- Methods -------------------- //
// Initialize the GLUT library
bool initGLUT(int argc, char** argv, const std::string& windowsTitle,
const Vector2& windowsSize, const Vector2& windowsPosition,
bool isMultisamplingActive);
bool mapMouseCoordinatesToSphere(int xMouse, int yMouse, Vector3& spherePoint) const;
public:
// -------------------- Methods -------------------- //
// Constructor
GlutViewer();
// Destructor
~GlutViewer();
// Initialize the viewer
bool init(int argc, char** argv, const std::string& windowsTitle,
const Vector2& windowsSize, const Vector2& windowsPosition,
bool isMultisamplingActive = false);
// Called when the windows is reshaped
void reshape(int width, int height);
// Set the scene position (where the camera needs to look at)
void setScenePosition(const Vector3& position, float sceneRadius);
// Set the camera so that we can view the whole scene
void resetCameraToViewAll();
// Enable/Disable the multi-sampling for anti-aliasing
void activateMultiSampling(bool isActive) const;
// Zoom the camera
void zoom(int xMouse, int yMouse);
// Translate the camera
void translate(int xMouse, int yMouse);
// Rotate the camera
void rotate(int xMouse, int yMouse);
// Get the camera
Camera& getCamera();
void motion(int x, int y);
// Called when a GLUT mouse button event occurs
void mouseButtonEvent(int button, int state, int x, int y);
// Called when a GLUT mouse motion event occurs
void mouseMotionEvent(int xMouse, int yMouse);
void keyboard(int key, int x, int y);
void special(int key, int x, int y);
// Check the OpenGL errors
static void checkOpenGLErrors();
};
// Set the dimension of the camera viewport
inline void GlutViewer::reshape(int width, int height) {
mCamera.setDimensions(width, height);
glViewport(0, 0, width, height);
glutPostRedisplay();
}
// Set the scene position (where the camera needs to look at)
inline void GlutViewer::setScenePosition(const Vector3& position, float sceneRadius) {
// Set the position and radius of the scene
mCenterScene = position;
mCamera.setSceneRadius(sceneRadius);
// Reset the camera position and zoom in order to view all the scene
resetCameraToViewAll();
}
// Get the camera
inline Camera& GlutViewer::getCamera() {
return mCamera;
}
// Enable/Disable the multi-sampling for anti-aliasing
inline void GlutViewer::activateMultiSampling(bool isActive) const {
(isActive) ? glEnable(GL_MULTISAMPLE) : glDisable(GL_MULTISAMPLE);
}
}
#endif

View File

@ -0,0 +1,100 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "Light.h"
// Namespaces
using namespace openglframework;
// Constructor
Light::Light(GLuint id)
: mLightID(id), mDiffuseColor(Color::white()),
mSpecularColor(Color::white()), mIsActive(false) {
}
// Constructor
Light::Light(GLuint id, Color diffuseColor, Color specularColor)
: mLightID(id), mDiffuseColor(diffuseColor),
mSpecularColor(specularColor), mIsActive(false) {
}
// Destructor
Light::~Light() {
}
// Initialize the light
void Light::init() {
// Enable the light
enable();
// Set the diffuse and specular color
GLfloat diffuseColor[] = {mDiffuseColor.r, mDiffuseColor.g, mDiffuseColor.b, mDiffuseColor.a};
GLfloat specularColor[] = {mSpecularColor.r,mSpecularColor.g,mSpecularColor.b,mSpecularColor.a};
glLightfv(mLightID, GL_DIFFUSE, diffuseColor);
glLightfv(mLightID, GL_SPECULAR, specularColor);
}
// Create a shadow map associated with this light
bool Light::createShadowMap(uint width, uint height) {
// Destroy the current shadow map
destroyShadowMap();
// Create the Framebuffer object to render the shadow map
bool isFBOCreated = mFBOShadowMap.create(width, height, false);
if (!isFBOCreated) {
std::cerr << "Error : Cannot create the Shadow Map !" << std::endl;
destroyShadowMap();
return false;
}
// Bind the Framebuffer object
mFBOShadowMap.bind(GL_NONE);
// Create the shadow map depth texture
mShadowMap.create(width, height, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE);
// Attache the shadow map texture to the Framebuffer object
mFBOShadowMap.attachTexture(GL_DEPTH_ATTACHMENT_EXT, mShadowMap.getID());
// Unbind the Framebuffer object
mFBOShadowMap.unbind();
// TODO : Change the path of the shader here so that it does not depend on the build folder
bool isShaderCreated = mDepthShader.create("../../opengl-framework/src/shaders/depth.vert",
"../../opengl-framework/src/shaders/depth.vert");
if (!isShaderCreated) {
std::cerr << "Error : Cannot create the Shadow Map !" << std::endl;
destroyShadowMap();
return false;
}
return true;
}

View File

@ -0,0 +1,181 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef LIGHT_H
#define LIGHT_H
// Libraries
#include "maths/Color.h"
#include "maths/Vector3.h"
#include "Object3D.h"
#include "Texture2D.h"
#include "FrameBufferObject.h"
#include "Shader.h"
#include <GL/glew.h>
namespace openglframework {
// Class Light
class Light : public Object3D {
private:
// -------------------- Attributes -------------------- //
// OpenGL light ID
GLuint mLightID;
// Diffuse color of the light
Color mDiffuseColor;
// Specular color of the light
Color mSpecularColor;
// True if the light is active
bool mIsActive;
// Shadow map associated with this light
Texture2D mShadowMap;
// Framebuffer object to render the shadow map
FrameBufferObject mFBOShadowMap;
// Shader to render the depth of the scene into a texture
Shader mDepthShader;
public:
// -------------------- Methods -------------------- //
// Constructor
Light(GLuint id);
// Constructor
Light(GLuint id, Color diffuseColor, Color specularColor);
// Destructor
virtual ~Light();
// Return the diffuse color
Color getDiffuseColor() const;
// Set the diffuse color
void setDiffuseColor(const Color& color);
// Return the specular color
Color getSpecularColor() const;
// Set the specular color
void setSpecularColor(const Color& color);
// Return true if the light is active
bool getIsActive() const;
// Initialize the light
void init();
// Enable the light
void enable();
// Disable the light
void disable();
// Create a shadow map associated with this light
bool createShadowMap(uint width, uint height);
// Call this method before rendering the scene for the shadow map computation
void startRenderingShadowMap();
// Call this method after having rendered the scene for the shadow map computation
void stopRenderingShadowMap();
// Destroy the shadow map associated with this light
void destroyShadowMap();
};
// Return the diffuse color
inline Color Light::getDiffuseColor() const {
return mDiffuseColor;
}
// Set the diffuse color
inline void Light::setDiffuseColor(const Color& color) {
mDiffuseColor = color;
}
// Return the specular color
inline Color Light::getSpecularColor() const {
return mSpecularColor;
}
// Set the specular color
inline void Light::setSpecularColor(const Color& color) {
mSpecularColor = color;
}
// Return true if the light is active
inline bool Light::getIsActive() const {
return mIsActive;
}
// Enable the light
inline void Light::enable() {
mIsActive = true;
// Enable the light
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0 + mLightID);
}
// Disable the light
inline void Light::disable() {
mIsActive = false;
// Disable the light
glDisable(GL_LIGHT0 + mLightID);
}
// Destroy the shadow map associated with this light
inline void Light::destroyShadowMap() {
mShadowMap.destroy();
mFBOShadowMap.destroy();
mDepthShader.destroy();
}
// Call this method before rendering the scene for the shadow map computation
inline void Light::startRenderingShadowMap() {
assert(mShadowMap.getID());
}
// Call this method after having rendered the scene for the shadow map computation
inline void Light::stopRenderingShadowMap() {
assert(mShadowMap.getID());
}
}
#endif

View File

@ -0,0 +1,177 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "Mesh.h"
// Namespaces
using namespace openglframework;
using namespace std;
// Constructor
Mesh::Mesh() {
}
// Destructor
Mesh::~Mesh() {
}
// Destroy the mesh
void Mesh::destroy() {
mVertices.clear();
mNormals.clear();
mTangents.clear();
mIndices.clear();
mColors.clear();
mUVs.clear();
mTextures.clear();
}
// Compute the normals of the mesh
void Mesh::calculateNormals() {
mNormals = vector<Vector3>(getNbVertices(), Vector3(0, 0, 0));
// For each triangular face
for (uint i=0; i<getNbFaces(); i++) {
// Get the three vertices index of the current face
uint v1 = getVertexIndexInFace(i, 0);
uint v2 = getVertexIndexInFace(i, 1);
uint v3 = getVertexIndexInFace(i, 2);
assert(v1 < getNbVertices());
assert(v2 < getNbVertices());
assert(v3 < getNbVertices());
// Compute the normal of the face
Vector3 p = getVertex(v1);
Vector3 q = getVertex(v2);
Vector3 r = getVertex(v3);
Vector3 normal = (q-p).cross(r-p).normalize();
// Add the face surface normal to the sum of normals at
// each vertex of the face
mNormals[v1] += normal;
mNormals[v2] += normal;
mNormals[v3] += normal;
}
// Normalize the normal at each vertex
for (uint i=0; i<getNbVertices(); i++) {
assert(mNormals[i].length() > 0);
mNormals[i] = mNormals[i].normalize();
}
}
// Compute the tangents of the mesh
void Mesh::calculateTangents() {
mTangents = std::vector<Vector3>(getNbVertices(), Vector3(0, 0, 0));
// For each face
for (uint i=0; i<getNbFaces(); i++) {
// Get the three vertices index of the face
uint v1 = getVertexIndexInFace(i, 0);
uint v2 = getVertexIndexInFace(i, 1);
uint v3 = getVertexIndexInFace(i, 2);
assert(v1 < getNbVertices());
assert(v2 < getNbVertices());
assert(v3 < getNbVertices());
// Get the vertices positions
Vector3 p = getVertex(v1);
Vector3 q = getVertex(v2);
Vector3 r = getVertex(v3);
// Get the texture coordinates of each vertex
Vector2 uvP = getUV(v1);
Vector2 uvQ = getUV(v2);
Vector2 uvR = getUV(v3);
// Get the three edges
Vector3 edge1 = q - p;
Vector3 edge2 = r - p;
Vector2 edge1UV = uvQ - uvP;
Vector2 edge2UV = uvR - uvP;
float cp = edge1UV.y * edge2UV.x - edge1UV.x * edge2UV.y;
// Compute the tangent
if (cp != 0.0f) {
float factor = 1.0f / cp;
Vector3 tangent = (edge1 * -edge2UV.y + edge2 * edge1UV.y) * factor;
tangent.normalize();
mTangents[v1] = tangent;
mTangents[v2] = tangent;
mTangents[v3] = tangent;
}
}
}
// Calculate the bounding box of the mesh
void Mesh::calculateBoundingBox(Vector3& min, Vector3& max) const {
// If the mesh contains vertices
if (!mVertices.empty()) {
min = mVertices[0];
max = mVertices[0];
std::vector<Vector3>::const_iterator it(mVertices.begin());
// For each vertex of the mesh
for (; it != mVertices.end(); ++it) {
if( (*it).x < min.x ) min.x = (*it).x;
else if ( (*it).x > max.x ) max.x = (*it).x;
if( (*it).y < min.y ) min.y = (*it).y;
else if ( (*it).y > max.y ) max.y = (*it).y;
if( (*it).z < min.z ) min.z = (*it).z;
else if ( (*it).z > max.z ) max.z = (*it).z;
}
}
else {
std::cerr << "Error : Impossible to calculate the bounding box of the mesh because there" <<
"are no vertices !" << std::endl;
assert(false);
}
}
// Scale of vertices of the mesh using a given factor
void Mesh::scaleVertices(float factor) {
// For each vertex
for (uint i=0; i<getNbVertices(); i++) {
mVertices.at(i) *= factor;
}
}

View File

@ -0,0 +1,411 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef MESH_H
#define MESH_H
// Libraries
#include <string>
#include <vector>
#include <map>
#include "definitions.h"
#include "maths/Vector2.h"
#include "maths/Vector3.h"
#include "maths/Color.h"
#include "Texture2D.h"
#include "Object3D.h"
namespace openglframework {
// Class Mesh
// This class represents a 3D triangular mesh
// object that can be loaded from an OBJ file for instance.
class Mesh : public Object3D {
private:
// -------------------- Attributes -------------------- //
// A triplet of vertex indices for each triangle
std::vector<std::vector<uint> > mIndices;
// Vertices coordinates (local space)
std::vector<Vector3> mVertices;
// Normals coordinates
std::vector<Vector3> mNormals;
// Tangents coordinates
std::vector<Vector3> mTangents;
// Color for each vertex
std::vector<Color> mColors;
// UV texture coordinates
std::vector<Vector2> mUVs;
// Textures of the mesh (one for each part of the mesh)
std::map<uint, Texture2D> mTextures;
public:
// -------------------- Methods -------------------- //
// Constructor
Mesh();
// Destructor
virtual ~Mesh();
// Destroy the mesh
void destroy();
// Compute the normals of the mesh
void calculateNormals();
// Compute the tangents of the mesh
void calculateTangents();
// Calculate the bounding box of the mesh
void calculateBoundingBox(Vector3& min, Vector3& max) const;
// Scale of vertices of the mesh using a given factor
void scaleVertices(float factor);
// Return the number of triangles
uint getNbFaces(uint part = 0) const;
// Return the number of vertices
uint getNbVertices() const;
// Return the number of parts in the mesh
uint getNbParts() const;
// Return a reference to the vertices
const std::vector<Vector3>& getVertices() const;
// Set the vertices of the mesh
void setVertices(std::vector<Vector3>& vertices);
// Return a reference to the normals
const std::vector<Vector3>& getNormals() const;
// set the normals of the mesh
void setNormals(std::vector<Vector3>& normals);
// Return a reference to the UVs
const std::vector<Vector2>& getUVs() const;
// Set the UV texture coordinates of the mesh
void setUVs(std::vector<Vector2>& uvs);
// Return a reference to the vertex indices
const std::vector<uint>& getIndices(uint part = 0) const;
// Set the vertices indices of the mesh
void setIndices(std::vector<std::vector<uint> >& indices);
// Return the coordinates of a given vertex
const Vector3& getVertex(uint i) const;
// Set the coordinates of a given vertex
void setVertex(uint i, const Vector3& vertex);
// Return the coordinates of a given normal
const Vector3& getNormal(uint i) const;
// Set the coordinates of a given normal
void setNormal(uint i, const Vector3& normal);
// Return the color of a given vertex
const Color& getColor(uint i) const;
// Set the color of a given vertex
void setColor(uint i, const Color& color);
// Set a color to all the vertices
void setColorToAllVertices(const Color& color);
// Return the UV of a given vertex
const Vector2& getUV(uint i) const;
// Set the UV of a given vertex
void setUV(uint i, const Vector2& uv);
// Return the vertex index of the ith (i=0,1,2) vertex of a given face
uint getVertexIndexInFace(uint faceIndex, uint i, uint part = 0) const;
// Return true if the mesh has normals
bool hasNormals() const;
// Return true if the mesh has tangents
bool hasTangents() const;
// Return true if the mesh has vertex colors
bool hasColors() const;
// Return true if the mesh has UV texture coordinates
bool hasUVTextureCoordinates() const;
// Return true if the mesh has a texture for a given part of the mesh and if it
// also have texture coordinates
bool hasTextureForPart(uint part = 0) const;
// Return true if the mesh has a texture (and texture coordinates) for at least one
// part of the mesh
bool hasTexture() const;
// Return a pointer to the vertices data
void* getVerticesPointer();
// Return a pointer to the normals data
void* getNormalsPointer();
// Return a pointer to the colors data
void* getColorsPointer();
// Return a pointer to the tangents data
void* getTangentsPointer();
// Return a pointer to the UV texture coordinates data
void* getUVTextureCoordinatesPointer();
// Return a pointer to the vertex indicies data
void* getIndicesPointer(uint part = 0);
// Return a reference to a texture of the mesh
Texture2D &getTexture(uint part = 0);
// Set a texture to a part of the mesh
void setTexture(Texture2D &texture, uint part = 0);
};
// Return the number of triangles
inline uint Mesh::getNbFaces(uint part) const {
return mIndices[part].size() / 3;
}
// Return the number of vertices
inline uint Mesh::getNbVertices() const {
return mVertices.size();
}
// Return the number of parts in the mesh
inline uint Mesh::getNbParts() const {
return mIndices.size();
}
// Return a reference to the vertices
inline const std::vector<Vector3>& Mesh::getVertices() const {
return mVertices;
}
// Set the vertices of the mesh
inline void Mesh::setVertices(std::vector<Vector3>& vertices) {
mVertices = vertices;
}
// Return a reference to the normals
inline const std::vector<Vector3>& Mesh::getNormals() const {
return mNormals;
}
// set the normals of the mesh
inline void Mesh::setNormals(std::vector<Vector3>& normals) {
mNormals = normals;
}
// Return a reference to the UVs
inline const std::vector<Vector2>& Mesh::getUVs() const {
return mUVs;
}
// Set the UV texture coordinates of the mesh
inline void Mesh::setUVs(std::vector<Vector2>& uvs) {
mUVs = uvs;
}
// Return a reference to the vertex indices
inline const std::vector<uint>& Mesh::getIndices(uint part) const {
return mIndices[part];
}
// Set the vertices indices of the mesh
inline void Mesh::setIndices(std::vector<std::vector<uint> >& indices) {
mIndices = indices;
}
// Return the coordinates of a given vertex
inline const Vector3& Mesh::getVertex(uint i) const {
assert(i < getNbVertices());
return mVertices[i];
}
// Set the coordinates of a given vertex
inline void Mesh::setVertex(uint i, const Vector3& vertex) {
assert(i < getNbVertices());
mVertices[i] = vertex;
}
// Return the coordinates of a given normal
inline const Vector3& Mesh::getNormal(uint i) const {
assert(i < getNbVertices());
return mNormals[i];
}
// Set the coordinates of a given normal
inline void Mesh::setNormal(uint i, const Vector3& normal) {
assert(i < getNbVertices());
mNormals[i] = normal;
}
// Return the color of a given vertex
inline const Color& Mesh::getColor(uint i) const {
assert(i < getNbVertices());
return mColors[i];
}
// Set the color of a given vertex
inline void Mesh::setColor(uint i, const Color& color) {
// If the color array does not have the same size as
// the vertices array
if (mColors.size() != mVertices.size()) {
// Create the color array with the same size
mColors = std::vector<Color>(mVertices.size());
}
mColors[i] = color;
}
// Set a color to all the vertices
inline void Mesh::setColorToAllVertices(const Color& color) {
// If the color array does not have the same size as
// the vertices array
if (mColors.size() != mVertices.size()) {
// Create the color array with the same size
mColors = std::vector<Color>(mVertices.size());
}
for (size_t v=0; v<mVertices.size(); v++) {
mColors[v] = color;
}
}
// Return the UV of a given vertex
inline const Vector2& Mesh::getUV(uint i) const {
assert(i < getNbVertices());
return mUVs[i];
}
// Set the UV of a given vertex
inline void Mesh::setUV(uint i, const Vector2& uv) {
assert(i < getNbVertices());
mUVs[i] = uv;
}
// Return the vertex index of the ith (i=0,1,2) vertex of a given face
inline uint Mesh::getVertexIndexInFace(uint faceIndex, uint i, uint part) const {
return (mIndices[part])[faceIndex*3 + i];
}
// Return true if the mesh has normals
inline bool Mesh::hasNormals() const {
return mNormals.size() == mVertices.size();
}
// Return true if the mesh has tangents
inline bool Mesh::hasTangents() const {
return mTangents.size() == mVertices.size();
}
// Return true if the mesh has vertex colors
inline bool Mesh::hasColors() const {
return mColors.size() == mVertices.size();
}
// Return true if the mesh has UV texture coordinates
inline bool Mesh::hasUVTextureCoordinates() const {
return mUVs.size() == mVertices.size();
}
// Return true if the mesh has a texture for a given part of the mesh and if it
// also have texture coordinates
inline bool Mesh::hasTextureForPart(uint part) const {
return hasUVTextureCoordinates() && mTextures.count(part);
}
// Return true if the mesh has a texture (and texture coordinates) for at least one
// part of the mesh
inline bool Mesh::hasTexture() const {
return hasUVTextureCoordinates() && (mTextures.size() > 0);
}
// Return a pointer to the vertices data
inline void* Mesh::getVerticesPointer() {
return &(mVertices[0]);
}
// Return a pointer to the normals data
inline void* Mesh::getNormalsPointer() {
return &(mNormals[0]);
}
// Return a pointer to the colors data
inline void* Mesh::getColorsPointer() {
return &(mColors[0]);
}
// Return a pointer to the tangents data
inline void* Mesh::getTangentsPointer() {
return &(mTangents[0]);
}
// Return a pointer to the UV texture coordinates data
inline void* Mesh::getUVTextureCoordinatesPointer() {
return &(mUVs[0]);
}
// Return a pointer to the vertex indicies data
inline void* Mesh::getIndicesPointer(uint part) {
return &(mIndices[part])[0];
}
// Return a reference to a texture of the mesh
inline Texture2D& Mesh::getTexture(uint part) {
return mTextures[part];
}
// Set a texture to a part of the mesh
inline void Mesh::setTexture(Texture2D& texture, uint part) {
mTextures[part] = texture;
}
}
#endif

View File

@ -0,0 +1,397 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "MeshReaderWriter.h"
#include <fstream>
#include <sstream>
#include <locale>
#include <cctype>
#include <map>
#include <algorithm>
using namespace openglframework;
using namespace std;
// Constructor
MeshReaderWriter::MeshReaderWriter() {
}
// Load a mesh from a file and returns true if the mesh has been sucessfully loaded
void MeshReaderWriter::loadMeshFromFile(const std::string& filename,
Mesh& meshToCreate)
throw(std::invalid_argument, std::runtime_error) {
// Get the extension of the file
uint startPosExtension = filename.find_last_of(".");
string extension = filename.substr(startPosExtension+1);
// Load the file using the correct method
if (extension == "obj") {
loadOBJFile(filename, meshToCreate);
}
else {
// Display an error message and throw an exception
string errorMessage("Error : the MeshReaderWriter class cannot load a file with the extension .");
errorMessage += extension;
std::cerr << errorMessage << std::endl;
throw std::invalid_argument(errorMessage.c_str());
}
}
// Write a mesh to a file
void MeshReaderWriter::writeMeshToFile(const std::string& filename,
const Mesh& meshToWrite)
throw(std::invalid_argument, std::runtime_error) {
// Get the extension of the file
uint startPosExtension = filename.find_last_of(".");
string extension = filename.substr(startPosExtension+1);
// Load the file using the correct method
if (extension == "obj") {
writeOBJFile(filename, meshToWrite);
}
else {
// Display an error message and throw an exception
string errorMessage("Error : the MeshReaderWriter class cannot store a mesh file with the extension .");
errorMessage += extension;
std::cerr << errorMessage << std::endl;
throw std::invalid_argument(errorMessage.c_str());
}
}
// Load an OBJ file with a triangular or quad mesh
void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
// Open the file
std::ifstream meshFile(filename.c_str());
// If we cannot open the file
if(!meshFile.is_open()) {
// Throw an exception and display an error message
string errorMessage("Error : Cannot open the file " + filename);
std::cerr << errorMessage << std::endl;
throw runtime_error(errorMessage);
}
std::string buffer;
string line, tmp;
int id1, id2, id3, id4;
int nId1, nId2, nId3, nId4;
int tId1, tId2, tId3, tId4;
float v1, v2, v3;
size_t found1, found2;
std::vector<bool> isQuad;
std::vector<Vector3> vertices;
std::vector<Vector3> normals;
std::vector<Vector2> uvs;
std::vector<uint> verticesIndices;
std::vector<uint> normalsIndices;
std::vector<uint> uvsIndices;
// ---------- Collect the data from the file ---------- //
// For each line of the file
while(std::getline(meshFile, buffer)) {
std::istringstream lineStream(buffer);
std::string word;
lineStream >> word;
std::transform(word.begin(), word.end(), word.begin(), ::tolower);
if(word == "usemtl") { // Material definition
// Loading of MTL file is not implemented
}
else if(word == "v") { // Vertex position
sscanf(buffer.c_str(), "%*s %f %f %f", &v1, &v2, &v3);
vertices.push_back(Vector3(v1, v2, v3));
}
else if(word == "vt") { // Vertex texture coordinate
sscanf(buffer.c_str(), "%*s %f %f", &v1, &v2);
uvs.push_back(Vector2(v1,v2));
}
else if(word == "vn") { // Vertex normal
sscanf(buffer.c_str(), "%*s %f %f %f", &v1, &v2, &v3);
normals.push_back(Vector3(v1 ,v2, v3));
}
else if (word == "f") { // Face
line = buffer;
found1 = (int)line.find("/");
bool isFaceQuad = false;
int foundNext = (int)line.substr(found1+1).find("/");
// If the face definition is of the form "f v1 v2 v3 v4"
if(found1 == string::npos) {
int nbVertices = sscanf(buffer.c_str(), "%*s %d %d %d %d", &id1, &id2, &id3, &id4);
if (nbVertices == 4) isFaceQuad = true;
}
// If the face definition is of the form "f v1// v2// v3// v4//"
else if (foundNext == 0) {
int nbVertices = sscanf(buffer.c_str(), "%*s %d// %d// %d// %d//", &id1, &id2, &id3, &id4);
if (nbVertices == 4) isFaceQuad = true;
}
else { // If the face definition contains vertices and texture coordinates
//get the part of the string until the second index
tmp = line.substr(found1+1);
found2 = (int)tmp.find(" ");
tmp = tmp.substr(0,found2);
found2 = (int)tmp.find("/");
// If the face definition is of the form "f vert1/textcoord1 vert2/textcoord2 ..."
if(found2 == string::npos) {
int n = sscanf(buffer.c_str(), "%*s %d/%d %d/%d %d/%d %d/%d", &id1, &tId1, &id2, &tId2, &id3, &tId3, &id4, &tId4);
if (n == 8) isFaceQuad = true;
uvsIndices.push_back(tId1-1);
uvsIndices.push_back(tId2-1);
uvsIndices.push_back(tId3-1);
if (isFaceQuad) uvsIndices.push_back(tId4-1);
}
else {
tmp = line.substr(found1+1);
found2 = (int)tmp.find("/");
// If the face definition is of the form "f vert1/normal1 vert2/normal2 ..."
if(found2 == 0) {
int n = sscanf(buffer.c_str(), "%*s %d//%d %d//%d %d//%d %d//%d", &id1, &nId1, &id2, &nId2, &id3, &nId3, &id4, &nId4);
if (n == 8) isFaceQuad = true;
}
// If the face definition is of the form "f vert1/textcoord1/normal1 ..."
else {
int n = sscanf(buffer.c_str(), "%*s %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d", &id1, &tId1, &nId1, &id2, &tId2, &nId2, &id3, &tId3, &nId3, &id4, &tId4, &nId4);
if (n == 12) isFaceQuad = true;
uvsIndices.push_back(tId1-1);
uvsIndices.push_back(tId2-1);
uvsIndices.push_back(tId3-1);
if (isFaceQuad) uvsIndices.push_back(tId4-1);
}
normalsIndices.push_back(nId1-1);
normalsIndices.push_back(nId2-1);
normalsIndices.push_back(nId3-1);
if (isFaceQuad) normalsIndices.push_back(nId4-1);
}
}
verticesIndices.push_back(id1-1);
verticesIndices.push_back(id2-1);
verticesIndices.push_back(id3-1);
if (isFaceQuad) verticesIndices.push_back((id4-1));
isQuad.push_back(isFaceQuad);
}
}
assert(!verticesIndices.empty());
assert(normalsIndices.empty() || normalsIndices.size() == verticesIndices.size());
assert(uvsIndices.empty() || uvsIndices.size() == verticesIndices.size());
meshFile.close();
// ---------- Merge the data that we have collected from the file ---------- //
// Destroy the current mesh
meshToCreate.destroy();
// Mesh data
vector<std::vector<uint> > meshIndices;
vector<Vector3> meshNormals;
if (!normals.empty()) meshNormals = vector<Vector3>(vertices.size(), Vector3(0, 0, 0));
vector<Vector2> meshUVs;
if (!uvs.empty()) meshUVs = vector<Vector2>(vertices.size(), Vector2(0, 0));
// We cannot load mesh with several parts for the moment
uint meshPart = 0;
// Fill in the vertex indices
// We also triangulate each quad face
meshIndices.push_back(std::vector<uint>());
for(size_t i = 0, j = 0; i < verticesIndices.size(); j++) {
// Get the current vertex IDs
uint i1 = verticesIndices[i];
uint i2 = verticesIndices[i+1];
uint i3 = verticesIndices[i+2];
// Add the vertex normal
if (!normalsIndices.empty() && !normals.empty()) {
meshNormals[i1] = normals[normalsIndices[i]];
meshNormals[i2] = normals[normalsIndices[i+1]];
meshNormals[i3] = normals[normalsIndices[i+2]];
}
// Add the vertex UV texture coordinates
if (!uvsIndices.empty() && !uvs.empty()) {
meshUVs[i1] = uvs[uvsIndices[i]];
meshUVs[i2] = uvs[uvsIndices[i+1]];
meshUVs[i3] = uvs[uvsIndices[i+2]];
}
// If the current vertex not in a quad (it is part of a triangle)
if (!isQuad[j]) {
// Add the vertex indices
meshIndices[meshPart].push_back(i1);
meshIndices[meshPart].push_back(i2);
meshIndices[meshPart].push_back(i3);
i+=3;
}
else { // If the current vertex is in a quad
Vector3 v1 = vertices[i1];
Vector3 v2 = vertices[i2];
Vector3 v3 = vertices[i3];
uint i4 = verticesIndices[i+3];
Vector3 v4 = vertices[i4];
Vector3 v13 = v3-v1;
Vector3 v12 = v2-v1;
Vector3 v14 = v4-v1;
float a1 = v13.dot(v12);
float a2 = v13.dot(v14);
if((a1 >= 0 && a2 <= 0) || (a1 <= 0 && a2 >= 0)) {
meshIndices[meshPart].push_back(i1);
meshIndices[meshPart].push_back(i2);
meshIndices[meshPart].push_back(i3);
meshIndices[meshPart].push_back(i1);
meshIndices[meshPart].push_back(i3);
meshIndices[meshPart].push_back(i4);
}
else {
meshIndices[meshPart].push_back(i1);
meshIndices[meshPart].push_back(i2);
meshIndices[meshPart].push_back(i4);
meshIndices[meshPart].push_back(i2);
meshIndices[meshPart].push_back(i3);
meshIndices[meshPart].push_back(i4);
}
// Add the vertex normal
if (!normalsIndices.empty() && !normals.empty()) {
meshNormals[i4] = normals[normalsIndices[i]];
}
// Add the vertex UV texture coordinates
if (!uvsIndices.empty() && !uvs.empty()) {
meshUVs[i4] = uvs[uvsIndices[i]];
}
i+=4;
}
}
assert(meshNormals.empty() || meshNormals.size() == vertices.size());
assert(meshUVs.empty() || meshUVs.size() == vertices.size());
// Set the data to the mesh
meshToCreate.setIndices(meshIndices);
meshToCreate.setVertices(vertices);
meshToCreate.setNormals(meshNormals);
meshToCreate.setUVs(meshUVs);
}
// Store a mesh into a OBJ file
void MeshReaderWriter::writeOBJFile(const std::string& filename, const Mesh& meshToWrite) {
std::ofstream file(filename.c_str());
// Geth the mesh data
const std::vector<Vector3>& vertices = meshToWrite.getVertices();
const std::vector<Vector3>& normals = meshToWrite.getNormals();
const std::vector<Vector2>& uvs = meshToWrite.getUVs();
// If we can open the file
if (file.is_open()) {
assert(meshToWrite.getNbVertices() == vertices.size());
// Write the vertices
for (uint v=0; v<vertices.size(); v++) {
file << "v " << vertices[v].x << " " << vertices[v].y << " " << vertices[v].z <<
std::endl;
}
// Write the normals
if (meshToWrite.hasNormals()) {
file << std::endl;
assert(meshToWrite.getNbVertices() == normals.size());
for (uint v=0; v<normals.size(); v++) {
file << "vn " << normals[v].x << " " << normals[v].y << " " << normals[v].z <<
std::endl;
}
}
// Write the UVs texture coordinates
if (meshToWrite.hasUVTextureCoordinates()) {
file << std::endl;
assert(meshToWrite.getNbVertices() == uvs.size());
for (uint v=0; v<uvs.size(); v++) {
file << "vt " << uvs[v].x << " " << uvs[v].y << std::endl;
}
}
// Write the faces
file << std::endl;
for (uint p=0; p<meshToWrite.getNbParts(); p++) {
// Get the indices of the part
const std::vector<uint>& indices = meshToWrite.getIndices(p);
// For each index of the part
for (uint i=0; i<indices.size(); i+=3) {
if (meshToWrite.hasNormals() && meshToWrite.hasUVTextureCoordinates()) {
file << "f " <<indices[i]+1 << "/" << indices[i]+1 << "/" << indices[i]+1 <<
" " << indices[i+1]+1 << "/" << indices[i+1]+1 << "/" << indices[i+1]+1 <<
" " << indices[i+2]+1 << "/" << indices[i+2]+1 << "/" << indices[i+2]+1 <<
std::endl;
}
else if (meshToWrite.hasNormals() || meshToWrite.hasUVTextureCoordinates()) {
file << "f " <<indices[i]+1 << "/" << indices[i]+1 <<
" " << indices[i+1]+1 << "/" << indices[i+1]+1 <<
" " << indices[i+2]+1 << "/" << indices[i+2]+1 << std::endl;
}
else {
file << "f " << indices[i]+1 << " " << indices[i+1]+1 << " " << indices[i+2]+1 <<
std::endl;
}
}
}
}
else {
std::cerr << "Error : Cannot open the file " << filename << std::endl;
exit(1);
}
}

View File

@ -0,0 +1,100 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef MESH_LOADER_H
#define MESH_LOADER_H
// Libraries
#include <string>
#include <stdexcept>
#include "Mesh.h"
namespace openglframework {
// Class MeshReaderWriter
// This class is used to read or write any mesh file in order to
// create the corresponding Mesh object. Currently, this class
// is able to read meshes of the current formats : .obj
class MeshReaderWriter {
private :
// -------------------- Methods -------------------- //
// Constructor (private because we do not want instances of this class)
MeshReaderWriter();
// Load an OBJ file with a triangular or quad mesh
static void loadOBJFile(const std::string& filename, Mesh& meshToCreate);
// Store a mesh into a OBJ file
static void writeOBJFile(const std::string& filename, const Mesh &meshToWrite);
public :
// -------------------- Methods -------------------- //
// Read a mesh from a file
static void loadMeshFromFile(const std::string& filename,
Mesh& meshToCreate)
throw(std::invalid_argument, std::runtime_error);
// Write a mesh to a file
static void writeMeshToFile(const std::string& filename,
const Mesh& meshToWrite)
throw(std::invalid_argument, std::runtime_error);
};
// Class VertexMergingData
// This class is used in the method to read a mesh
class VertexMergingData {
public:
VertexMergingData() : indexPosition(0), indexNormal(0), indexUV(0) {}
unsigned int indexPosition;
unsigned int indexNormal;
unsigned int indexUV;
};
// Class VertexMergingDataComparison
// This class is used in the method to read a mesh
class VertexMergingDataComparison {
public:
bool operator()(const VertexMergingData& x, const VertexMergingData& y) const {
if(x.indexPosition < y.indexPosition)
return true;
if(x.indexPosition == y.indexPosition && x.indexNormal < y.indexNormal)
return true;
if(x.indexPosition == y.indexPosition && x.indexNormal ==
y.indexNormal && x.indexUV < y.indexUV)
return true;
return false;
}
};
}
#endif

View File

@ -0,0 +1,41 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "Object3D.h"
// Namespaces
using namespace openglframework;
// Constructor
Object3D::Object3D() {
// Set the transformation matrix to the identity
setToIdentity();
}
// Destructor
Object3D::~Object3D() {
}

View File

@ -0,0 +1,149 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef OBJECT3D_H
#define OBJECT3D_H
// Libraries
#include "maths/Vector3.h"
#include "maths/Matrix4.h"
namespace openglframework {
// Class Object3D
// This class represent a generic 3D object on the scene.
class Object3D {
protected:
// -------------------- Attributes -------------------- //
// Transformation matrix that convert local-space
// coordinates to world-space coordinates
Matrix4 mTransformMatrix;
public:
// -------------------- Methods -------------------- //
// Constructor
Object3D();
// Destructor
virtual ~Object3D();
// Return the transform matrix
const Matrix4& getTransformMatrix() const;
// Set the transform matrix
void setTransformMatrix(const Matrix4& matrix);
// Set to the identity transform
void setToIdentity();
// Return the origin of object in world-space
Vector3 getOrigin() const;
// Translate the object in world-space
void translateWorld(const Vector3& v);
// Translate the object in local-space
void translateLocal(const Vector3& v);
// Rotate the object in world-space
void rotateWorld(const Vector3& axis, float angle);
// Rotate the object in local-space
void rotateLocal(const Vector3& axis, float angle);
// Rotate around a world-space point
void rotateAroundWorldPoint(const Vector3& axis, float angle, const Vector3& point);
// Rotate around a local-space point
void rotateAroundLocalPoint(const Vector3& axis, float angle, const Vector3& worldPoint);
};
// Return the transform matrix
inline const Matrix4& Object3D::getTransformMatrix() const {
return mTransformMatrix;
}
// Set the transform matrix
inline void Object3D::setTransformMatrix(const Matrix4& matrix) {
mTransformMatrix = matrix;
}
// Set to the identity transform
inline void Object3D::setToIdentity() {
mTransformMatrix.setToIdentity();
}
// Return the origin of object in world-space
inline Vector3 Object3D::getOrigin() const {
return mTransformMatrix * Vector3(0.0, 0.0, 0.0);
}
// Translate the object in world-space
inline void Object3D::translateWorld(const Vector3& v) {
mTransformMatrix = Matrix4::translationMatrix(v) * mTransformMatrix;
}
// Translate the object in local-space
inline void Object3D::translateLocal(const Vector3& v) {
mTransformMatrix = mTransformMatrix * Matrix4::translationMatrix(v);
}
// Rotate the object in world-space
inline void Object3D::rotateWorld(const Vector3& axis, float angle) {
mTransformMatrix = Matrix4::rotationMatrix(axis, angle) * mTransformMatrix;
}
// Rotate the object in local-space
inline void Object3D::rotateLocal(const Vector3& axis, float angle) {
mTransformMatrix = mTransformMatrix * Matrix4::rotationMatrix(axis, angle);
}
// Rotate the object around a world-space point
inline void Object3D::rotateAroundWorldPoint(const Vector3& axis, float angle,
const Vector3& worldPoint) {
mTransformMatrix = Matrix4::translationMatrix(worldPoint) * Matrix4::rotationMatrix(axis, angle)
* Matrix4::translationMatrix(-worldPoint) * mTransformMatrix;
}
// Rotate the object around a local-space point
inline void Object3D::rotateAroundLocalPoint(const Vector3& axis, float angle,
const Vector3& worldPoint) {
// Convert the world point into the local coordinate system
Vector3 localPoint = mTransformMatrix.getInverse() * worldPoint;
mTransformMatrix = mTransformMatrix * Matrix4::translationMatrix(localPoint)
* Matrix4::rotationMatrix(axis, angle)
* Matrix4::translationMatrix(-localPoint);
}
}
#endif

View File

@ -0,0 +1,207 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "Shader.h"
#include <cassert>
#include <fstream>
#include <iostream>
// Namespaces
using namespace openglframework;
using namespace std;
// Constructor
Shader::Shader() : mProgramObjectID(0) {
}
// Constructor with arguments
Shader::Shader(const std::string vertexShaderFilename, const std::string fragmentShaderFilename)
: mProgramObjectID(0) {
// Create the shader
create(vertexShaderFilename, fragmentShaderFilename);
}
// Destructor
Shader::~Shader() {
}
// Create the shader
bool Shader::create(const std::string vertexShaderFilename,
const std::string fragmentShaderFilename) {
// Set the shader filenames
mFilenameVertexShader = vertexShaderFilename;
mFilenameFragmentShader = fragmentShaderFilename;
// Check that the needed OpenGL extensions are available
bool isExtensionOK = checkOpenGLExtensions();
if (!isExtensionOK) {
cerr << "Error : Impossible to use GLSL vertex or fragment shaders on this platform" << endl;
assert(false);
return false;
}
// Delete the current shader
destroy();
assert(!vertexShaderFilename.empty() && !fragmentShaderFilename.empty());
// ------------------- Load the vertex shader ------------------- //
GLuint vertexShaderID;
std::ifstream fileVertexShader;
fileVertexShader.open(vertexShaderFilename.c_str(), std::ios::binary);
if (fileVertexShader.is_open()) {
// Get the size of the file
fileVertexShader.seekg(0, std::ios::end);
uint fileSize = (uint) (fileVertexShader.tellg());
assert(fileSize != 0);
// Read the file
fileVertexShader.seekg(std::ios::beg);
char* bufferVertexShader = new char[fileSize + 1];
fileVertexShader.read(bufferVertexShader, fileSize);
fileVertexShader.close();
bufferVertexShader[fileSize] = '\0';
// Create the OpenGL vertex shader and compile it
vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
assert(vertexShaderID != 0);
glShaderSource(vertexShaderID, 1, (const char **) (&bufferVertexShader), NULL);
glCompileShader(vertexShaderID);
delete[] bufferVertexShader;
// Get the compilation information
int compiled;
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &compiled);
// If the compilation failed
if (compiled == 0) {
// Get the log of the compilation
int lengthLog;
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &lengthLog);
char* str = new char[lengthLog];
glGetShaderInfoLog(vertexShaderID, lengthLog, NULL, str);
// Display the log of the compilation
std::cerr << "Vertex Shader Error : " << str << std::endl;
delete[] str;
assert(false);
return false;
}
}
else {
std::cerr << "Error : Impossible to open the vertex shader file " <<
vertexShaderFilename << std::endl;
assert(false);
return false;
}
// ------------------- Load the fragment shader ------------------- //
GLuint fragmentShaderID;
std::ifstream fileFragmentShader;
fileFragmentShader.open(fragmentShaderFilename.c_str(), std::ios::binary);
assert(fileFragmentShader.is_open());
if (fileFragmentShader.is_open()) {
// Get the size of the file
fileFragmentShader.seekg(0, std::ios::end);
uint fileSize = (uint) (fileFragmentShader.tellg());
assert(fileSize != 0);
// Read the file
fileFragmentShader.seekg(std::ios::beg);
char* bufferFragmentShader = new char[fileSize + 1];
fileFragmentShader.read(bufferFragmentShader, fileSize);
fileFragmentShader.close();
bufferFragmentShader[fileSize] = '\0';
// Create the OpenGL fragment shader and compile it
fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
assert(fragmentShaderID != 0);
glShaderSource(fragmentShaderID, 1, (const char **) (&bufferFragmentShader), NULL);
glCompileShader(fragmentShaderID);
delete[] bufferFragmentShader;
// Get the compilation information
int compiled;
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &compiled);
// If the compilation failed
if (compiled == 0) {
// Get the log of the compilation
int lengthLog;
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &lengthLog);
char* str = new char[lengthLog];
glGetShaderInfoLog(fragmentShaderID, lengthLog, NULL, str);
// Display the log of the compilation
std::cerr << "Fragment Shader Error : " << str << std::endl;
delete[] str;
assert(false);
return false;
}
}
else {
std::cerr << "Error : Impossible to open the fragment shader file " <<
fragmentShaderFilename << std::endl;
assert(false);
return false;
}
// Create the shader program and attach the shaders
mProgramObjectID = glCreateProgram();
assert(mProgramObjectID);
glAttachShader(mProgramObjectID, vertexShaderID);
glAttachShader(mProgramObjectID, fragmentShaderID);
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
// Try to link the program
glLinkProgram(mProgramObjectID);
int linked;
glGetProgramiv(mProgramObjectID, GL_LINK_STATUS, &linked);
if (!linked) {
int logLength;
glGetProgramiv(mProgramObjectID, GL_INFO_LOG_LENGTH, &logLength);
char* strLog = new char[logLength];
glGetProgramInfoLog(mProgramObjectID, logLength, NULL, strLog);
cerr << "Linker Error in vertex shader " << vertexShaderFilename <<
" or in fragment shader " << fragmentShaderFilename << " : " << strLog << endl;
delete[] strLog;
destroy();
assert(false);
}
return true;
}

View File

@ -0,0 +1,243 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef SHADER_H
#define SHADER_H
// Libraries
#include "definitions.h"
#include "maths/Matrix4.h"
#include "maths/Vector2.h"
#include "maths/Vector3.h"
#include "maths/Vector4.h"
#include <string>
#include <iostream>
#include <GL/glew.h>
namespace openglframework {
// Class Shader
class Shader {
private :
// -------------------- Attributes -------------------- //
// Shader object program ID
GLuint mProgramObjectID;
// Filenames of the vertex and fragment shaders
std::string mFilenameVertexShader, mFilenameFragmentShader;
public :
// -------------------- Methods -------------------- //
// Constructor
Shader();
// Constructor with arguments
Shader(const std::string vertexShaderFilename, const std::string fragmentShaderFilename);
// Destructor
~Shader();
// Create the shader
bool create(const std::string vertexShaderFilename,
const std::string fragmentShaderFilename);
// Clear the shader
void destroy();
// Bind the shader
void bind() const;
// Unbind the shader
void unbind() const;
// Return the location of a uniform variable inside a shader program
int getUniformLocation(const std::string& variableName) const;
// Set a float uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setFloatUniform(const std::string& variableName, float value) const;
// Set an int uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setIntUniform(const std::string& variableName, int value) const;
// Set a vector 2 uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setVector2Uniform(const std::string& variableName, const Vector2& v) const;
// Set a vector 3 uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setVector3Uniform(const std::string& variableName, const Vector3& v) const;
// Set a vector 4 uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setVector4Uniform(const std::string& variableName, const Vector4 &v) const;
// Set a 3x3 matrix uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setMatrix3x3Uniform(const std::string& variableName, const float* matrix,
bool transpose = false) const;
// Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setMatrix4x4Uniform(const std::string& variableName, const float* matrix,
bool transpose = false) const;
// Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setMatrix4x4Uniform(const std::string& variableName, const Matrix4& matrix) const;
// Return true if the needed OpenGL extensions are available
static bool checkOpenGLExtensions();
};
// Bind the shader
inline void Shader::bind() const {
assert(mProgramObjectID != 0);
glUseProgram(mProgramObjectID);
}
// Unbind the shader
inline void Shader::unbind() const {
assert(mProgramObjectID != 0);
glUseProgram(0);
}
// Return the location of a uniform variable inside a shader program
inline int Shader::getUniformLocation(const std::string& variableName) const {
assert(mProgramObjectID != 0);
int location = glGetUniformLocation(mProgramObjectID, variableName.c_str());
if (location == -1) {
std::cerr << "Error in vertex shader " << mFilenameVertexShader << " or in fragment shader"
<< mFilenameFragmentShader << " : No Uniform variable : " << variableName
<< std::endl;
}
assert(location != -1);
return location;
}
// Clear the shader
inline void Shader::destroy() {
if (mProgramObjectID != 0) {
glDeleteShader(mProgramObjectID);
mProgramObjectID = 0;
}
}
// Set a float uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setFloatUniform(const std::string& variableName, float value) const {
assert(mProgramObjectID != 0);
glUniform1f(getUniformLocation(variableName), value);
}
// Set an int uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setIntUniform(const std::string& variableName, int value) const {
assert(mProgramObjectID != 0);
glUniform1i(getUniformLocation(variableName), value);
}
// Set a vector 2 uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setVector2Uniform(const std::string& variableName, const Vector2& v) const {
assert(mProgramObjectID != 0);
glUniform2f(getUniformLocation(variableName), v.x, v.y);
}
// Set a vector 3 uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setVector3Uniform(const std::string& variableName, const Vector3 &v) const {
assert(mProgramObjectID != 0);
glUniform3f(getUniformLocation(variableName), v.x, v.y, v.z);
}
// Set a vector 4 uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setVector4Uniform(const std::string& variableName, const Vector4& v) const {
assert(mProgramObjectID != 0);
glUniform4f(getUniformLocation(variableName), v.x, v.y, v.z, v.w);
}
// Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setMatrix3x3Uniform(const std::string& variableName, const float* matrix,
bool transpose) const {
assert(mProgramObjectID != 0);
glUniformMatrix3fv(getUniformLocation(variableName), 1, transpose, matrix);
}
// Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setMatrix4x4Uniform(const std::string& variableName, const float* matrix,
bool transpose) const {
assert(mProgramObjectID != 0);
glUniformMatrix4fv(getUniformLocation(variableName), 1, transpose, matrix);
}
// Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setMatrix4x4Uniform(const std::string& variableName, const Matrix4& matrix) const {
assert(mProgramObjectID != 0);
GLfloat mat[16];
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++) {
mat[i*4 + j] = matrix.m[i][j];
}
}
glUniformMatrix4fv(getUniformLocation(variableName), 1, true, mat);
}
// Return true if the needed OpenGL extensions are available for shaders
inline bool Shader::checkOpenGLExtensions() {
// Check that GLSL vertex and fragment shaders are available on the platform
return (GLEW_VERSION_2_0 || (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader));
}
}
#endif

View File

@ -0,0 +1,84 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "Texture2D.h"
#include <fstream>
#include <iostream>
#include <string>
// Namespaces
using namespace openglframework;
// Constructor
Texture2D::Texture2D() : mID(0), mLayer(0), mWidth(0), mHeight(0) {
}
// Constructor
Texture2D::Texture2D(uint width, uint height, uint internalFormat, uint format, uint type)
: mID(0), mLayer(0), mWidth(0), mHeight(0){
// Create the texture
create(width, height, internalFormat, format, type);
}
// Destructor
Texture2D::~Texture2D() {
}
// Create the texture
void Texture2D::create(uint width, uint height, uint internalFormat, uint format, uint type,
void* data) throw(std::invalid_argument) {
// Destroy the current texture
destroy();
mWidth = width;
mHeight = height;
// Create the OpenGL texture
glGenTextures(1, &mID);
assert(mID != 0);
glBindTexture(GL_TEXTURE_2D, mID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0, format, type, data);
glBindTexture(GL_TEXTURE_2D, 0);
}
// Destroy the texture
void Texture2D::destroy() {
if (mID != 0) {
glDeleteTextures(1, &mID);
mID = 0;
mLayer = 0;
mWidth = 0;
mHeight = 0;
}
}

View File

@ -0,0 +1,142 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef TEXTURE2D_H
#define TEXTURE2D_H
// Libraries
#include <string>
#include <cassert>
#include "definitions.h"
#include <GL/glew.h>
namespace openglframework {
// Class Texture2D
// This class represents a 2D texture
class Texture2D {
private:
// -------------------- Attributes -------------------- //
// OpenGL texture ID
GLuint mID;
// Layer of the texture
GLuint mLayer;
// Width
uint mWidth;
// Height
uint mHeight;
public:
// -------------------- Methods -------------------- //
// Constructor
Texture2D();
// Constructor
Texture2D(uint width, uint height, uint internalFormat, uint format, uint type);
// Destructor
~Texture2D();
// Create the texture
void create(uint width, uint height, uint internalFormat, uint format, uint type,
void* data = NULL) throw(std::invalid_argument);
// Destroy the texture
void destroy();
// Bind the texture
void bind() const;
// Unbind the texture
void unbind() const;
// Get the OpenGL texture ID
uint getID() const;
// Get the layer of the texture
uint getLayer() const;
// Set the layer of the texture
void setLayer(uint layer);
// Get the width
uint getWidth() const;
// Get the height
uint getHeight() const;
};
// Bind the texture
inline void Texture2D::bind() const {
assert(mID != 0);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0 + mLayer);
glBindTexture(GL_TEXTURE_2D, mID);
}
// Unbind the texture
inline void Texture2D::unbind() const {
assert(mID != 0);
glActiveTexture(GL_TEXTURE0 + mLayer);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
// Get the OpenGL texture ID
inline uint Texture2D::getID() const {
return mID;
}
// Get the layer of the texture
inline uint Texture2D::getLayer() const {
return mLayer;
}
// Set the layer of the texture
inline void Texture2D::setLayer(uint layer) {
mLayer = layer;
}
// Get the width
inline uint Texture2D::getWidth() const {
return mWidth;
}
// Get the height
inline uint Texture2D::getHeight() const {
return mHeight;
}
}
#endif

View File

@ -0,0 +1,329 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Librairies
#include "TextureReaderWriter.h"
#include <string>
#include <jpeglib.h>
#include <jerror.h>
using namespace openglframework;
using namespace std;
// Constants
const uint TextureReaderWriter::JPEG_COMPRESSION_QUALITY = 98;
// TGA file Header
#pragma pack(push, 1)
typedef struct {
unsigned char identsize; // size of ID field that follows 18 byte header (0 usually)
unsigned char colourmaptype; // type of colour map 0=none, 1=has palette
unsigned char imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
short colourmapstart; // first colour map entry in palette
short colourmaplength; // number of colours in palette
unsigned char colourmapbits; // number of bits per palette entry 15,16,24,32
short xstart; // image x origin
short ystart; // image y origin
short width; // image width in pixels
short height; // image height in pixels
unsigned char bits; // image bits per pixel 8,16,24,32
unsigned char descriptor; // image descriptor bits (vh flip bits)
// pixel data follows header
} TGA_HEADER;
#pragma pack(pop)
// Load a texture from a file
void TextureReaderWriter::loadTextureFromFile(const std::string& filename,
Texture2D& textureToCreate)
throw(runtime_error, invalid_argument){
// Get the extension of the file
uint startPosExtension = filename.find_last_of(".");
string extension = filename.substr(startPosExtension+1);
// Load the file using the correct method
if (extension == "tga") {
readTGAPicture(filename, textureToCreate);
}
else if (extension == "jpg" || extension == "jpeg"){
readJPEGPicture(filename, textureToCreate);
}
else {
// Display an error message and throw an exception
string errorMessage("Error : the TextureLoader class cannot load a file with the extension .");
errorMessage += extension;
std::cerr << errorMessage << std::endl;
throw std::invalid_argument(errorMessage.c_str());
}
}
// Write a texture to a file
void TextureReaderWriter::writeTextureToFile(const std::string& filename,
const Texture2D& texture)
throw(runtime_error, invalid_argument){
// Get the extension of the file
uint startPosExtension = filename.find_last_of(".");
string extension = filename.substr(startPosExtension+1);
// Write the file using the correct method
if (extension == "tga") {
writeTGAPicture(filename, texture);
}
else if (extension == "jpg" || extension == "jpeg"){
writeJPEGPicture(filename, texture);
}
else {
// Display an error message and throw an exception
string errorMessage("Error : the TextureReaderWriter class cannot write a file with the extension .");
errorMessage += extension;
std::cerr << errorMessage << std::endl;
throw std::invalid_argument(errorMessage.c_str());
}
}
// Load a TGA picture
void TextureReaderWriter::readTGAPicture(const std::string &filename,
Texture2D& textureToCreate) throw(runtime_error) {
// Open the file
std::ifstream stream(filename.c_str(), std::ios::binary);
// If we cannot open the file
if(!stream.is_open()) {
// Throw an exception and display an error message
string errorMessage("Error : Cannot open the file " + filename);
std::cerr << errorMessage << std::endl;
throw std::runtime_error(errorMessage);
}
TGA_HEADER header;
stream.read((char *)(&header), sizeof(TGA_HEADER));
assert(header.width <= 4096 && header.width <= 4096 &&
header.imagetype == 2 && header.bits == 24);
// Read the file
uint width = header.width;
uint height = header.width;
uint sizeImg = width*height;
char* data = new char[sizeImg*3];
assert(data);
stream.read(data, sizeImg*3);
for(uint i = 0; i < sizeImg; i++) {
unsigned pos = i*3;
unsigned char red = data[pos];
data[pos] = data[pos + 2];
data[pos + 2] = red;
}
// Close the stream
stream.close();
// Create the OpenGL texture using the picture data from the file
textureToCreate.create(width, height, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, data);
// Free the data memory
delete[] data;
}
// Write a TGA picture
void TextureReaderWriter::writeTGAPicture(const std::string& filename,
const Texture2D& texture) throw(runtime_error) {
assert(texture.getID() != 0);
// Bind the corresponding texture
glBindTexture(GL_TEXTURE_2D, texture.getID());
uint sizeImg = texture.getWidth() * texture.getHeight();
// Get the bytes form the OpenGL texture
char* data = new char[sizeImg * 3];
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
// Open the file
std::ofstream stream(filename.c_str(), std::ios::binary);
// If the file cannot be opened
if(!stream.is_open()) {
// Throw an exception and display an error message
string errorMessage("Error : Cannot create/access the file " + filename);
std::cerr << errorMessage << std::endl;
delete[] data;
throw std::runtime_error(errorMessage);
}
// Fill in the TGA header
TGA_HEADER header;
header.identsize = 0; // size of ID field that follows 18 byte header (0 usually)
header.colourmaptype = 0; // type of colour map 0=none, 1=has palette
header.imagetype = 2; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
header.colourmapstart = 0; // first colour map entry in palette
header.colourmaplength = 0; // number of colours in palette
header.colourmapbits=0; // number of bits per palette entry 15,16,24,32
header.xstart = 0; // image x origin
header.ystart = 0; // image y origin
header.width = (short)texture.getWidth(); // image width in pixels
header.height = (short)texture.getHeight(); // image height in pixels
header.bits = 24; // image bits per pixel 8,16,24,32
header.descriptor = 0; // image descriptor bits (vh flip bits)
// Write the header to the file
stream.write((char*)(&header), sizeof(TGA_HEADER));
// Write the bytes to the file
for(uint i = 0; i < sizeImg; i++) {
unsigned pos = i*3;
unsigned char red = data[pos];
data[pos] = data[pos + 2];
data[pos + 2] = red;
}
stream.write(data, sizeImg*3);
// Close the file
stream.close();
// Delete the data
delete[] data;
// Unbind the corresponding texture
glBindTexture(GL_TEXTURE_2D, 0);
}
// Read a JPEG picture
void TextureReaderWriter::readJPEGPicture(const std::string& filename,
Texture2D& textureToCreate) throw(std::runtime_error) {
struct jpeg_decompress_struct info;
struct jpeg_error_mgr error;
info.err = jpeg_std_error(&error);
jpeg_create_decompress(&info);
// Open the file
FILE* file = fopen(filename.c_str(), "rb");
// If we cannot open the file
if (!file) {
// Throw an exception and display an error message
string errorMessage("Error : Cannot open the file " + filename);
std::cerr << errorMessage << std::endl;
throw std::runtime_error(errorMessage);
}
jpeg_stdio_src(&info, file);
jpeg_read_header(&info, true);
jpeg_start_decompress(&info);
unsigned long x = info.output_width;
unsigned long y = info.output_height;
int channels = info.num_components;
assert(channels == 3);
unsigned long size = x * y * 3;
BYTE* data = new BYTE[size];
BYTE* p1 = data;
BYTE** p2 = &p1;
int numlines = 0;
while(info.output_scanline < info.output_height) {
numlines = jpeg_read_scanlines(&info, p2, 1);
*p2 += numlines * 3 * info.output_width;
}
jpeg_finish_decompress(&info); //finish decompressing this file
// Close the file
fclose(file);
// Create the OpenGL texture
textureToCreate.create(x, y, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, data);
// Free allocated memory
delete[] data;
}
// Write a JPEG picture
void TextureReaderWriter::writeJPEGPicture(const std::string& filename,
const Texture2D& texture) throw(std::runtime_error) {
struct jpeg_compress_struct info;
struct jpeg_error_mgr error;
info.err = jpeg_std_error(&error);
jpeg_create_compress(&info);
// Open the file
FILE* file = fopen(filename.c_str(), "wb");
if (!file) {
// Throw an exception and display an error message
string errorMessage("Error : Cannot write JPEG picture into the file " + filename);
std::cerr << errorMessage << std::endl;
throw std::runtime_error(errorMessage);
}
// Get the bytes form the OpenGL texture
char* data = new char[texture.getWidth() * texture.getHeight() * 3];
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
jpeg_stdio_dest(&info, file);
info.image_width = texture.getWidth();
info.image_height = texture.getHeight();
info.input_components = 3;
info.in_color_space = JCS_RGB;
jpeg_set_defaults(&info);
jpeg_set_quality(&info, JPEG_COMPRESSION_QUALITY, true);
jpeg_start_compress(&info, true);
// Write the data into the file
JSAMPROW rowPointer;
int rowStride = texture.getWidth() * 3;
while (info.next_scanline < info.image_height) {
rowPointer = (JSAMPROW) &data[info.next_scanline * rowStride];
jpeg_write_scanlines(&info, &rowPointer, 1);
}
jpeg_finish_compress(&info);
jpeg_destroy_compress(&info);
// Close the file
fclose(file);
// Free allocated memory
delete[] data;
}

View File

@ -0,0 +1,87 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef TEXTURE_READER_WRITER_H
#define TEXTURE_READER_WRITER_H
// Libraries
#include "Texture2D.h"
#include <fstream>
#include <iostream>
#include <stdexcept>
namespace openglframework {
// Class TextureReaderWriter
// This class is used to load or write a texture image in different picture format.
// It currently allows to read and write the following formats : .tga
class TextureReaderWriter {
private :
// ------------------- Constants ------------------- //
// JPEG quality for compression (in percent)
static const uint JPEG_COMPRESSION_QUALITY;
// -------------------- Methods -------------------- //
// Constructor (private because we do not want instances of this class)
TextureReaderWriter();
// Read a TGA picture
static void readTGAPicture(const std::string& filename,
Texture2D& textureToCreate) throw(std::runtime_error);
// Write a TGA picture
static void writeTGAPicture(const std::string& filename,
const Texture2D& texture) throw(std::runtime_error);
// Read a JPEG picture
static void readJPEGPicture(const std::string& filename,
Texture2D& textureToCreate) throw(std::runtime_error);
// Write a JPEG picture
static void writeJPEGPicture(const std::string& filename,
const Texture2D& texture) throw(std::runtime_error);
public :
// -------------------- Methods -------------------- //
// Load a texture from a file
static void loadTextureFromFile(const std::string& filename,
Texture2D& textureToCreate)
throw(std::runtime_error, std::invalid_argument);
// Write a texture to a file
static void writeTextureToFile(const std::string& filename,
const Texture2D& texture)
throw(std::runtime_error, std::invalid_argument);
};
}
#endif

View File

@ -0,0 +1,84 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "VertexBufferObject.h"
using namespace openglframework;
// Constructor
VertexBufferObject::VertexBufferObject(GLenum targetData)
: mVertexBufferID(0), mTargetData(targetData) {
}
// Destructor
VertexBufferObject::~VertexBufferObject() {
}
// Create the vertex buffer object
bool VertexBufferObject::create() {
// Destroy the current VBO
destroy();
// Check that the needed OpenGL extensions are available
bool isExtensionOK = checkOpenGLExtensions();
if (!isExtensionOK) {
std::cerr << "Error : Impossible to use Vertex Buffer Object on this platform" << std::endl;
assert(false);
return false;
}
// Generate a new VBO
glGenBuffers(1, &mVertexBufferID);
assert(mVertexBufferID != 0);
return true;
}
// Copy data into the VBO
void VertexBufferObject::copyDataIntoVBO(GLsizei size, const void* data, GLenum usage) {
// Bind the VBO
bind();
// Copy the data into the VBO
glBufferData(mTargetData, size, data, usage);
// Unbind the VBO
unbind();
}
// Destroy the VBO
void VertexBufferObject::destroy() {
// Delete the vertex buffer object
if (mVertexBufferID) {
glDeleteFramebuffers(1, &mVertexBufferID);
mVertexBufferID = 0;
}
}

View File

@ -0,0 +1,106 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef VERTEX_BUFFER_OBJECT_H
#define VERTEX_BUFFER_OBJECT_H
// Libraries
#include <GL/glew.h>
#include <cassert>
#include <iostream>
namespace openglframework {
// Class VertexBufferObject
class VertexBufferObject {
private :
// -------------------- Attributes -------------------- //
/// ID of the Vertex Buffer Object
GLuint mVertexBufferID;
/// Target data. This variable must be GL_ARRAY_BUFFER if the VBO contains vertex
/// data (vertex coordinates, texture coordinates, normals, colors) or must be
/// GL_ELEMENT_ARRAY_BUFFER if the VBO contains index data (index array).
GLenum mTargetData;
public :
// -------------------- Methods -------------------- //
/// Constructor
VertexBufferObject(GLenum targetData);
/// Destructor
~VertexBufferObject();
/// Create the vertex buffer object
bool create();
/// Copy data into the VBO
void copyDataIntoVBO(GLsizei size, const void* data, GLenum usage);
/// Bind the VBO
void bind() const;
/// Unbind the VBO
void unbind() const;
/// Return true if the needed OpenGL extensions are available for VBO
static bool checkOpenGLExtensions();
/// Destroy the VBO
void destroy();
};
// Bind the VBO
inline void VertexBufferObject::bind() const {
assert(mVertexBufferID != 0);
// Bind the VBO
glBindBuffer(mTargetData, mVertexBufferID);
}
// Unbind the VBO
inline void VertexBufferObject::unbind() const {
assert(mVertexBufferID != 0);
// Unbind the VBO
glBindBuffer(mTargetData, 0);
}
// Return true if the needed OpenGL extensions are available for VBO
inline bool VertexBufferObject::checkOpenGLExtensions() {
// Check that OpenGL version is at least 1.5 or there the vertex buffer object extension exists
return (GLEW_VERSION_1_5 || GL_ARB_vertex_buffer_object);
}
}
#endif

View File

@ -0,0 +1,39 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef DEFINITIONS_H
#define DEFINITIONS_H
namespace openglframework {
// ------------------- Type definitions ------------------- //
typedef unsigned int uint;
// ------------------- Constants ------------------- //
const float PI = 3.141592654f;
}
#endif

View File

@ -0,0 +1,76 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef COLOR_H
#define COLOR_H
namespace openglframework {
// Structure Color
// This structure represents a RGBA color.
struct Color {
public:
// -------------------- Attributes -------------------- //
// RGBA color components
float r, g, b, a;
// -------------------- Methods -------------------- //
// Constructor
Color() : r(1), g(1), b(1), a(1) {}
// Constructor
Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) {}
// Constructor
Color(const Color& color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
// Destructor
~Color() {}
// Return the black color
static Color black() { return Color(0.0f, 0.0f, 0.0f, 1.0f);}
// Return the white color
static Color white() { return Color(1.0f, 1.0f, 1.0f, 1.0f);}
// = operator
Color& operator=(const Color& color) {
if (&color != this) {
r = color.r;
g = color.g;
b = color.b;
a = color.a;
}
return *this;
}
};
}
#endif

View File

@ -0,0 +1,279 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef MATRIX3_H
#define MATRIX3_H
// Libraries
#include <cassert>
#include <limits>
#include "Vector3.h"
namespace openglframework {
// Class Matrix4
// This class represents a 4x4 matrix
class Matrix3 {
private :
// -------------------- Attributes -------------------- //
// Elements of the matrix
float m[3][3];
public :
// Constructor
Matrix3() {
setToNull();
}
// Constructor
Matrix3(float a1, float a2,
float a3, float b1, float b2, float b3,
float c1, float c2, float c3) {
setAllValues(a1, a2, a3, b1, b2, b3, c1, c2, c3);
}
// Constructor
Matrix3(float n[3][3]) {
m[0][0]=n[0][0]; m[0][1]=n[0][1]; m[0][2]=n[0][2];
m[1][0]=n[1][0]; m[1][1]=n[1][1]; m[1][2]=n[1][2];
m[2][0]=n[2][0]; m[2][1]=n[2][1]; m[2][2]=n[2][2];
}
// Constructor
Matrix3(const Vector3& a1, const Vector3& a2, const Vector3& a3) {
m[0][0] = a1.x; m[0][1] = a2.x; m[0][2] = a3.x;
m[1][0] = a1.y; m[1][1] = a2.y; m[1][2] = a3.y;
m[2][0] = a1.z; m[2][1] = a2.z; m[2][2] = a3.z;
}
// Constructor
Matrix3(const Matrix3& matrix) {
setAllValues(matrix.m[0][0], matrix.m[0][1], matrix.m[0][2],
matrix.m[1][0], matrix.m[1][1], matrix.m[1][2],
matrix.m[2][0], matrix.m[2][1], matrix.m[2][2]);
}
// Method to get a value in the matrix
float getValue(int i, int j) const {
assert(i>=0 && i<3 && j>=0 && j<3);
return m[i][j];
}
// Method to set a value in the matrix
void setValue(int i, int j, float value) {
assert(i>=0 && i<3 && j>=0 && j<3);
m[i][j] = value;
}
// Method to set all the values in the matrix
void setAllValues(float a1, float a2, float a3, float b1, float b2, float b3,
float c1, float c2, float c3) {
m[0][0] = a1; m[0][1] = a2; m[0][2] = a3;
m[1][0] = b1; m[1][1] = b2; m[1][2] = b3;
m[2][0] = c1; m[2][1] = c2; m[2][2] = c3;
}
// Return a column
Vector3 getColumn(int i) const {
assert(i>= 0 && i<3);
return Vector3(m[0][i], m[1][i], m[2][i]);
}
// Return the transpose matrix
Matrix3 getTranspose() const {
// Return the transpose matrix
return Matrix3(m[0][0], m[1][0], m[2][0],
m[0][1], m[1][1], m[2][1],
m[0][2], m[1][2], m[2][2]);
}
// Return the determinant of the matrix
float getDeterminant() const {
// Compute and return the determinant of the matrix
return (m[0][0]*(m[1][1]*m[2][2]-m[2][1]*m[1][2]) - m[0][1]*(m[1][0]*m[2][2]-m[2][0]*m[1][2]) +
m[0][2]*(m[1][0]*m[2][1]-m[2][0]*m[1][1]));
}
// Return the trace of the matrix
float getTrace() const {
// Compute and return the trace
return (m[0][0] + m[1][1] + m[2][2]);
}
void setToNull() {
m[0][0] = 0.0; m[0][1] = 0.0; m[0][2] = 0.0;
m[1][0] = 0.0; m[1][1] = 0.0; m[1][2] = 0.0;
m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 0.0;
}
bool isNull() const {
Matrix3 zero;
return *this == zero;
}
// Set the matrix to the identity matrix
void setToIdentity() {
m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0;
m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0;
m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0;
}
bool isIdentity() const {
Matrix3 I;
I.setToIdentity();
return ( *this == I );
}
// Return the inverse matrix
Matrix3 getInverse() const {
// Compute the determinant of the matrix
float determinant = getDeterminant();
// Check if the determinant is equal to zero
assert(determinant > std::numeric_limits<float>::epsilon());
float invDeterminant = 1.0f / determinant;
Matrix3 tempMatrix((m[1][1]*m[2][2]-m[2][1]*m[1][2]), -(m[0][1]*m[2][2]-m[2][1]*m[0][2]), (m[0][1]*m[1][2]-m[0][2]*m[1][1]),
-(m[1][0]*m[2][2]-m[2][0]*m[1][2]), (m[0][0]*m[2][2]-m[2][0]*m[0][2]), -(m[0][0]*m[1][2]-m[1][0]*m[0][2]),
(m[1][0]*m[2][1]-m[2][0]*m[1][1]), -(m[0][0]*m[2][1]-m[2][0]*m[0][1]), (m[0][0]*m[1][1]-m[0][1]*m[1][0]));
// Return the inverse matrix
return (tempMatrix * invDeterminant);
}
// Display the matrix
void print() const {
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) {
std::cout << m[i][j] << " ";
}
std::cout << std::endl;
}
}
// Overloaded operator =
Matrix3& operator=(const Matrix3& matrix) {
if (&matrix != this) {
setAllValues(matrix.m[0][0], matrix.m[0][1], matrix.m[0][2],
matrix.m[1][0], matrix.m[1][1], matrix.m[1][2],
matrix.m[2][0], matrix.m[2][1], matrix.m[2][2]);
}
return *this;
}
// Overloaded operator for addition
Matrix3 operator+(const Matrix3& matrix2) {
return Matrix3(m[0][0] + matrix2.m[0][0], m[0][1] + matrix2.m[0][1], m[0][2] + matrix2.m[0][2],
m[1][0] + matrix2.m[1][0], m[1][1] + matrix2.m[1][1], m[1][2] + matrix2.m[1][2],
m[2][0] + matrix2.m[2][0], m[2][1] + matrix2.m[2][1], m[2][2] + matrix2.m[2][2]);
}
// Overloaded operator for substraction
Matrix3 operator-(const Matrix3& matrix2) {
return Matrix3(m[0][0] - matrix2.m[0][0], m[0][1] - matrix2.m[0][1], m[0][2] - matrix2.m[0][2],
m[1][0] - matrix2.m[1][0], m[1][1] - matrix2.m[1][1], m[1][2] - matrix2.m[1][2],
m[2][0] - matrix2.m[2][0], m[2][1] - matrix2.m[2][1], m[2][2] - matrix2.m[2][2]);
}
// Overloaded operator for the negative of the matrix
Matrix3 operator-() {
return Matrix3(-m[0][0], -m[0][1], -m[0][2],
-m[1][0], -m[1][1], -m[1][2],
-m[2][0], -m[2][1], -m[2][2]);
}
// Overloaded operator for multiplication with a number
Matrix3 operator*(float nb) {
return Matrix3(m[0][0] * nb, m[0][1] * nb, m[0][2] * nb,
m[1][0] * nb, m[1][1] * nb, m[1][2] * nb,
m[2][0] * nb, m[2][1] * nb, m[2][2] * nb);
}
// Overloaded operator for matrix multiplication
Matrix3 operator*(const Matrix3& matrix2) {
return Matrix3(m[0][0]*matrix2.m[0][0] + m[0][1]*matrix2.m[1][0] + m[0][2]*matrix2.m[2][0],
m[0][0]*matrix2.m[0][1] + m[0][1]*matrix2.m[1][1] + m[0][2]*matrix2.m[2][1],
m[0][0]*matrix2.m[0][2] + m[0][1]*matrix2.m[1][2] + m[0][2]*matrix2.m[2][2],
m[1][0]*matrix2.m[0][0] + m[1][1]*matrix2.m[1][0] + m[1][2]*matrix2.m[2][0],
m[1][0]*matrix2.m[0][1] + m[1][1]*matrix2.m[1][1] + m[1][2]*matrix2.m[2][1],
m[1][0]*matrix2.m[0][2] + m[1][1]*matrix2.m[1][2] + m[1][2]*matrix2.m[2][2],
m[2][0]*matrix2.m[0][0] + m[2][1]*matrix2.m[1][0] + m[2][2]*matrix2.m[2][0],
m[2][0]*matrix2.m[0][1] + m[2][1]*matrix2.m[1][1] + m[2][2]*matrix2.m[2][1],
m[2][0]*matrix2.m[0][2] + m[2][1]*matrix2.m[1][2] + m[2][2]*matrix2.m[2][2]);
}
// Overloaded operator for multiplication with a vector
Vector3 operator*(const Vector3& vector) {
return Vector3(m[0][0]*vector.x + m[0][1]*vector.y + m[0][2]*vector.z,
m[1][0]*vector.x + m[1][1]*vector.y + m[1][2]*vector.z,
m[2][0]*vector.x + m[2][1]*vector.y + m[2][2]*vector.z);
}
// Overloaded operator for equality condition
bool operator==(const Matrix3& matrix) const {
return (m[0][0] == matrix.m[0][0] && m[0][1] == matrix.m[0][1] && m[0][2] == matrix.m[0][2] &&
m[1][0] == matrix.m[1][0] && m[1][1] == matrix.m[1][1] && m[1][2] == matrix.m[1][2] &&
m[2][0] == matrix.m[2][0] && m[2][1] == matrix.m[2][1] && m[2][2] == matrix.m[2][2]);
}
// Overloaded operator for the is different condition
bool operator!= (const Matrix3& matrix) const {
return !(*this == matrix);
}
// Overloaded operator for addition with assignment
Matrix3& operator+=(const Matrix3& matrix) {
m[0][0] += matrix.m[0][0]; m[0][1] += matrix.m[0][1]; m[0][2] += matrix.m[0][2];
m[1][0] += matrix.m[1][0]; m[1][1] += matrix.m[1][1]; m[1][2] += matrix.m[1][2];
m[2][0] += matrix.m[2][0]; m[2][1] += matrix.m[2][1]; m[2][2] += matrix.m[2][2];
return *this;
}
// Overloaded operator for substraction with assignment
Matrix3& operator-=(const Matrix3& matrix) {
m[0][0] -= matrix.m[0][0]; m[0][1] -= matrix.m[0][1]; m[0][2] -= matrix.m[0][2];
m[1][0] -= matrix.m[1][0]; m[1][1] -= matrix.m[1][1]; m[1][2] -= matrix.m[1][2];
m[2][0] -= matrix.m[2][0]; m[2][1] -= matrix.m[2][1]; m[2][2] -= matrix.m[2][2];
return *this;
}
// Overloaded operator for multiplication with a number with assignment
Matrix3& operator*=(float nb) {
m[0][0] *= nb; m[0][1] *= nb; m[0][2] *= nb;
m[1][0] *= nb; m[1][1] *= nb; m[1][2] *= nb;
m[2][0] *= nb; m[2][1] *= nb; m[2][2] *= nb;
return *this;
}
};
}
#endif

View File

@ -0,0 +1,419 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef MATRIX4_H
#define MATRIX4_H
// Libraries
#include <math.h>
#include <assert.h>
#include <iostream>
#include "Vector3.h"
#include "Vector4.h"
namespace openglframework {
// Class Matrix4
// This class represents a 4x4 matrix
class Matrix4 {
public:
// -------------------- Attributes -------------------- //
// Elements of the matrix
float m[4][4];
// -------------------- Methods -------------------- //
// Constructor
Matrix4(float m_00=0, float m_01=0, float m_02=0, float m_03=0,
float m_10=0, float m_11=0, float m_12=0, float m_13=0,
float m_20=0, float m_21=0, float m_22=0, float m_23=0,
float m_30=0, float m_31=0, float m_32=0, float m_33=0) {
m[0][0] = m_00; m[0][1] = m_01; m[0][2] = m_02; m[0][3] = m_03;
m[1][0] = m_10; m[1][1] = m_11; m[1][2] = m_12; m[1][3] = m_13;
m[2][0] = m_20; m[2][1] = m_21; m[2][2] = m_22; m[2][3] = m_23;
m[3][0] = m_30; m[3][1] = m_31; m[3][2] = m_32; m[3][3] = m_33;
}
// Constructor
Matrix4(float n[4][4]) {
m[0][0]=n[0][0]; m[0][1]=n[0][1]; m[0][2]=n[0][2]; m[0][3]=n[0][3];
m[1][0]=n[1][0]; m[1][1]=n[1][1]; m[1][2]=n[1][2]; m[1][3]=n[1][3];
m[2][0]=n[2][0]; m[2][1]=n[2][1]; m[2][2]=n[2][2]; m[2][3]=n[2][3];
m[3][0]=n[3][0]; m[3][1]=n[3][1]; m[3][2]=n[3][2]; m[3][3]=n[3][3];
}
// Constructor
Matrix4(const Vector3& a1, const Vector3& a2, const Vector3& a3) {
m[0][0] = a1.x; m[0][1] = a2.x; m[0][2] = a3.x; m[0][3] = 0.f;
m[1][0] = a1.y; m[1][1] = a2.y; m[1][2] = a3.y; m[1][3] = 0.f;
m[2][0] = a1.z; m[2][1] = a2.z; m[2][2] = a3.z; m[2][3] = 0.f;
m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f;
}
// Constructor
Matrix4(const Vector4& a1, const Vector4& a2, const Vector4& a3) {
m[0][0] = a1.x; m[0][1] = a2.x; m[0][2] = a3.x; m[0][3] = 0.f;
m[1][0] = a1.y; m[1][1] = a2.y; m[1][2] = a3.y; m[1][3] = 0.f;
m[2][0] = a1.z; m[2][1] = a2.z; m[2][2] = a3.z; m[2][3] = 0.f;
m[3][0] = a1.w; m[3][1] = a2.w; m[3][2] = a3.w; m[3][3] = 1.f;
}
// Constructor
Matrix4(const Matrix4& matrix) {
setAllValues(matrix.m[0][0], matrix.m[0][1], matrix.m[0][2], matrix.m[0][3],
matrix.m[1][0], matrix.m[1][1], matrix.m[1][2], matrix.m[1][3],
matrix.m[2][0], matrix.m[2][1], matrix.m[2][2], matrix.m[2][3],
matrix.m[3][0], matrix.m[3][1], matrix.m[3][2], matrix.m[3][3]);
}
// + operator
Matrix4 operator+(const Matrix4 &n) const {
return Matrix4(m[0][0]+n.m[0][0], m[0][1]+n.m[0][1], m[0][2]+n.m[0][2], m[0][3]+n.m[0][3],
m[1][0]+n.m[1][0], m[1][1]+n.m[1][1], m[1][2]+n.m[1][2], m[1][3]+n.m[1][3],
m[2][0]+n.m[2][0], m[2][1]+n.m[2][1], m[2][2]+n.m[2][2], m[2][3]+n.m[2][3],
m[3][0]+n.m[3][0], m[3][1]+n.m[3][1], m[3][2]+n.m[3][2], m[3][3]+n.m[3][3]);
}
// += operator
Matrix4& operator+=(const Matrix4 &n) {
m[0][0]+=n.m[0][0]; m[0][1]+=n.m[0][1]; m[0][2]+=n.m[0][2]; m[0][3]+=n.m[0][3];
m[1][0]+=n.m[1][0]; m[1][1]+=n.m[1][1]; m[1][2]+=n.m[1][2]; m[1][3]+=n.m[1][3];
m[2][0]+=n.m[2][0]; m[2][1]+=n.m[2][1]; m[2][2]+=n.m[2][2]; m[2][3]+=n.m[2][3];
m[3][0]+=n.m[3][0]; m[3][1]+=n.m[3][1]; m[3][2]+=n.m[3][2]; m[3][3]+=n.m[3][3];
return *this;
}
// - operator
Matrix4 operator-(const Matrix4 &n) const {
return Matrix4(m[0][0]-n.m[0][0], m[0][1]-n.m[0][1], m[0][2]-n.m[0][2], m[0][3]-n.m[0][3],
m[1][0]-n.m[1][0], m[1][1]-n.m[1][1], m[1][2]-n.m[1][2], m[1][3]-n.m[1][3],
m[2][0]-n.m[2][0], m[2][1]-n.m[2][1], m[2][2]-n.m[2][2], m[2][3]-n.m[2][3],
m[3][0]-n.m[3][0], m[3][1]-n.m[3][1], m[3][2]-n.m[3][2], m[3][3]-n.m[3][3]);
}
// -= operator
Matrix4& operator-=(const Matrix4 &n) {
m[0][0]-=n.m[0][0]; m[0][1]-=n.m[0][1]; m[0][2]-=n.m[0][2]; m[0][3]-=n.m[0][3];
m[1][0]-=n.m[1][0]; m[1][1]-=n.m[1][1]; m[1][2]-=n.m[1][2]; m[1][3]-=n.m[1][3];
m[2][0]-=n.m[2][0]; m[2][1]-=n.m[2][1]; m[2][2]-=n.m[2][2]; m[2][3]-=n.m[2][3];
m[3][0]-=n.m[3][0]; m[3][1]-=n.m[3][1]; m[3][2]-=n.m[3][2]; m[3][3]-=n.m[3][3];
return *this;
}
// = operator
Matrix4& operator=(const Matrix4& matrix) {
if (&matrix != this) {
setAllValues(matrix.m[0][0], matrix.m[0][1], matrix.m[0][2], matrix.m[0][3],
matrix.m[1][0], matrix.m[1][1], matrix.m[1][2], matrix.m[1][3],
matrix.m[2][0], matrix.m[2][1], matrix.m[2][2], matrix.m[2][3],
matrix.m[3][0], matrix.m[3][1], matrix.m[3][2], matrix.m[3][3]);
}
return *this;
}
// == operator
bool operator==(const Matrix4 &n) const {
return m[0][0]==n.m[0][0] && m[0][1]==n.m[0][1] && m[0][2]==n.m[0][2] && m[0][3]==n.m[0][3] &&
m[1][0]==n.m[1][0] && m[1][1]==n.m[1][1] && m[1][2]==n.m[1][2] && m[1][3]==n.m[1][3] &&
m[2][0]==n.m[2][0] && m[2][1]==n.m[2][1] && m[2][2]==n.m[2][2] && m[2][3]==n.m[2][3] &&
m[3][0]==n.m[3][0] && m[3][1]==n.m[3][1] && m[3][2]==n.m[3][2] && m[3][3]==n.m[3][3];
}
// * operator
Matrix4 operator*(const Matrix4 &n) const {
Matrix4 o;
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
float v = 0;
for(int k = 0; k < 4; k++) {
v += m[i][k] * n.m[k][j];
}
o.m[i][j] = v;
}
}
return o;
}
// * operator
Vector3 operator*(const Vector3 &v) const {
Vector3 u =Vector3(m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3],
m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3],
m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3]);
float w = m[3][0]*v.x + m[3][1]*v.y + m[3][2]*v.z + m[3][3];
return u/w;
}
// * operator
Vector4 operator*(const Vector4 &v) const {
Vector4 u = Vector4(m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + v.w*m[0][3],
m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + v.w*m[1][3],
m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + v.w*m[2][3],
m[3][0]*v.x + m[3][1]*v.y + m[3][2]*v.z + v.w*m[3][3]);
if(u.w != 0)
return u/u.w;
else
return u;
}
// * operator
Matrix4 operator*(float f) const {
return Matrix4(m[0][0]*f, m[0][1]*f, m[0][2]*f, m[0][3]*f,
m[1][0]*f, m[1][1]*f, m[1][2]*f, m[1][3]*f,
m[2][0]*f, m[2][1]*f, m[2][2]*f, m[2][3]*f,
m[3][0]*f, m[3][1]*f, m[3][2]*f, m[3][3]*f);
}
// * operator
Matrix4 &operator*=(float f) {
m[0][0]*=f; m[0][1]*=f; m[0][2]*=f; m[0][3]*=f;
m[1][0]*=f; m[1][1]*=f; m[1][2]*=f; m[1][3]*=f;
m[2][0]*=f; m[2][1]*=f; m[2][2]*=f; m[2][3]*=f;
m[3][0]*=f; m[3][1]*=f; m[3][2]*=f; m[3][3]*=f;
return *this;
}
// / operator
Matrix4 operator/(float f) const {
assert(f!=0);
return Matrix4(m[0][0]/f, m[0][1]/f, m[0][2]/f, m[0][3]/f,
m[1][0]/f, m[1][1]/f, m[1][2]/f, m[1][3]/f,
m[2][0]/f, m[2][1]/f, m[2][2]/f, m[2][3]/f,
m[3][0]/f, m[3][1]/f, m[3][2]/f, m[3][3]/f);
}
// /= operator
Matrix4 &operator/=(float f) {
assert(f!=0);
m[0][0]/=f; m[0][1]/=f; m[0][2]/=f; m[0][3]/=f;
m[1][0]/=f; m[1][1]/=f; m[1][2]/=f; m[1][3]/=f;
m[2][0]/=f; m[2][1]/=f; m[2][2]/=f; m[2][3]/=f;
m[3][0]/=f; m[3][1]/=f; m[3][2]/=f; m[3][3]/=f;
return *this;
}
// - operator
Matrix4 operator-() const {
return Matrix4(-m[0][0], -m[0][1], -m[0][2], -m[0][3],
-m[1][0], -m[1][1], -m[1][2], -m[1][3],
-m[2][0], -m[2][1], -m[2][2], -m[2][3],
-m[3][0], -m[3][1], -m[3][2], -m[3][3]);
}
// Return the transpose matrix
Matrix4 getTranspose() const {
return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
m[0][1], m[1][1], m[2][1], m[3][1],
m[0][2], m[1][2], m[2][2], m[3][2],
m[0][3], m[1][3], m[2][3], m[3][3]);
}
// Return the inversed matrix
Matrix4 getInverse() const {
int indxc[4], indxr[4];
int ipiv[4] = { 0, 0, 0, 0 };
float minv[4][4];
float temp;
for (int s=0; s<4; s++) {
for (int t=0; t<4; t++) {
minv[s][t] = m[s][t];
}
}
for (int i = 0; i < 4; i++) {
int irow = -1, icol = -1;
float big = 0.;
// Choose pivot
for (int j = 0; j < 4; j++) {
if (ipiv[j] != 1) {
for (int k = 0; k < 4; k++) {
if (ipiv[k] == 0) {
if (fabs(minv[j][k]) >= big) {
big = float(fabs(minv[j][k]));
irow = j;
icol = k;
}
}
else if (ipiv[k] > 1) {
std::cout << "ERROR: Singular matrix in MatrixInvert\n";
}
}
}
}
++ipiv[icol];
// Swap rows _irow_ and _icol_ for pivot
if (irow != icol) {
for (int k = 0; k < 4; ++k){
temp = minv[irow][k];
minv[irow][k] = minv[icol][k];
minv[icol][k] = temp;
}
}
indxr[i] = irow;
indxc[i] = icol;
if (minv[icol][icol] == 0.){
std::cout << "Singular matrix in MatrixInvert\n";
}
// Set $m[icol][icol]$ to one by scaling row _icol_ appropriately
float pivinv = 1.f / minv[icol][icol];
minv[icol][icol] = 1.f;
for (int j = 0; j < 4; j++) {
minv[icol][j] *= pivinv;
}
// Subtract this row from others to zero out their columns
for (int j = 0; j < 4; j++) {
if (j != icol) {
float save = minv[j][icol];
minv[j][icol] = 0;
for (int k = 0; k < 4; k++) {
minv[j][k] -= minv[icol][k]*save;
}
}
}
}
// Swap columns to reflect permutation
for (int j = 3; j >= 0; j--) {
if (indxr[j] != indxc[j]) {
for (int k = 0; k < 4; k++){
temp = minv[k][indxr[j]];
minv[k][indxr[j]] = minv[k][indxc[j]];
minv[k][indxc[j]] = temp;
}
}
}
return Matrix4(minv);
}
// Method to set all the values in the matrix
void setAllValues(float a1, float a2, float a3, float a4,
float b1, float b2, float b3, float b4,
float c1, float c2, float c3, float c4,
float d1, float d2, float d3, float d4) {
m[0][0] = a1; m[0][1] = a2; m[0][2] = a3, m[0][3] = a4;
m[1][0] = b1; m[1][1] = b2; m[1][2] = b3; m[1][3] = b4;
m[2][0] = c1; m[2][1] = c2; m[2][2] = c3; m[2][3] = c4;
m[3][0] = d1; m[3][1] = d2; m[3][2] = d3; m[3][3] = d4;
}
// Set the matrix to the identity matrix
Matrix4 setToIdentity() {
m[0][0] = 1.f; m[0][1] = 0.f; m[0][2] = 0.f; m[0][3] = 0.f;
m[1][0] = 0.f; m[1][1] = 1.f; m[1][2] = 0.f; m[1][3] = 0.f;
m[2][0] = 0.f; m[2][1] = 0.f; m[2][2] = 1.f; m[2][3] = 0.f;
m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f;
return *this;
}
// Display the matrix
void print() const {
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++) {
std::cout << m[i][j];
}
std::cout << std::endl;
}
}
// Return the pointer to the data array of the matrix
float* dataBlock() {
return m[0];
}
// Return the constant pointer to the data array of the matrix
const float* dataBlock() const {
return m[0];
}
// Return a given value from the matrix
float getValue(int i, int j) const {
assert(i >= 0 && i<4 && j >= 0 && j<4);
return m[i][j];
}
// Return the trace of the matrix
float getTrace() const {
// Compute and return the trace
return (m[0][0] + m[1][1] + m[2][2] + m[3][3]);
}
// Return a 4x4 translation matrix
static Matrix4 translationMatrix(const Vector3& v);
// Return a 4x4 rotation matrix
static Matrix4 rotationMatrix(const Vector3& axis, float angle);
};
// * operator
inline Matrix4 operator*(float f, const Matrix4 & m) {
return (m * f);
}
// Return a 4x4 translation matrix
inline Matrix4 Matrix4::translationMatrix(const Vector3& v) {
return Matrix4(1, 0, 0, v.x,
0, 1, 0, v.y,
0, 0, 1, v.z,
0, 0, 0, 1);
}
// Return a 4x4 rotation matrix
inline Matrix4 Matrix4::rotationMatrix(const Vector3& axis, float angle) {
float cosA = cos(angle);
float sinA = sin(angle);
Matrix4 rotationMatrix;
rotationMatrix.setToIdentity();
rotationMatrix.m[0][0] = cosA + (1-cosA) * axis.x * axis.x;
rotationMatrix.m[0][1] = (1-cosA) * axis.x * axis.y - axis.z * sinA;
rotationMatrix.m[0][2] = (1-cosA) * axis.x * axis.z + axis.y * sinA;
rotationMatrix.m[0][3] = 0.f;
rotationMatrix.m[1][0] = (1-cosA) * axis.x * axis.y + axis.z * sinA;
rotationMatrix.m[1][1] = cosA + (1-cosA) * axis.y * axis.y;
rotationMatrix.m[1][2] = (1-cosA) * axis.y * axis.z - axis.x * sinA;
rotationMatrix.m[1][3] = 0.f;
rotationMatrix.m[2][0] = (1-cosA) * axis.x * axis.z - axis.y * sinA;
rotationMatrix.m[2][1] = (1-cosA) * axis.y * axis.z + axis.x * sinA;
rotationMatrix.m[2][2] = cosA + (1-cosA) * axis.z * axis.z;
rotationMatrix.m[2][3] = 0.f;
rotationMatrix.m[3][0] = 0.f;
rotationMatrix.m[3][1] = 0.f;
rotationMatrix.m[3][2] = 0.f;
rotationMatrix.m[3][3] = 1.f;
return rotationMatrix;
}
}
#endif //_MATRIX4_H

View File

@ -0,0 +1,159 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef VECTOR2_H
#define VECTOR2_H
// Libraries
#include <math.h>
#include <assert.h>
namespace openglframework {
// Class Vector2
// This class represents a 2D vector.
class Vector2 {
public:
// -------------------- Attributes -------------------- //
// Components of the vector
float x, y;
// -------------------- Methods -------------------- //
// Constructor
Vector2(float x=0, float y=0) : x(x), y(y) {}
// Constructor
Vector2(const Vector2& vector) : x(vector.x), y(vector.y) {}
// + operator
Vector2 operator+(const Vector2 &v) const {
return Vector2(x + v.x, y + v.y);
}
// += operator
Vector2& operator+=(const Vector2 &v) {
x += v.x; y += v.y;
return *this;
}
// - operator
Vector2 operator-(const Vector2 &v) const {
return Vector2(x - v.x, y - v.y);
}
// -= operator
Vector2& operator-=(const Vector2 &v) {
x -= v.x; y -= v.y;
return *this;
}
// = operator
Vector2& operator=(const Vector2& vector) {
if (&vector != this) {
x = vector.x;
y = vector.y;
}
return *this;
}
// == operator
bool operator==(const Vector2 &v) const {
return x == v.x && y == v.y;
}
// * operator
Vector2 operator*(float f) const {
return Vector2(f*x, f*y);
}
// *= operator
Vector2 &operator*=(float f) {
x *= f; y *= f;
return *this;
}
// / operator
Vector2 operator/(float f) const {
assert(f!=0);
float inv = 1.f / f;
return Vector2(x * inv, y * inv);
}
// /= operator
Vector2 &operator/=(float f) {
assert(f!=0);
float inv = 1.f / f;
x *= inv; y *= inv;
return *this;
}
// - operator
Vector2 operator-() const {
return Vector2(-x, -y);
}
// [] operator
float &operator[](int i) {
assert(i >= 0 && i <= 1);
switch (i) {
case 0: return x;
case 1: return y;
}
return y;
}
// Normalize the vector and return it
Vector2 normalize() {
float l = length();
assert(l > 0);
x /= l;
y /= l;
return *this;
}
// Clamp the vector values between 0 and 1
Vector2 clamp01() {
if (x>1.f) x=1.f;
else if (x<0.f) x=0.f;
if (y>1.f) y=1.f;
else if (y<0.f) y=0.f;
return *this;
}
// Return the squared length of the vector
float lengthSquared() const { return x*x + y*y; }
// Return the length of the vector
float length() const { return sqrt(lengthSquared()); }
};
}
#endif

View File

@ -0,0 +1,203 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef OPENGLFRAMEWORK_VECTOR3_H
#define OPENGLFRAMEWORK_VECTOR3_H
// Libraries
#include <cmath>
#include <cassert>
#include <limits>
namespace openglframework {
// Class Vector3
// This class represents a 3D vector.
class Vector3 {
public:
// -------------------- Attributes -------------------- //
// Components of the vector
float x, y, z;
// -------------------- Methods -------------------- //
// Constructor
Vector3(float x=0, float y=0, float z=0) : x(x), y(y), z(z) {}
// Constructor
Vector3(const Vector3& vector) : x(vector.x), y(vector.y), z(vector.z) {}
// Constructor
~Vector3() {}
// = operator
Vector3& operator=(const Vector3& vector) {
if (&vector != this) {
x = vector.x;
y = vector.y;
z = vector.z;
}
return *this;
}
// + operator
Vector3 operator+(const Vector3 &v) const {
return Vector3(x + v.x, y + v.y, z + v.z);
}
// += operator
Vector3& operator+=(const Vector3 &v) {
x += v.x; y += v.y; z += v.z;
return *this;
}
// - operator
Vector3 operator-(const Vector3 &v) const {
return Vector3(x - v.x, y - v.y, z - v.z);
}
// -= operator
Vector3& operator-=(const Vector3 &v) {
x -= v.x; y -= v.y; z -= v.z;
return *this;
}
// == operator
bool operator==(const Vector3 &v) const {
return x == v.x && y == v.y && z == v.z;
}
// != operator
bool operator!=(const Vector3 &v) const {
return !( *this == v );
}
// * operator
Vector3 operator*(float f) const {
return Vector3(f*x, f*y, f*z);
}
// *= operator
Vector3 &operator*=(float f) {
x *= f; y *= f; z *= f;
return *this;
}
// / operator
Vector3 operator/(float f) const {
assert(f > std::numeric_limits<float>::epsilon() );
float inv = 1.f / f;
return Vector3(x * inv, y * inv, z * inv);
}
// /= operator
Vector3 &operator/=(float f) {
assert(f > std::numeric_limits<float>::epsilon());
float inv = 1.f / f;
x *= inv; y *= inv; z *= inv;
return *this;
}
// - operator
Vector3 operator-() const {
return Vector3(-x, -y, -z);
}
// [] operator
float &operator[](int i) {
assert(i >= 0 && i <= 2);
switch (i) {
case 0: return x;
case 1: return y;
case 2: return z;
}
return z;
}
// [] operator
const float &operator[](int i) const {
assert(i >= 0 && i <= 2);
switch (i) {
case 0: return x;
case 1: return y;
case 2: return z;
}
return z;
}
// Cross product operator
Vector3 cross(const Vector3 &v) const{
return Vector3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
}
// Dot product operator
float dot(const Vector3 &v) const{
return x * v.x + y * v.y + z * v.z;
}
// Normalize the vector and return it
Vector3 normalize() {
float l = length();
if(l < std::numeric_limits<float>::epsilon() ) {
assert(false);
}
x /= l;
y /= l;
z /= l;
return *this;
}
bool isNull() const {
return( x == 0. && y == 0. && z == 0. );
}
// Clamp the values between 0 and 1
Vector3 clamp01() {
if (x>1.f) x=1.f;
else if (x<0.f) x=0.f;
if (y>1.f) y=1.f;
else if (y<0.f) y=0.f;
if (z>1.f) z=1.f;
else if (z<0.f) z=0.f;
return *this;
}
// Return the squared length of the vector
float lengthSquared() const { return x*x + y*y + z*z; }
// Return the length of the vector
float length() const { return sqrt(lengthSquared()); }
};
inline Vector3 operator*(float f, const Vector3 & o) {
return o*f;
}
}
#endif

View File

@ -0,0 +1,167 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef VECTOR4_H
#define VECTOR4_H
// Libraries
#include <math.h>
#include <assert.h>
namespace openglframework {
// Class Vector4
// This class represents a 4D vector.
class Vector4 {
public:
// -------------------- Attributes -------------------- //
// Components of the vector
float x, y, z, w;
// -------------------- Methods -------------------- //
// Constructor
Vector4(float x=0, float y=0, float z=0, float w=0) : x(x), y(y), z(z), w(w) {}
// Constructor
Vector4(const Vector4& vector) : x(vector.x), y(vector.y), z(vector.z), w(vector.w) {}
// + operator
Vector4 operator+(const Vector4 &v) const {
return Vector4(x + v.x, y + v.y, z + v.z, w + v.w);
}
// += operator
Vector4& operator+=(const Vector4 &v) {
x += v.x; y += v.y; z += v.z; w += v.w;
return *this;
}
// - operator
Vector4 operator-(const Vector4 &v) const {
return Vector4(x - v.x, y - v.y, z - v.z, w - v.w);
}
// -= operator
Vector4& operator-=(const Vector4 &v) {
x -= v.x; y -= v.y; z -= v.z, w -=v.w;
return *this;
}
// = operator
Vector4& operator=(const Vector4& vector) {
if (&vector != this) {
x = vector.x;
y = vector.y;
z = vector.z;
w = vector.w;
}
return *this;
}
// == operator
bool operator==(const Vector4 &v) const {
return x == v.x && y == v.y && z == v.z && w == v.w;
}
// * operator
Vector4 operator*(float f) const {
return Vector4(f*x, f*y, f*z, f*w);
}
// *= operator
Vector4 &operator*=(float f) {
x *= f; y *= f; z *= f; w *= f;
return *this;
}
// / operator
Vector4 operator/(float f) const {
assert(f!=0);
float inv = 1.f / f;
return Vector4(x * inv, y * inv, z * inv, w * inv);
}
// /= operator
Vector4 &operator/=(float f) {
assert(f!=0);
float inv = 1.f / f;
x *= inv; y *= inv; z *= inv; w *= inv;
return *this;
}
// - operator
Vector4 operator-() const {
return Vector4(-x, -y, -z, -w);
}
// [] operator
float &operator[](int i) {
assert(i >= 0 && i <= 3);
switch (i) {
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
return w;
}
// Dot product operator
float dot(const Vector4 &v) const {
return x * v.x + y * v.y + z * v.z + w * v.w;
}
// Multiply two vectors by their components
Vector4 componentMul(const Vector4 &v) const {
return Vector4(x * v.x, y * v.y, z * v.z, w * v.w);
}
// Clamp the values between 0 and 1
Vector4 clamp01() {
if (x>1.f) x=1.f;
else if (x<0.f) x=0.f;
if (y>1.f) y=1.f;
else if (y<0.f) y=0.f;
if (z>1.f) z=1.f;
else if (z<0.f) z=0.f;
if (w>1.f) w=1.f;
else if (w<0.f) w=0.f;
return *this;
}
// Return the squared length of the vector
float lengthSquared() const { return x * x + y * y + z * z + w * w; }
// Return the length of the vector
float length() const { return sqrt(lengthSquared()); }
};
}
#endif //_VECTOR4_H

View File

@ -0,0 +1,49 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef OPENGL_FRAMEWORK_H
#define OPENGL_FRAMEWORK_H
// Libraries
#include "MeshReaderWriter.h"
#include "TextureReaderWriter.h"
#include "GlutViewer.h"
#include "Camera.h"
#include "Light.h"
#include "Mesh.h"
#include "Shader.h"
#include "Texture2D.h"
#include "FrameBufferObject.h"
#include "VertexBufferObject.h"
#include "Shader.h"
#include "maths/Color.h"
#include "maths/Vector2.h"
#include "maths/Vector3.h"
#include "maths/Vector4.h"
#include "maths/Matrix4.h"
#include "maths/Matrix3.h"
#include "definitions.h"
#endif

View File

@ -0,0 +1,32 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
void main(void) {
// Compute the depth of the pixel
float depth =
gl_FragColor = vec4(depth, depth, depth, 1);
}

View File

@ -0,0 +1,36 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Uniform variables
uniform mat4 modelToWorldMatrix; // Model too world coordinates matrix
uniform mat4 worldToCameraMatrix; // World to camera coordinates matrix
uniform mat4 projectionMatrix; // Projection matrix
void main(void) {
// Compute the clip-space vertex coordinates
gl_Position = projectionMatrix * worldToCameraMatrix *
modelToWorldMatrix * gl_Vertex;
}

View File

@ -0,0 +1,63 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Uniform variables
uniform vec3 cameraWorldPosition; // World position of the camera
uniform vec3 lightWorldPosition; // World position of the light
uniform vec3 lightAmbientColor; // Lights ambient color
uniform vec3 lightDiffuseColor; // Light diffuse color
uniform vec3 lightSpecularColor; // Light specular color
uniform float shininess; // Shininess
uniform sampler2D texture; // Texture
uniform bool isTexture; // True if we need to use the texture
// Varying variables
varying vec3 worldPosition; // World position of the vertex
varying vec3 worldNormal; // World surface normalWorld
varying vec2 texCoords; // Texture coordinates
void main() {
// Compute the ambient term
vec3 ambient = lightAmbientColor;
// Get the texture color
vec3 textureColor = vec3(1);
if (isTexture) textureColor = texture2D(texture, texCoords).rgb;
// Compute the diffuse term
vec3 L = normalize(lightWorldPosition - worldPosition);
vec3 N = normalize(worldNormal);
vec3 diffuse = lightDiffuseColor * max(dot(N, L), 0.0) * textureColor;
// Compute the specular term
vec3 V = normalize(cameraWorldPosition - worldPosition);
vec3 H = normalize(V + L);
vec3 specular = lightSpecularColor * pow(max(dot(N, H), 0), shininess);
// Compute the final color
gl_FragColor = vec4(ambient + diffuse + specular, 1.0);
}

View File

@ -0,0 +1,51 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Uniform variables
uniform mat4 modelToWorldMatrix; // Model too world coordinates matrix
uniform mat4 worldToCameraMatrix; // World to camera coordinates matrix
uniform mat4 projectionMatrix; // Projection matrix
// Varying variables
varying vec3 worldPosition; // World position of the vertex
varying vec3 worldNormal; // World surface normalWorld
varying vec2 texCoords; // Texture coordinates
void main() {
// Compute the vertex position
vec4 worldPos = modelToWorldMatrix * gl_Vertex;
worldPosition = worldPos.xyz;
// Compute the world surface normal
vec3 bodyNormal = normalize(gl_Normal);
worldNormal = (modelToWorldMatrix * vec4(bodyNormal, 0.0)).xyz;
// Get the texture coordinates
texCoords = gl_MultiTexCoord0.xy;
// Compute the clip-space vertex coordinates
gl_Position = projectionMatrix * worldToCameraMatrix * worldPos;
}