Merge branch 'develop' of https://code.google.com/p/reactphysics3d into develop
This commit is contained in:
commit
51f164bfa7
141
CMakeLists.txt
141
CMakeLists.txt
|
@ -7,9 +7,6 @@ PROJECT(REACTPHYSICS3D)
|
|||
# Where to build the library
|
||||
SET(LIBRARY_OUTPUT_PATH lib/)
|
||||
|
||||
# Where to find the module to find special packages/libraries
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
|
||||
# Options
|
||||
OPTION(COMPILE_EXAMPLES "Select this if you want to build the examples" OFF)
|
||||
OPTION(COMPILE_TESTS "Select this if you want to build the tests" OFF)
|
||||
|
@ -19,34 +16,130 @@ OPTION(DOUBLE_PRECISION_ENABLED "Select this if you want to compile using double
|
|||
# Headers
|
||||
INCLUDE_DIRECTORIES(src)
|
||||
|
||||
IF (PROFILING_ENABLED)
|
||||
ADD_DEFINITIONS(-DIS_PROFILING_ACTIVE)
|
||||
ENDIF (PROFILING_ENABLED)
|
||||
IF(PROFILING_ENABLED)
|
||||
ADD_DEFINITIONS(-DIS_PROFILING_ACTIVE)
|
||||
ENDIF(PROFILING_ENABLED)
|
||||
|
||||
IF (DOUBLE_PRECISION_ENABLED)
|
||||
ADD_DEFINITIONS(-DIS_DOUBLE_PRECISION_ENABLED)
|
||||
ENDIF (DOUBLE_PRECISION_ENABLED)
|
||||
IF(DOUBLE_PRECISION_ENABLED)
|
||||
ADD_DEFINITIONS(-DIS_DOUBLE_PRECISION_ENABLED)
|
||||
ENDIF(DOUBLE_PRECISION_ENABLED)
|
||||
|
||||
# Library configuration
|
||||
file (
|
||||
GLOB_RECURSE
|
||||
source_files
|
||||
src/*
|
||||
# Source files
|
||||
SET (REACTPHYSICS3D_SOURCES
|
||||
"src/configuration.h"
|
||||
"src/decimal.h"
|
||||
"src/reactphysics3d.h"
|
||||
"src/body/Body.h"
|
||||
"src/body/Body.cpp"
|
||||
"src/body/CollisionBody.h"
|
||||
"src/body/CollisionBody.cpp"
|
||||
"src/body/RigidBody.h"
|
||||
"src/body/RigidBody.cpp"
|
||||
"src/collision/broadphase/BroadPhaseAlgorithm.h"
|
||||
"src/collision/broadphase/BroadPhaseAlgorithm.cpp"
|
||||
"src/collision/broadphase/NoBroadPhaseAlgorithm.h"
|
||||
"src/collision/broadphase/NoBroadPhaseAlgorithm.cpp"
|
||||
"src/collision/broadphase/PairManager.h"
|
||||
"src/collision/broadphase/PairManager.cpp"
|
||||
"src/collision/broadphase/SweepAndPruneAlgorithm.h"
|
||||
"src/collision/broadphase/SweepAndPruneAlgorithm.cpp"
|
||||
"src/collision/narrowphase/EPA/EdgeEPA.h"
|
||||
"src/collision/narrowphase/EPA/EdgeEPA.cpp"
|
||||
"src/collision/narrowphase/EPA/EPAAlgorithm.h"
|
||||
"src/collision/narrowphase/EPA/EPAAlgorithm.cpp"
|
||||
"src/collision/narrowphase/EPA/TriangleEPA.h"
|
||||
"src/collision/narrowphase/EPA/TriangleEPA.cpp"
|
||||
"src/collision/narrowphase/EPA/TrianglesStore.h"
|
||||
"src/collision/narrowphase/EPA/TrianglesStore.cpp"
|
||||
"src/collision/narrowphase/GJK/Simplex.h"
|
||||
"src/collision/narrowphase/GJK/Simplex.cpp"
|
||||
"src/collision/narrowphase/GJK/GJKAlgorithm.h"
|
||||
"src/collision/narrowphase/GJK/GJKAlgorithm.cpp"
|
||||
"src/collision/narrowphase/NarrowPhaseAlgorithm.h"
|
||||
"src/collision/narrowphase/NarrowPhaseAlgorithm.cpp"
|
||||
"src/collision/narrowphase/SphereVsSphereAlgorithm.h"
|
||||
"src/collision/narrowphase/SphereVsSphereAlgorithm.cpp"
|
||||
"src/collision/shapes/AABB.h"
|
||||
"src/collision/shapes/AABB.cpp"
|
||||
"src/collision/shapes/BoxShape.h"
|
||||
"src/collision/shapes/BoxShape.cpp"
|
||||
"src/collision/shapes/CapsuleShape.h"
|
||||
"src/collision/shapes/CapsuleShape.cpp"
|
||||
"src/collision/shapes/CollisionShape.h"
|
||||
"src/collision/shapes/CollisionShape.cpp"
|
||||
"src/collision/shapes/ConeShape.h"
|
||||
"src/collision/shapes/ConeShape.cpp"
|
||||
"src/collision/shapes/ConvexMeshShape.h"
|
||||
"src/collision/shapes/ConvexMeshShape.cpp"
|
||||
"src/collision/shapes/CylinderShape.h"
|
||||
"src/collision/shapes/CylinderShape.cpp"
|
||||
"src/collision/shapes/SphereShape.h"
|
||||
"src/collision/shapes/SphereShape.cpp"
|
||||
"src/collision/BroadPhasePair.h"
|
||||
"src/collision/BroadPhasePair.cpp"
|
||||
"src/collision/CollisionDetection.h"
|
||||
"src/collision/CollisionDetection.cpp"
|
||||
"src/constraint/BallAndSocketJoint.h"
|
||||
"src/constraint/BallAndSocketJoint.cpp"
|
||||
"src/constraint/ContactPoint.h"
|
||||
"src/constraint/ContactPoint.cpp"
|
||||
"src/constraint/FixedJoint.h"
|
||||
"src/constraint/FixedJoint.cpp"
|
||||
"src/constraint/HingeJoint.h"
|
||||
"src/constraint/HingeJoint.cpp"
|
||||
"src/constraint/Joint.h"
|
||||
"src/constraint/Joint.cpp"
|
||||
"src/constraint/SliderJoint.h"
|
||||
"src/constraint/SliderJoint.cpp"
|
||||
"src/engine/CollisionWorld.h"
|
||||
"src/engine/CollisionWorld.cpp"
|
||||
"src/engine/ConstraintSolver.h"
|
||||
"src/engine/ConstraintSolver.cpp"
|
||||
"src/engine/ContactManifold.h"
|
||||
"src/engine/ContactManifold.cpp"
|
||||
"src/engine/ContactSolver.h"
|
||||
"src/engine/ContactSolver.cpp"
|
||||
"src/engine/DynamicsWorld.h"
|
||||
"src/engine/DynamicsWorld.cpp"
|
||||
"src/engine/EventListener.h"
|
||||
"src/engine/Impulse.h"
|
||||
"src/engine/Island.h"
|
||||
"src/engine/Island.cpp"
|
||||
"src/engine/Material.h"
|
||||
"src/engine/Material.cpp"
|
||||
"src/engine/OverlappingPair.h"
|
||||
"src/engine/OverlappingPair.cpp"
|
||||
"src/engine/Profiler.h"
|
||||
"src/engine/Profiler.cpp"
|
||||
"src/engine/Timer.h"
|
||||
"src/engine/Timer.cpp"
|
||||
"src/mathematics/mathematics.h"
|
||||
"src/mathematics/mathematics_functions.h"
|
||||
"src/mathematics/Matrix2x2.h"
|
||||
"src/mathematics/Matrix2x2.cpp"
|
||||
"src/mathematics/Matrix3x3.h"
|
||||
"src/mathematics/Matrix3x3.cpp"
|
||||
"src/mathematics/Quaternion.h"
|
||||
"src/mathematics/Quaternion.cpp"
|
||||
"src/mathematics/Transform.h"
|
||||
"src/mathematics/Transform.cpp"
|
||||
"src/mathematics/Vector2.h"
|
||||
"src/mathematics/Vector2.cpp"
|
||||
"src/mathematics/Vector3.h"
|
||||
"src/mathematics/Vector3.cpp"
|
||||
"src/memory/MemoryAllocator.h"
|
||||
"src/memory/MemoryAllocator.cpp"
|
||||
)
|
||||
|
||||
# Require the reactphysics3d code to be compiled in a static library
|
||||
ADD_LIBRARY (
|
||||
reactphysics3d
|
||||
STATIC
|
||||
${source_files}
|
||||
)
|
||||
# Create the library
|
||||
ADD_LIBRARY (reactphysics3d STATIC ${REACTPHYSICS3D_SOURCES})
|
||||
|
||||
# If we need to compile the examples
|
||||
IF (COMPILE_EXAMPLES)
|
||||
IF(COMPILE_EXAMPLES)
|
||||
add_subdirectory(examples/)
|
||||
ENDIF (COMPILE_EXAMPLES)
|
||||
ENDIF(COMPILE_EXAMPLES)
|
||||
|
||||
# If we need to compile the tests
|
||||
IF (COMPILE_TESTS)
|
||||
IF(COMPILE_TESTS)
|
||||
add_subdirectory(test/)
|
||||
ENDIF (COMPILE_TESTS)
|
||||
ENDIF(COMPILE_TESTS)
|
||||
|
|
32
cmake/FindFreeglut.cmake
Normal file
32
cmake/FindFreeglut.cmake
Normal file
|
@ -0,0 +1,32 @@
|
|||
# This module is used to try to find the Freeglut library and include files
|
||||
|
||||
IF(WIN32)
|
||||
FIND_PATH(FREEGLUT_INCLUDE_DIR NAMES GL/freeglut.h)
|
||||
FIND_LIBRARY(FREEGLUT_LIBRARY NAMES freeglut freeglut_static)
|
||||
PATHS ${OPENGL_LIBRARY_DIR})
|
||||
ELSE(WIN32)
|
||||
|
||||
IF(APPLE)
|
||||
# Do nothing, we do not want to use freeglut on Mac OS X
|
||||
ELSE(APPLE)
|
||||
FIND_PATH(FREEGLUT_INCLUDE_DIR GL/freeglut.h /usr/include/GL
|
||||
/usr/openwin/share/include
|
||||
/usr/openwin/include
|
||||
/opt/graphics/OpenGL/include
|
||||
/opt/graphics/OpenGL/contrib/libglut)
|
||||
|
||||
FIND_LIBRARY(FREEGLUT_LIBRARY NAMES freeglut freeglut_static PATHS /usr/openwin/lib)
|
||||
FIND_LIBRARY(Xi_LIBRARY Xi /usr/openwin/lib)
|
||||
FIND_LIBRARY(Xmu_LIBRARY Xmu /usr/openwin/lib)
|
||||
ENDIF(APPLE)
|
||||
ENDIF(WIN32)
|
||||
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FREEGLUT REQUIRED_VARS FREEGLUT_LIBRARY FREEGLUT_INCLUDE_DIR)
|
||||
|
||||
IF(FREEGLUT_FOUND)
|
||||
SET(FREEGLUT_LIBRARIES ${FREEGLUT_LIBRARY} ${Xi_LIBRARY} ${Xmu_LIBRARY})
|
||||
SET(FREEGLUT_LIBRARY ${FREEGLUT_LIBRARIES})
|
||||
ENDIF(FREEGLUT_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(FREEGLUT_INCLUDE_DIR FREEGLUT_LIBRARY Xi_LIBRARY Xmu_LIBRARY)
|
|
@ -1,7 +1,15 @@
|
|||
# Minimum cmake version required
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
add_subdirectory(common/)
|
||||
add_subdirectory(fallingcubes/)
|
||||
add_subdirectory(joints/)
|
||||
add_subdirectory(convexmesh/)
|
||||
# Set a variable for the directory of the opengl-framework
|
||||
SET(OPENGLFRAMEWORK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/common/opengl-framework")
|
||||
|
||||
# If we will use FREEGLUT
|
||||
IF(NOT APPLE)
|
||||
ADD_DEFINITIONS(-DUSE_FREEGLUT)
|
||||
ENDIF()
|
||||
|
||||
ADD_SUBDIRECTORY(common/)
|
||||
ADD_SUBDIRECTORY(cubes/)
|
||||
ADD_SUBDIRECTORY(joints/)
|
||||
ADD_SUBDIRECTORY(collisionshapes/)
|
||||
|
|
38
examples/collisionshapes/CMakeLists.txt
Normal file
38
examples/collisionshapes/CMakeLists.txt
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Minimum cmake version required
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
# Project configuration
|
||||
PROJECT(CollisionShapes)
|
||||
|
||||
# Where to build the executable
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin/collisionshapes/)
|
||||
|
||||
# Copy the shaders used for the demo into the build directory
|
||||
FILE(COPY "${OPENGLFRAMEWORK_DIR}/src/shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
|
||||
|
||||
# Copy the meshes used for the demo into the build directory
|
||||
FILE(COPY "../common/meshes/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/meshes/")
|
||||
|
||||
# Headers
|
||||
INCLUDE_DIRECTORIES("${OPENGLFRAMEWORK_DIR}/src/" "../common/")
|
||||
|
||||
# Source files
|
||||
SET(COLLISION_SHAPES_SOURCES
|
||||
CollisionShapes.cpp
|
||||
Scene.cpp
|
||||
Scene.h
|
||||
"../common/VisualContactPoint.cpp"
|
||||
"../common/ConvexMesh.cpp"
|
||||
"../common/Capsule.cpp"
|
||||
"../common/Sphere.cpp"
|
||||
"../common/Cylinder.cpp"
|
||||
"../common/Cone.cpp"
|
||||
"../common/Box.cpp"
|
||||
"../common/Viewer.cpp"
|
||||
)
|
||||
|
||||
# Create the executable
|
||||
ADD_EXECUTABLE(collisionshapes ${COLLISION_SHAPES_SOURCES})
|
||||
|
||||
# Link with libraries
|
||||
TARGET_LINK_LIBRARIES(collisionshapes reactphysics3d openglframework)
|
158
examples/collisionshapes/CollisionShapes.cpp
Normal file
158
examples/collisionshapes/CollisionShapes.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
/********************************************************************************
|
||||
* 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"
|
||||
#include "Viewer.h"
|
||||
|
||||
// Declarations
|
||||
void simulate();
|
||||
void display();
|
||||
void finish();
|
||||
void reshape(int width, int height);
|
||||
void mouseButton(int button, int state, int x, int y);
|
||||
void mouseMotion(int x, int y);
|
||||
void keyboard(unsigned char key, int x, int y);
|
||||
void init();
|
||||
|
||||
// Namespaces
|
||||
using namespace openglframework;
|
||||
|
||||
// Global variables
|
||||
Viewer* viewer;
|
||||
Scene* scene;
|
||||
|
||||
// Main function
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// Create and initialize the Viewer
|
||||
viewer = new Viewer();
|
||||
Vector2 windowsSize = Vector2(800, 600);
|
||||
Vector2 windowsPosition = Vector2(100, 100);
|
||||
bool initOK = viewer->init(argc, argv, "ReactPhysics3D Examples - Collision Shapes",
|
||||
windowsSize, windowsPosition);
|
||||
if (!initOK) return 1;
|
||||
|
||||
// Create the scene
|
||||
scene = new Scene(viewer);
|
||||
|
||||
init();
|
||||
|
||||
// Glut Idle function that is continuously called
|
||||
glutIdleFunc(simulate);
|
||||
glutDisplayFunc(display);
|
||||
glutReshapeFunc(reshape);
|
||||
glutMouseFunc(mouseButton);
|
||||
glutMotionFunc(mouseMotion);
|
||||
glutKeyboardFunc(keyboard);
|
||||
#ifdef USE_FREEGLUT
|
||||
glutCloseFunc(finish);
|
||||
#else
|
||||
atexit(finish);
|
||||
#endif
|
||||
|
||||
// Glut main looop
|
||||
glutMainLoop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Simulate function
|
||||
void simulate() {
|
||||
|
||||
// Physics simulation
|
||||
scene->simulate();
|
||||
|
||||
viewer->computeFPS();
|
||||
|
||||
// Ask GLUT to render the scene
|
||||
glutPostRedisplay ();
|
||||
}
|
||||
|
||||
// Initialization
|
||||
void init() {
|
||||
|
||||
// Define the background color (black)
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Reshape function
|
||||
void reshape(int newWidth, int newHeight) {
|
||||
viewer->reshape(newWidth, 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 keyboard(unsigned char key, int x, int y) {
|
||||
switch(key) {
|
||||
|
||||
// Escape key
|
||||
case 27:
|
||||
#ifdef USE_FREEGLUT
|
||||
glutLeaveMainLoop();
|
||||
#endif
|
||||
break;
|
||||
|
||||
// Space bar
|
||||
case 32:
|
||||
scene->pauseContinueSimulation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// End of the application
|
||||
void finish() {
|
||||
|
||||
// Destroy the viewer and the scene
|
||||
delete viewer;
|
||||
delete scene;
|
||||
}
|
||||
|
||||
// Display the scene
|
||||
void display() {
|
||||
|
||||
// Render the scene
|
||||
scene->render();
|
||||
|
||||
// Display the FPS
|
||||
viewer->displayGUI();
|
||||
|
||||
// Swap the buffers
|
||||
glutSwapBuffers();
|
||||
|
||||
// Check the OpenGL errors
|
||||
GlutViewer::checkOpenGLErrors();
|
||||
}
|
||||
|
||||
|
451
examples/collisionshapes/Scene.cpp
Normal file
451
examples/collisionshapes/Scene.cpp
Normal file
|
@ -0,0 +1,451 @@
|
|||
/********************************************************************************
|
||||
* 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"), mIsRunning(false) {
|
||||
|
||||
// Move the light 0
|
||||
mLight0.translateWorld(Vector3(50, 50, 50));
|
||||
|
||||
// Compute the radius and the center of the scene
|
||||
float radiusScene = 10.0f;
|
||||
openglframework::Vector3 center(0, 5, 0);
|
||||
|
||||
// Set the center of the scene
|
||||
mViewer->setScenePosition(center, radiusScene);
|
||||
|
||||
// Gravity vector in the dynamics world
|
||||
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
|
||||
|
||||
// Time step for the physics simulation
|
||||
rp3d::decimal timeStep = 1.0f / 60.0f;
|
||||
|
||||
// Create the dynamics world for the physics simulation
|
||||
mDynamicsWorld = new rp3d::DynamicsWorld(gravity, timeStep);
|
||||
|
||||
// Set the number of iterations of the constraint solver
|
||||
mDynamicsWorld->setNbIterationsVelocitySolver(15);
|
||||
|
||||
// Create the static data for the visual contact points
|
||||
VisualContactPoint::createStaticData();
|
||||
|
||||
float radius = 3.0f;
|
||||
|
||||
// Create all the boxes of the scene
|
||||
for (int i=0; i<NB_BOXES; i++) {
|
||||
|
||||
// Position
|
||||
float angle = i * 30.0f;
|
||||
openglframework::Vector3 position(radius * cos(angle),
|
||||
60 + i * (BOX_SIZE.y + 0.8f),
|
||||
radius * sin(angle));
|
||||
|
||||
// Create a sphere and a corresponding rigid in the dynamics world
|
||||
Box* box = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld);
|
||||
|
||||
// The sphere is a moving rigid body
|
||||
box->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = box->getRigidBody()->getMaterial();
|
||||
material.setBounciness(rp3d::decimal(0.2));
|
||||
|
||||
// Add the sphere the list of sphere in the scene
|
||||
mBoxes.push_back(box);
|
||||
}
|
||||
|
||||
// Create all the spheres of the scene
|
||||
for (int i=0; i<NB_SPHERES; i++) {
|
||||
|
||||
// Position
|
||||
float angle = i * 35.0f;
|
||||
openglframework::Vector3 position(radius * cos(angle),
|
||||
50 + i * (SPHERE_RADIUS + 0.8f),
|
||||
radius * sin(angle));
|
||||
|
||||
// Create a sphere and a corresponding rigid in the dynamics world
|
||||
Sphere* sphere = new Sphere(SPHERE_RADIUS, position , BOX_MASS, mDynamicsWorld);
|
||||
|
||||
// The sphere is a moving rigid body
|
||||
sphere->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = sphere->getRigidBody()->getMaterial();
|
||||
material.setBounciness(rp3d::decimal(0.2));
|
||||
|
||||
// Add the sphere the list of sphere in the scene
|
||||
mSpheres.push_back(sphere);
|
||||
}
|
||||
|
||||
// Create all the cones of the scene
|
||||
for (int i=0; i<NB_CONES; i++) {
|
||||
|
||||
// Position
|
||||
float angle = i * 50.0f;
|
||||
openglframework::Vector3 position(radius * cos(angle),
|
||||
35 + i * (CONE_HEIGHT + 0.3f),
|
||||
radius * sin(angle));
|
||||
|
||||
// Create a cone and a corresponding rigid in the dynamics world
|
||||
Cone* cone = new Cone(CONE_RADIUS, CONE_HEIGHT, position , CONE_MASS, mDynamicsWorld);
|
||||
|
||||
// The cone is a moving rigid body
|
||||
cone->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = cone->getRigidBody()->getMaterial();
|
||||
material.setBounciness(rp3d::decimal(0.2));
|
||||
|
||||
// Add the cone the list of sphere in the scene
|
||||
mCones.push_back(cone);
|
||||
}
|
||||
|
||||
// Create all the cylinders of the scene
|
||||
for (int i=0; i<NB_CYLINDERS; i++) {
|
||||
|
||||
// Position
|
||||
float angle = i * 35.0f;
|
||||
openglframework::Vector3 position(radius * cos(angle),
|
||||
25 + i * (CYLINDER_HEIGHT + 0.3f),
|
||||
radius * sin(angle));
|
||||
|
||||
// Create a cylinder and a corresponding rigid in the dynamics world
|
||||
Cylinder* cylinder = new Cylinder(CYLINDER_RADIUS, CYLINDER_HEIGHT, position ,
|
||||
CYLINDER_MASS, mDynamicsWorld);
|
||||
|
||||
// The cylinder is a moving rigid body
|
||||
cylinder->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = cylinder->getRigidBody()->getMaterial();
|
||||
material.setBounciness(rp3d::decimal(0.2));
|
||||
|
||||
// Add the cylinder the list of sphere in the scene
|
||||
mCylinders.push_back(cylinder);
|
||||
}
|
||||
|
||||
// Create all the capsules of the scene
|
||||
for (int i=0; i<NB_CAPSULES; i++) {
|
||||
|
||||
// Position
|
||||
float angle = i * 45.0f;
|
||||
openglframework::Vector3 position(radius * cos(angle),
|
||||
15 + i * (CAPSULE_HEIGHT + 0.3f),
|
||||
radius * sin(angle));
|
||||
|
||||
// Create a cylinder and a corresponding rigid in the dynamics world
|
||||
Capsule* capsule = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, position ,
|
||||
CAPSULE_MASS, mDynamicsWorld);
|
||||
|
||||
// The cylinder is a moving rigid body
|
||||
capsule->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = capsule->getRigidBody()->getMaterial();
|
||||
material.setBounciness(rp3d::decimal(0.2));
|
||||
|
||||
// Add the cylinder the list of sphere in the scene
|
||||
mCapsules.push_back(capsule);
|
||||
}
|
||||
|
||||
// Create all the convex meshes of the scene
|
||||
for (int i=0; i<NB_MESHES; i++) {
|
||||
|
||||
// Position
|
||||
float angle = i * 30.0f;
|
||||
openglframework::Vector3 position(radius * cos(angle),
|
||||
5 + i * (CAPSULE_HEIGHT + 0.3f),
|
||||
radius * sin(angle));
|
||||
|
||||
// Create a convex mesh and a corresponding rigid in the dynamics world
|
||||
ConvexMesh* mesh = new ConvexMesh(position, MESH_MASS, mDynamicsWorld);
|
||||
|
||||
// The mesh is a moving rigid body
|
||||
mesh->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = mesh->getRigidBody()->getMaterial();
|
||||
material.setBounciness(rp3d::decimal(0.2));
|
||||
|
||||
// Add the mesh the list of sphere in the scene
|
||||
mConvexMeshes.push_back(mesh);
|
||||
}
|
||||
|
||||
// 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()->enableMotion(false);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = mFloor->getRigidBody()->getMaterial();
|
||||
material.setBounciness(rp3d::decimal(0.2));
|
||||
|
||||
// Start the simulation
|
||||
startSimulation();
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Scene::~Scene() {
|
||||
|
||||
// Stop the physics simulation
|
||||
stopSimulation();
|
||||
|
||||
// Destroy the shader
|
||||
mPhongShader.destroy();
|
||||
|
||||
// Destroy all the boxes 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 box
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
// Destroy all the sphere of the scene
|
||||
for (std::vector<Sphere*>::iterator it = mSpheres.begin(); it != mSpheres.end(); ++it) {
|
||||
|
||||
// Destroy the corresponding rigid body from the dynamics world
|
||||
mDynamicsWorld->destroyRigidBody((*it)->getRigidBody());
|
||||
|
||||
// Destroy the sphere
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
// Destroy all the cones of the scene
|
||||
for (std::vector<Cone*>::iterator it = mCones.begin(); it != mCones.end(); ++it) {
|
||||
|
||||
// Destroy the corresponding rigid body from the dynamics world
|
||||
mDynamicsWorld->destroyRigidBody((*it)->getRigidBody());
|
||||
|
||||
// Destroy the sphere
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
// Destroy all the cylinders of the scene
|
||||
for (std::vector<Cylinder*>::iterator it = mCylinders.begin(); it != mCylinders.end(); ++it) {
|
||||
|
||||
// Destroy the corresponding rigid body from the dynamics world
|
||||
mDynamicsWorld->destroyRigidBody((*it)->getRigidBody());
|
||||
|
||||
// Destroy the sphere
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
// Destroy all the capsules of the scene
|
||||
for (std::vector<Capsule*>::iterator it = mCapsules.begin(); it != mCapsules.end(); ++it) {
|
||||
|
||||
// Destroy the corresponding rigid body from the dynamics world
|
||||
mDynamicsWorld->destroyRigidBody((*it)->getRigidBody());
|
||||
|
||||
// Destroy the sphere
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
// Destroy all the convex meshes of the scene
|
||||
for (std::vector<ConvexMesh*>::iterator it = mConvexMeshes.begin();
|
||||
it != mConvexMeshes.end(); ++it) {
|
||||
|
||||
// Destroy the corresponding rigid body from the dynamics world
|
||||
mDynamicsWorld->destroyRigidBody((*it)->getRigidBody());
|
||||
|
||||
// Destroy the convex mesh
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
// Destroy all the visual contact points
|
||||
for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin();
|
||||
it != mContactPoints.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
// Destroy the static data for the visual contact points
|
||||
VisualContactPoint::destroyStaticData();
|
||||
|
||||
// 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() {
|
||||
|
||||
// If the physics simulation is running
|
||||
if (mIsRunning) {
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// Update the position and orientation of the sphere
|
||||
for (std::vector<Sphere*>::iterator it = mSpheres.begin(); it != mSpheres.end(); ++it) {
|
||||
|
||||
// Update the transform used for the rendering
|
||||
(*it)->updateTransform();
|
||||
}
|
||||
|
||||
// Update the position and orientation of the cones
|
||||
for (std::vector<Cone*>::iterator it = mCones.begin(); it != mCones.end(); ++it) {
|
||||
|
||||
// Update the transform used for the rendering
|
||||
(*it)->updateTransform();
|
||||
}
|
||||
|
||||
// Update the position and orientation of the cylinders
|
||||
for (std::vector<Cylinder*>::iterator it = mCylinders.begin(); it != mCylinders.end(); ++it) {
|
||||
|
||||
// Update the transform used for the rendering
|
||||
(*it)->updateTransform();
|
||||
}
|
||||
|
||||
// Update the position and orientation of the capsules
|
||||
for (std::vector<Capsule*>::iterator it = mCapsules.begin(); it != mCapsules.end(); ++it) {
|
||||
|
||||
// Update the transform used for the rendering
|
||||
(*it)->updateTransform();
|
||||
}
|
||||
|
||||
// Update the position and orientation of the convex meshes
|
||||
for (std::vector<ConvexMesh*>::iterator it = mConvexMeshes.begin();
|
||||
it != mConvexMeshes.end(); ++it) {
|
||||
|
||||
// Update the transform used for the rendering
|
||||
(*it)->updateTransform();
|
||||
}
|
||||
|
||||
// Destroy all the visual contact points
|
||||
for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin();
|
||||
it != mContactPoints.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
mContactPoints.clear();
|
||||
|
||||
// Generate the new visual contact points
|
||||
const std::vector<rp3d::ContactManifold*>& manifolds = mDynamicsWorld->getContactManifolds();
|
||||
for (std::vector<rp3d::ContactManifold*>::const_iterator it = manifolds.begin();
|
||||
it != manifolds.end(); ++it) {
|
||||
for (unsigned int i=0; i<(*it)->getNbContactPoints(); i++) {
|
||||
rp3d::ContactPoint* point = (*it)->getContactPoint(i);
|
||||
|
||||
const rp3d::Vector3 pos = point->getWorldPointOnBody1();
|
||||
openglframework::Vector3 position(pos.x, pos.y, pos.z);
|
||||
VisualContactPoint* visualPoint = new VisualContactPoint(position);
|
||||
mContactPoints.push_back(visualPoint);
|
||||
}
|
||||
}
|
||||
|
||||
mFloor->updateTransform();
|
||||
}
|
||||
}
|
||||
|
||||
// Render the scene
|
||||
void Scene::render() {
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
// Get the world-space to camera-space matrix
|
||||
const Camera& camera = mViewer->getCamera();
|
||||
const openglframework::Matrix4 worldToCameraMatrix = camera.getTransformMatrix().getInverse();
|
||||
|
||||
// Bind the shader
|
||||
mPhongShader.bind();
|
||||
|
||||
// Set the variables of the shader
|
||||
mPhongShader.setMatrix4x4Uniform("projectionMatrix", camera.getProjectionMatrix());
|
||||
mPhongShader.setVector3Uniform("light0PosCameraSpace", worldToCameraMatrix * mLight0.getOrigin());
|
||||
mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f));
|
||||
const Color& diffColLight0 = mLight0.getDiffuseColor();
|
||||
const Color& specColLight0 = mLight0.getSpecularColor();
|
||||
mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffColLight0.r, diffColLight0.g, diffColLight0.b));
|
||||
mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specColLight0.r, specColLight0.g, specColLight0.b));
|
||||
mPhongShader.setFloatUniform("shininess", 200.0f);
|
||||
|
||||
// Render all the boxes of the scene
|
||||
for (std::vector<Box*>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) {
|
||||
(*it)->render(mPhongShader, worldToCameraMatrix);
|
||||
}
|
||||
|
||||
// Render all the sphere of the scene
|
||||
for (std::vector<Sphere*>::iterator it = mSpheres.begin(); it != mSpheres.end(); ++it) {
|
||||
(*it)->render(mPhongShader, worldToCameraMatrix);
|
||||
}
|
||||
|
||||
// Render all the cones of the scene
|
||||
for (std::vector<Cone*>::iterator it = mCones.begin(); it != mCones.end(); ++it) {
|
||||
(*it)->render(mPhongShader, worldToCameraMatrix);
|
||||
}
|
||||
|
||||
// Render all the cylinders of the scene
|
||||
for (std::vector<Cylinder*>::iterator it = mCylinders.begin(); it != mCylinders.end(); ++it) {
|
||||
(*it)->render(mPhongShader, worldToCameraMatrix);
|
||||
}
|
||||
|
||||
// Render all the capsules of the scene
|
||||
for (std::vector<Capsule*>::iterator it = mCapsules.begin(); it != mCapsules.end(); ++it) {
|
||||
(*it)->render(mPhongShader, worldToCameraMatrix);
|
||||
}
|
||||
|
||||
// Render all the convex meshes of the scene
|
||||
for (std::vector<ConvexMesh*>::iterator it = mConvexMeshes.begin();
|
||||
it != mConvexMeshes.end(); ++it) {
|
||||
(*it)->render(mPhongShader, worldToCameraMatrix);
|
||||
}
|
||||
|
||||
// Render all the visual contact points
|
||||
for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin();
|
||||
it != mContactPoints.end(); ++it) {
|
||||
(*it)->render(mPhongShader, worldToCameraMatrix);
|
||||
}
|
||||
|
||||
// Render the floor
|
||||
mFloor->render(mPhongShader, worldToCameraMatrix);
|
||||
|
||||
// Unbind the shader
|
||||
mPhongShader.unbind();
|
||||
}
|
153
examples/collisionshapes/Scene.h
Normal file
153
examples/collisionshapes/Scene.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/********************************************************************************
|
||||
* 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 "Sphere.h"
|
||||
#include "Box.h"
|
||||
#include "Cone.h"
|
||||
#include "Cylinder.h"
|
||||
#include "Capsule.h"
|
||||
#include "ConvexMesh.h"
|
||||
#include "VisualContactPoint.h"
|
||||
|
||||
// Constants
|
||||
const int NB_BOXES = 3;
|
||||
const int NB_SPHERES = 3;
|
||||
const int NB_CONES = 3;
|
||||
const int NB_CYLINDERS = 3;
|
||||
const int NB_CAPSULES = 3;
|
||||
const int NB_MESHES = 3;
|
||||
const openglframework::Vector3 BOX_SIZE(2, 2, 2);
|
||||
const float SPHERE_RADIUS = 1.5f;
|
||||
const float CONE_RADIUS = 2.0f;
|
||||
const float CONE_HEIGHT = 3.0f;
|
||||
const float CYLINDER_RADIUS = 1.0f;
|
||||
const float CYLINDER_HEIGHT = 5.0f;
|
||||
const float CAPSULE_RADIUS = 1.0f;
|
||||
const float CAPSULE_HEIGHT = 1.0f;
|
||||
const openglframework::Vector3 FLOOR_SIZE(20, 0.5f, 20); // Floor dimensions in meters
|
||||
const float BOX_MASS = 1.0f;
|
||||
const float CONE_MASS = 1.0f;
|
||||
const float CYLINDER_MASS = 1.0f;
|
||||
const float CAPSULE_MASS = 1.0f;
|
||||
const float MESH_MASS = 1.0f;
|
||||
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 spheres of the scene
|
||||
std::vector<Box*> mBoxes;
|
||||
|
||||
std::vector<Sphere*> mSpheres;
|
||||
|
||||
std::vector<Cone*> mCones;
|
||||
|
||||
std::vector<Cylinder*> mCylinders;
|
||||
|
||||
std::vector<Capsule*> mCapsules;
|
||||
|
||||
/// All the convex meshes of the scene
|
||||
std::vector<ConvexMesh*> mConvexMeshes;
|
||||
|
||||
/// All the visual contact points
|
||||
std::vector<VisualContactPoint*> mContactPoints;
|
||||
|
||||
/// Box for the floor
|
||||
Box* mFloor;
|
||||
|
||||
/// Dynamics world used for the physics simulation
|
||||
rp3d::DynamicsWorld* mDynamicsWorld;
|
||||
|
||||
/// True if the physics simulation is running
|
||||
bool mIsRunning;
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Scene(openglframework::GlutViewer* viewer);
|
||||
|
||||
/// Destructor
|
||||
~Scene();
|
||||
|
||||
/// Take a step for the simulation
|
||||
void simulate();
|
||||
|
||||
/// Stop the simulation
|
||||
void stopSimulation();
|
||||
|
||||
/// Start the simulation
|
||||
void startSimulation();
|
||||
|
||||
/// Pause or continue simulation
|
||||
void pauseContinueSimulation();
|
||||
|
||||
/// Render the scene
|
||||
void render();
|
||||
};
|
||||
|
||||
// Stop the simulation
|
||||
inline void Scene::stopSimulation() {
|
||||
mDynamicsWorld->stop();
|
||||
mIsRunning = false;
|
||||
}
|
||||
|
||||
// Start the simulation
|
||||
inline void Scene::startSimulation() {
|
||||
mDynamicsWorld->start();
|
||||
mIsRunning = true;
|
||||
}
|
||||
|
||||
// Pause or continue simulation
|
||||
inline void Scene::pauseContinueSimulation() {
|
||||
if (mIsRunning) {
|
||||
stopSimulation();
|
||||
}
|
||||
else {
|
||||
startSimulation();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -34,14 +34,14 @@ 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)}
|
||||
{openglframework::Vector3(1,1,1),openglframework::Vector3(1,1,1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(-1,1,1),openglframework::Vector3(-1,1,1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(-1,-1,1),openglframework::Vector3(-1,-1,1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(1,-1,1),openglframework::Vector3(1,-1,1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(1,-1,-1),openglframework::Vector3(1,-1,-1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(-1,-1,-1),openglframework::Vector3(-1,-1,-1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(-1,1,-1),openglframework::Vector3(-1,1,-1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(1,1,-1),openglframework::Vector3(1,1,-1),openglframework::Color(1,0,0,1)}
|
||||
};
|
||||
GLuint Box::mCubeIndices[36] = { 0, 1, 2,
|
||||
2, 3, 0,
|
||||
|
@ -59,7 +59,7 @@ GLuint Box::mCubeIndices[36] = { 0, 1, 2,
|
|||
// Constructor
|
||||
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position,
|
||||
float mass, reactphysics3d::DynamicsWorld* dynamicsWorld)
|
||||
: openglframework::Object3D() {
|
||||
: openglframework::Object3D(), mColor(0.5f, 0.5f, 0.5f, 1.0f) {
|
||||
|
||||
// Initialize the size of the box
|
||||
mSize[0] = size.x * 0.5f;
|
||||
|
@ -77,7 +77,7 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p
|
|||
|
||||
// Create the collision shape for the rigid body (box shape)
|
||||
// ReactPhysics3D will clone this object to create an internal one. Therefore,
|
||||
// it is OK if this object is destroy right after calling Dynamics::createRigidBody()
|
||||
// it is OK if this object is destroyed right after calling Dynamics::createRigidBody()
|
||||
const rp3d::BoxShape collisionShape(rp3d::Vector3(mSize[0], mSize[1], mSize[2]));
|
||||
|
||||
// Compute the inertia tensor of the body using its collision shape
|
||||
|
@ -121,6 +121,10 @@ void Box::render(openglframework::Shader& shader,
|
|||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
|
||||
// Set the vertex color
|
||||
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color);
|
||||
|
||||
// Bind the vertices VBO
|
||||
mVBOVertices.bind();
|
||||
|
||||
|
|
|
@ -74,6 +74,9 @@ class Box : public openglframework::Object3D {
|
|||
/// True if the VBOs have already been created
|
||||
static bool areVBOsCreated;
|
||||
|
||||
/// Main color of the box
|
||||
openglframework::Color mColor;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Create a Vertex Buffer Object to render to box with OpenGL
|
||||
|
@ -98,6 +101,9 @@ class Box : public openglframework::Object3D {
|
|||
|
||||
/// Render the cube at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix);
|
||||
|
||||
/// Set the color of the box
|
||||
void setColor(const openglframework::Color& color);
|
||||
};
|
||||
|
||||
// Return a pointer to the rigid body of the box
|
||||
|
@ -105,4 +111,9 @@ inline rp3d::RigidBody* Box::getRigidBody() {
|
|||
return mRigidBody;
|
||||
}
|
||||
|
||||
// Set the color of the box
|
||||
inline void Box::setColor(const openglframework::Color& color) {
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Minimum cmake version required
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
add_subdirectory(opengl-framework/)
|
||||
ADD_SUBDIRECTORY(opengl-framework/)
|
||||
|
|
|
@ -40,16 +40,16 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3 &pos
|
|||
|
||||
// Compute the scaling matrix
|
||||
mScalingMatrix = openglframework::Matrix4(mRadius, 0, 0, 0,
|
||||
0, (mHeight + 2.0 * mRadius) / 3.0, 0,0,
|
||||
0, (mHeight + 2.0f * mRadius) / 3.0f, 0,0,
|
||||
0, 0, mRadius, 0,
|
||||
0, 0, 0, 1);
|
||||
0, 0, 0, 1.0f);
|
||||
|
||||
// Initialize the position where the sphere will be rendered
|
||||
translateWorld(position);
|
||||
|
||||
// Create the collision shape for the rigid body (sphere shape)
|
||||
// ReactPhysics3D will clone this object to create an internal one. Therefore,
|
||||
// it is OK if this object is destroy right after calling Dynamics::createRigidBody()
|
||||
// it is OK if this object is destroyed right after calling Dynamics::createRigidBody()
|
||||
const rp3d::CapsuleShape collisionShape(mRadius, mHeight);
|
||||
|
||||
// Compute the inertia tensor of the body using its collision shape
|
||||
|
|
|
@ -49,7 +49,7 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
|
|||
|
||||
// Create the collision shape for the rigid body (cone shape)
|
||||
// ReactPhysics3D will clone this object to create an internal one. Therefore,
|
||||
// it is OK if this object is destroy right after calling Dynamics::createRigidBody()
|
||||
// it is OK if this object is destroyed right after calling Dynamics::createRigidBody()
|
||||
const rp3d::ConeShape collisionShape(mRadius, mHeight);
|
||||
|
||||
// Compute the inertia tensor of the body using its collision shape
|
||||
|
|
149
examples/common/ConvexMesh.cpp
Normal file
149
examples/common/ConvexMesh.cpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
/********************************************************************************
|
||||
* 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 "ConvexMesh.h"
|
||||
|
||||
|
||||
// Constructor
|
||||
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
|
||||
reactphysics3d::DynamicsWorld* dynamicsWorld)
|
||||
: openglframework::Mesh() {
|
||||
|
||||
// Load the mesh from a file
|
||||
openglframework::MeshReaderWriter::loadMeshFromFile("meshes/convexmesh.obj", *this);
|
||||
|
||||
// Calculate the normals of the mesh
|
||||
calculateNormals();
|
||||
|
||||
// Initialize the position where the sphere will be rendered
|
||||
translateWorld(position);
|
||||
|
||||
// Create the collision shape for the rigid body (convex mesh shape)
|
||||
// ReactPhysics3D will clone this object to create an internal one. Therefore,
|
||||
// it is OK if this object is destroyed right after calling Dynamics::createRigidBody()
|
||||
rp3d::decimal* verticesArray = (rp3d::decimal*) getVerticesPointer();
|
||||
rp3d::ConvexMeshShape collisionShape(verticesArray, mVertices.size(),
|
||||
sizeof(openglframework::Vector3));
|
||||
|
||||
// Add the edges information of the mesh into the convex mesh collision shape.
|
||||
// This is optional but it really speed up the convex mesh collision detection at the
|
||||
// cost of some additional memory to store the edges inside the collision shape.
|
||||
for (unsigned int i=0; i<getNbFaces(); i++) { // For each triangle face of the mesh
|
||||
|
||||
// Get the three vertex IDs of the vertices of the face
|
||||
unsigned int v1 = getVertexIndexInFace(i, 0);
|
||||
unsigned int v2 = getVertexIndexInFace(i, 1);
|
||||
unsigned int v3 = getVertexIndexInFace(i, 2);
|
||||
|
||||
// Add the three edges into the collision shape
|
||||
collisionShape.addEdge(v1, v2);
|
||||
collisionShape.addEdge(v1, v3);
|
||||
collisionShape.addEdge(v2, v3);
|
||||
}
|
||||
collisionShape.setIsEdgesInformationUsed(true);// Enable the fast collision detection with edges
|
||||
|
||||
// Compute the inertia tensor of the body using its collision shape
|
||||
rp3d::Matrix3x3 inertiaTensor;
|
||||
collisionShape.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 sphere in the dynamics world
|
||||
mRigidBody = dynamicsWorld->createRigidBody(transform, mass, inertiaTensor, collisionShape);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
ConvexMesh::~ConvexMesh() {
|
||||
|
||||
// Destroy the mesh
|
||||
destroy();
|
||||
}
|
||||
|
||||
// Render the sphere at the correct position and with the correct orientation
|
||||
void ConvexMesh::render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix) {
|
||||
|
||||
// Bind the shader
|
||||
shader.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
|
||||
|
||||
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
|
||||
// model-view matrix)
|
||||
const openglframework::Matrix3 normalMatrix =
|
||||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
|
||||
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
|
||||
if(hasTexture()) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
|
||||
}
|
||||
|
||||
// For each part of the mesh
|
||||
for (unsigned int i=0; i<getNbParts(); i++) {
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
|
||||
GL_UNSIGNED_INT, getIndicesPointer());
|
||||
}
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
// Unbind the shader
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
// Update the transform matrix of the sphere
|
||||
void ConvexMesh::updateTransform() {
|
||||
|
||||
// Get the interpolated transform of the rigid body
|
||||
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
|
||||
|
||||
// Compute the transform used for rendering the sphere
|
||||
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]);
|
||||
|
||||
// Apply the scaling matrix to have the correct sphere dimensions
|
||||
mTransformMatrix = newMatrix;
|
||||
}
|
72
examples/common/ConvexMesh.h
Normal file
72
examples/common/ConvexMesh.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/********************************************************************************
|
||||
* 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 CONVEX_MESH_H
|
||||
#define CONVEX_MESH_H
|
||||
|
||||
// Libraries
|
||||
#include "openglframework.h"
|
||||
#include "reactphysics3d.h"
|
||||
|
||||
// Class ConvexMesh
|
||||
class ConvexMesh : public openglframework::Mesh {
|
||||
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Rigid body used to simulate the dynamics of the mesh
|
||||
rp3d::RigidBody* mRigidBody;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ConvexMesh(const openglframework::Vector3& position, float mass,
|
||||
rp3d::DynamicsWorld* dynamicsWorld);
|
||||
|
||||
/// Destructor
|
||||
~ConvexMesh();
|
||||
|
||||
/// Return a pointer to the rigid body of the mesh
|
||||
rp3d::RigidBody* getRigidBody();
|
||||
|
||||
/// Update the transform matrix of the mesh
|
||||
void updateTransform();
|
||||
|
||||
/// Render the mesh at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix);
|
||||
};
|
||||
|
||||
// Return a pointer to the rigid body of the mesh
|
||||
inline rp3d::RigidBody* ConvexMesh::getRigidBody() {
|
||||
return mRigidBody;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -49,7 +49,7 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3 &p
|
|||
|
||||
// Create the collision shape for the rigid body (cylinder shape)
|
||||
// ReactPhysics3D will clone this object to create an internal one. Therefore,
|
||||
// it is OK if this object is destroy right after calling Dynamics::createRigidBody()
|
||||
// it is OK if this object is destroyed right after calling Dynamics::createRigidBody()
|
||||
const rp3d::CylinderShape collisionShape(mRadius, mHeight);
|
||||
|
||||
// Compute the inertia tensor of the body using its collision shape
|
||||
|
|
|
@ -49,7 +49,7 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position,
|
|||
|
||||
// Create the collision shape for the rigid body (sphere shape)
|
||||
// ReactPhysics3D will clone this object to create an internal one. Therefore,
|
||||
// it is OK if this object is destroy right after calling Dynamics::createRigidBody()
|
||||
// it is OK if this object is destroyed right after calling Dynamics::createRigidBody()
|
||||
const rp3d::SphereShape collisionShape(mRadius);
|
||||
|
||||
// Compute the inertia tensor of the body using its collision shape
|
||||
|
|
|
@ -48,7 +48,7 @@ void Viewer::computeFPS() {
|
|||
if(timeInterval > 1000){
|
||||
|
||||
// calculate the number of frames per second
|
||||
fps = nbFrames / (timeInterval / 1000.0f);
|
||||
fps = static_cast<int>(nbFrames / (timeInterval / 1000.0f));
|
||||
|
||||
// Set time
|
||||
previousTime = currentTime;
|
||||
|
@ -68,6 +68,7 @@ void Viewer::displayGUI() {
|
|||
// Display the FPS
|
||||
void Viewer::displayFPS() {
|
||||
|
||||
#ifdef USE_FREEGLUT
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, mCamera.getWidth(), mCamera.getHeight(), 0, -1, 1);
|
||||
|
@ -80,4 +81,5 @@ void Viewer::displayFPS() {
|
|||
std::stringstream ss;
|
||||
ss << "FPS : " << fps;
|
||||
glutBitmapString(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)ss.str().c_str());
|
||||
#endif
|
||||
}
|
||||
|
|
125
examples/common/meshes/convexmesh.obj
Normal file
125
examples/common/meshes/convexmesh.obj
Normal file
|
@ -0,0 +1,125 @@
|
|||
# Blender v2.66 (sub 0) OBJ File: ''
|
||||
# www.blender.org
|
||||
v 0.000000 -1.000000 0.000000
|
||||
v 0.723607 -0.447220 0.525725
|
||||
v -0.276388 -0.447220 0.850649
|
||||
v -0.894426 -0.447216 0.000000
|
||||
v -0.276388 -0.447220 -0.850649
|
||||
v 0.723607 -0.447220 -0.525725
|
||||
v 0.276388 0.447220 0.850649
|
||||
v -0.723607 0.447220 0.525725
|
||||
v -0.723607 0.447220 -0.525725
|
||||
v 0.276388 0.447220 -0.850649
|
||||
v 0.894426 0.447216 0.000000
|
||||
v 0.000000 1.000000 0.000000
|
||||
v 0.425323 -0.850654 0.309011
|
||||
v 0.262869 -0.525738 0.809012
|
||||
v -0.162456 -0.850654 0.499995
|
||||
v 0.425323 -0.850654 -0.309011
|
||||
v 0.850648 -0.525736 0.000000
|
||||
v -0.688189 -0.525736 0.499997
|
||||
v -0.525730 -0.850652 0.000000
|
||||
v -0.688189 -0.525736 -0.499997
|
||||
v -0.162456 -0.850654 -0.499995
|
||||
v 0.262869 -0.525738 -0.809012
|
||||
v 0.951058 0.000000 -0.309013
|
||||
v 0.951058 0.000000 0.309013
|
||||
v 0.587786 0.000000 0.809017
|
||||
v 0.000000 0.000000 1.000000
|
||||
v -0.587786 0.000000 0.809017
|
||||
v -0.951058 0.000000 0.309013
|
||||
v -0.951058 0.000000 -0.309013
|
||||
v -0.587786 0.000000 -0.809017
|
||||
v 0.000000 0.000000 -1.000000
|
||||
v 0.587786 0.000000 -0.809017
|
||||
v 0.688189 0.525736 0.499997
|
||||
v -0.262869 0.525738 0.809012
|
||||
v -0.850648 0.525736 0.000000
|
||||
v -0.262869 0.525738 -0.809012
|
||||
v 0.688189 0.525736 -0.499997
|
||||
v 0.525730 0.850652 0.000000
|
||||
v 0.162456 0.850654 0.499995
|
||||
v -0.425323 0.850654 0.309011
|
||||
v -0.425323 0.850654 -0.309011
|
||||
v 0.162456 0.850654 -0.499995
|
||||
s off
|
||||
f 1 13 15
|
||||
f 2 13 17
|
||||
f 1 15 19
|
||||
f 1 19 21
|
||||
f 1 21 16
|
||||
f 2 17 24
|
||||
f 3 14 26
|
||||
f 4 18 28
|
||||
f 5 20 30
|
||||
f 6 22 32
|
||||
f 2 24 25
|
||||
f 3 26 27
|
||||
f 4 28 29
|
||||
f 5 30 31
|
||||
f 6 32 23
|
||||
f 7 33 39
|
||||
f 8 34 40
|
||||
f 9 35 41
|
||||
f 10 36 42
|
||||
f 11 37 38
|
||||
f 15 14 3
|
||||
f 15 13 14
|
||||
f 13 2 14
|
||||
f 17 16 6
|
||||
f 17 13 16
|
||||
f 13 1 16
|
||||
f 19 18 4
|
||||
f 19 15 18
|
||||
f 15 3 18
|
||||
f 21 20 5
|
||||
f 21 19 20
|
||||
f 19 4 20
|
||||
f 16 22 6
|
||||
f 16 21 22
|
||||
f 21 5 22
|
||||
f 24 23 11
|
||||
f 24 17 23
|
||||
f 17 6 23
|
||||
f 26 25 7
|
||||
f 26 14 25
|
||||
f 14 2 25
|
||||
f 28 27 8
|
||||
f 28 18 27
|
||||
f 18 3 27
|
||||
f 30 29 9
|
||||
f 30 20 29
|
||||
f 20 4 29
|
||||
f 32 31 10
|
||||
f 32 22 31
|
||||
f 22 5 31
|
||||
f 25 33 7
|
||||
f 25 24 33
|
||||
f 24 11 33
|
||||
f 27 34 8
|
||||
f 27 26 34
|
||||
f 26 7 34
|
||||
f 29 35 9
|
||||
f 29 28 35
|
||||
f 28 8 35
|
||||
f 31 36 10
|
||||
f 31 30 36
|
||||
f 30 9 36
|
||||
f 23 37 11
|
||||
f 23 32 37
|
||||
f 32 10 37
|
||||
f 39 38 12
|
||||
f 39 33 38
|
||||
f 33 11 38
|
||||
f 40 39 12
|
||||
f 40 34 39
|
||||
f 34 7 39
|
||||
f 41 40 12
|
||||
f 41 35 40
|
||||
f 35 8 40
|
||||
f 42 41 12
|
||||
f 42 36 41
|
||||
f 36 9 41
|
||||
f 38 42 12
|
||||
f 38 37 42
|
||||
f 37 10 42
|
|
@ -4,52 +4,106 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
|||
# Project configuration
|
||||
PROJECT(OPENGLFRAMEWORK)
|
||||
|
||||
# Options
|
||||
OPTION(USE_JPEG_TEXTURES "Select this if you want to use jpeg textures (libjpeg required)" OFF)
|
||||
|
||||
# Where to find the module to find special packages/libraries
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
|
||||
# Find OpenGL
|
||||
FIND_PACKAGE(OpenGL REQUIRED)
|
||||
if(OPENGL_FOUND)
|
||||
IF(OPENGL_FOUND)
|
||||
MESSAGE("OpenGL found")
|
||||
else()
|
||||
ELSE()
|
||||
MESSAGE("OpenGL not found")
|
||||
endif()
|
||||
ENDIF()
|
||||
|
||||
# Find the GLEW library
|
||||
FIND_PACKAGE(GLEW REQUIRED)
|
||||
if(GLEW_FOUND)
|
||||
IF(GLEW_FOUND)
|
||||
MESSAGE("GLEW found")
|
||||
else()
|
||||
ELSE()
|
||||
MESSAGE("GLEW not found")
|
||||
endif()
|
||||
ENDIF()
|
||||
|
||||
# Find the LIBJPEG library
|
||||
FIND_PACKAGE(JPEG REQUIRED)
|
||||
if(JPEG_FOUND)
|
||||
MESSAGE("LIBJPEG found")
|
||||
else()
|
||||
MESSAGE("LIBJPEG not found")
|
||||
endif()
|
||||
# Find the GLUT/FREEGLUT library
|
||||
IF(APPLE)
|
||||
|
||||
# Freeglut
|
||||
add_subdirectory(freeglut)
|
||||
# Find the GLUT library
|
||||
FIND_PACKAGE(GLUT REQUIRED)
|
||||
IF(GLUT_FOUND)
|
||||
MESSAGE("GLUT found")
|
||||
ELSE(GLUT_FOUND)
|
||||
MESSAGE(SEND_ERROR "GLUT not found")
|
||||
ENDIF(GLUT_FOUND)
|
||||
|
||||
ELSE(APPLE)
|
||||
|
||||
# Find the FREEGLUT library
|
||||
FIND_PACKAGE(FREEGLUT REQUIRED)
|
||||
IF(FREEGLUT_FOUND)
|
||||
MESSAGE("FREEGLUT found")
|
||||
ELSE(FREEGLUT_FOUND)
|
||||
MESSAGE(SEND_ERROR "FREEGLUT not found")
|
||||
ENDIF(FREEGLUT_FOUND)
|
||||
|
||||
ENDIF(APPLE)
|
||||
|
||||
# If the user wants to use JPEG textures
|
||||
IF(USE_JPEG_TEXTURES)
|
||||
|
||||
# Find the LIBJPEG library
|
||||
FIND_PACKAGE(JPEG REQUIRED)
|
||||
IF(JPEG_FOUND)
|
||||
MESSAGE("LIBJPEG found")
|
||||
ELSE()
|
||||
MESSAGE("LIBJPEG not found")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Headers
|
||||
INCLUDE_DIRECTORIES(src freeglut ${JPEG_INCLUDE_DIR})
|
||||
INCLUDE_DIRECTORIES(src ${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_PATH} ${FREEGLUT_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${JPEG_INCLUDE_DIR})
|
||||
|
||||
# Library configuration
|
||||
file (
|
||||
GLOB_RECURSE
|
||||
OPENGLFRAMEWORK_SOURCES_FILES
|
||||
src/*
|
||||
# Source files
|
||||
SET(OPENGL_FRAMEWORK_SOURCES
|
||||
"src/maths/Color.h"
|
||||
"src/maths/Matrix3.h"
|
||||
"src/maths/Matrix4.h"
|
||||
"src/maths/Vector2.h"
|
||||
"src/maths/Vector3.h"
|
||||
"src/maths/Vector4.h"
|
||||
"src/Camera.cpp"
|
||||
"src/Camera.h"
|
||||
"src/definitions.h"
|
||||
"src/FrameBufferObject.cpp"
|
||||
"src/FrameBufferObject.h"
|
||||
"src/GlutViewer.cpp"
|
||||
"src/GlutViewer.h"
|
||||
"src/Light.h"
|
||||
"src/Light.cpp"
|
||||
"src/Mesh.h"
|
||||
"src/Mesh.cpp"
|
||||
"src/MeshReaderWriter.h"
|
||||
"src/MeshReaderWriter.cpp"
|
||||
"src/Object3D.h"
|
||||
"src/Object3D.cpp"
|
||||
"src/openglframework.h"
|
||||
"src/Shader.h"
|
||||
"src/Shader.cpp"
|
||||
"src/Texture2D.h"
|
||||
"src/Texture2D.cpp"
|
||||
"src/TextureReaderWriter.h"
|
||||
"src/TextureReaderWriter.cpp"
|
||||
"src/VertexBufferObject.h"
|
||||
"src/VertexBufferObject.cpp"
|
||||
)
|
||||
|
||||
IF(USE_JPEG_TEXTURES)
|
||||
ADD_DEFINITIONS(-DUSE_JPEG_TEXTURE)
|
||||
ENDIF()
|
||||
|
||||
# Require the opengl-framework code to be compiled in a static library
|
||||
ADD_LIBRARY (
|
||||
openglframework
|
||||
STATIC
|
||||
${OPENGLFRAMEWORK_SOURCES_FILES}
|
||||
)
|
||||
# Create the library
|
||||
ADD_LIBRARY (openglframework STATIC ${OPENGL_FRAMEWORK_SOURCES})
|
||||
|
||||
TARGET_LINK_LIBRARIES(openglframework ${GLEW_LIBRARIES} ${OPENGL_LIBRARY} freeglut_static)
|
||||
# Link with others libraries
|
||||
TARGET_LINK_LIBRARIES(openglframework ${GLEW_LIBRARIES} ${OPENGL_LIBRARY} ${FREEGLUT_LIBRARY} ${GLUT_LIBRARY})
|
||||
|
|
32
examples/common/opengl-framework/cmake/FindFREEGLUT.cmake
Normal file
32
examples/common/opengl-framework/cmake/FindFREEGLUT.cmake
Normal file
|
@ -0,0 +1,32 @@
|
|||
# This module is used to try to find the Freeglut library and include files
|
||||
|
||||
IF(WIN32)
|
||||
FIND_PATH(FREEGLUT_INCLUDE_DIR NAMES GL/freeglut.h)
|
||||
FIND_LIBRARY(FREEGLUT_LIBRARY NAMES freeglut freeglut_static
|
||||
PATHS ${OPENGL_LIBRARY_DIR})
|
||||
ELSE(WIN32)
|
||||
|
||||
IF(APPLE)
|
||||
# Do nothing, we do not want to use freeglut on Mac OS X
|
||||
ELSE(APPLE)
|
||||
FIND_PATH(FREEGLUT_INCLUDE_DIR GL/freeglut.h /usr/include/GL
|
||||
/usr/openwin/share/include
|
||||
/usr/openwin/include
|
||||
/opt/graphics/OpenGL/include
|
||||
/opt/graphics/OpenGL/contrib/libglut)
|
||||
|
||||
FIND_LIBRARY(FREEGLUT_LIBRARY NAMES glut freeglut freeglut_static PATHS /usr/openwin/lib)
|
||||
FIND_LIBRARY(Xi_LIBRARY Xi /usr/openwin/lib)
|
||||
FIND_LIBRARY(Xmu_LIBRARY Xmu /usr/openwin/lib)
|
||||
ENDIF(APPLE)
|
||||
ENDIF(WIN32)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FREEGLUT REQUIRED_VARS FREEGLUT_LIBRARY FREEGLUT_INCLUDE_DIR)
|
||||
|
||||
IF(FREEGLUT_FOUND)
|
||||
SET(FREEGLUT_LIBRARIES ${FREEGLUT_LIBRARY} ${Xi_LIBRARY} ${Xmu_LIBRARY})
|
||||
SET(FREEGLUT_LIBRARY ${FREEGLUT_LIBRARIES})
|
||||
ENDIF(FREEGLUT_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(FREEGLUT_INCLUDE_DIR FREEGLUT_LIBRARY Xi_LIBRARY Xmu_LIBRARY)
|
65
examples/common/opengl-framework/cmake/FindGLEW.cmake
Normal file
65
examples/common/opengl-framework/cmake/FindGLEW.cmake
Normal file
|
@ -0,0 +1,65 @@
|
|||
#
|
||||
# Try to find GLEW library and include path.
|
||||
# Once done this will define
|
||||
#
|
||||
# GLEW_FOUND
|
||||
# GLEW_INCLUDE_PATH
|
||||
# GLEW_LIBRARY
|
||||
#
|
||||
|
||||
IF (WIN32)
|
||||
FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
|
||||
$ENV{PROGRAMFILES}/GLEW/include
|
||||
${GLEW_ROOT_DIR}/include
|
||||
DOC "The directory where GL/glew.h resides")
|
||||
|
||||
IF (NV_SYSTEM_PROCESSOR STREQUAL "AMD64")
|
||||
FIND_LIBRARY( GLEW_LIBRARY
|
||||
NAMES glew64 glew64s
|
||||
PATHS
|
||||
$ENV{PROGRAMFILES}/GLEW/lib
|
||||
${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin
|
||||
${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib
|
||||
DOC "The GLEW library (64-bit)"
|
||||
)
|
||||
ELSE(NV_SYSTEM_PROCESSOR STREQUAL "AMD64")
|
||||
FIND_LIBRARY( GLEW_LIBRARY
|
||||
NAMES glew GLEW glew32 glew32s
|
||||
PATHS
|
||||
$ENV{PROGRAMFILES}/GLEW/lib
|
||||
${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin
|
||||
${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib
|
||||
DOC "The GLEW library"
|
||||
)
|
||||
ENDIF(NV_SYSTEM_PROCESSOR STREQUAL "AMD64")
|
||||
ELSE (WIN32)
|
||||
FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/sw/include
|
||||
/opt/local/include
|
||||
${GLEW_ROOT_DIR}/include
|
||||
DOC "The directory where GL/glew.h resides")
|
||||
|
||||
FIND_LIBRARY( GLEW_LIBRARY
|
||||
NAMES GLEW glew
|
||||
PATHS
|
||||
/usr/lib64
|
||||
/usr/lib
|
||||
/usr/local/lib64
|
||||
/usr/local/lib
|
||||
/sw/lib
|
||||
/opt/local/lib
|
||||
${GLEW_ROOT_DIR}/lib
|
||||
DOC "The GLEW library")
|
||||
ENDIF (WIN32)
|
||||
|
||||
SET(GLEW_FOUND "NO")
|
||||
IF (GLEW_INCLUDE_PATH AND GLEW_LIBRARY)
|
||||
SET(GLEW_LIBRARIES ${GLEW_LIBRARY})
|
||||
SET(GLEW_FOUND "YES")
|
||||
ENDIF (GLEW_INCLUDE_PATH AND GLEW_LIBRARY)
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_LIBRARY GLEW_INCLUDE_PATH)
|
|
@ -1,24 +0,0 @@
|
|||
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}
|
||||
)
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
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.
|
|
@ -1,22 +0,0 @@
|
|||
#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__ */
|
|
@ -1,236 +0,0 @@
|
|||
#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__ */
|
|
@ -1,628 +0,0 @@
|
|||
#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__ */
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#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__ */
|
|
@ -1 +0,0 @@
|
|||
2.8.0
|
|
@ -1,412 +0,0 @@
|
|||
/*
|
||||
* 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 ***/
|
|
@ -1,282 +0,0 @@
|
|||
/*
|
||||
* 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 ***/
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* 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 ***/
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* 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 );
|
||||
}
|
|
@ -1,384 +0,0 @@
|
|||
/*
|
||||
* 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
|
@ -1,819 +0,0 @@
|
|||
/*
|
||||
* 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
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* 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
|
@ -1,378 +0,0 @@
|
|||
/*
|
||||
* 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
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
* 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 ***/
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* 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 ***/
|
|
@ -1,471 +0,0 @@
|
|||
/* 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 */
|
|
@ -1,887 +0,0 @@
|
|||
/*
|
||||
* 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
|
@ -1,598 +0,0 @@
|
|||
/*
|
||||
* 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 ***/
|
|
@ -1,200 +0,0 @@
|
|||
/*
|
||||
* 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
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* 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
|
@ -1,219 +0,0 @@
|
|||
/* 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
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#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__ */
|
|
@ -32,7 +32,11 @@
|
|||
#include "maths/Vector2.h"
|
||||
#include <string>
|
||||
#include <GL/glew.h>
|
||||
#include "GL/freeglut.h"
|
||||
#ifdef __APPLE__
|
||||
#include "GLUT/glut.h"
|
||||
#else
|
||||
#include "GL/freeglut.h"
|
||||
#endif
|
||||
|
||||
namespace openglframework {
|
||||
|
||||
|
|
|
@ -84,7 +84,6 @@ void Mesh::calculateNormals() {
|
|||
|
||||
// Normalize the normal at each vertex
|
||||
for (uint i=0; i<getNbVertices(); i++) {
|
||||
std::cout << "vertex n : " << i << std::endl;
|
||||
mNormals[i] = mNormals[i].normalize();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace openglframework {
|
|||
// object that can be loaded from an OBJ file for instance.
|
||||
class Mesh : public Object3D {
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
|
|
|
@ -41,9 +41,7 @@ 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) {
|
||||
void MeshReaderWriter::loadMeshFromFile(const std::string& filename, Mesh& meshToCreate) {
|
||||
|
||||
// Get the extension of the file
|
||||
uint startPosExtension = filename.find_last_of(".");
|
||||
|
@ -64,9 +62,7 @@ void MeshReaderWriter::loadMeshFromFile(const std::string& filename,
|
|||
}
|
||||
|
||||
// Write a mesh to a file
|
||||
void MeshReaderWriter::writeMeshToFile(const std::string& filename,
|
||||
const Mesh& meshToWrite)
|
||||
throw(std::invalid_argument, std::runtime_error) {
|
||||
void MeshReaderWriter::writeMeshToFile(const std::string& filename, const Mesh& meshToWrite) {
|
||||
|
||||
// Get the extension of the file
|
||||
uint startPosExtension = filename.find_last_of(".");
|
||||
|
|
|
@ -57,14 +57,10 @@ class MeshReaderWriter {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
// Read a mesh from a file
|
||||
static void loadMeshFromFile(const std::string& filename,
|
||||
Mesh& meshToCreate)
|
||||
throw(std::invalid_argument, std::runtime_error);
|
||||
static void loadMeshFromFile(const std::string& filename, Mesh& meshToCreate);
|
||||
|
||||
// Write a mesh to a file
|
||||
static void writeMeshToFile(const std::string& filename,
|
||||
const Mesh& meshToWrite)
|
||||
throw(std::invalid_argument, std::runtime_error);
|
||||
static void writeMeshToFile(const std::string& filename, const Mesh& meshToWrite);
|
||||
};
|
||||
|
||||
// Class VertexMergingData
|
||||
|
|
|
@ -52,7 +52,7 @@ Texture2D::~Texture2D() {
|
|||
|
||||
// Create the texture
|
||||
void Texture2D::create(uint width, uint height, uint internalFormat, uint format, uint type,
|
||||
void* data) throw(std::invalid_argument) {
|
||||
void* data) {
|
||||
|
||||
// Destroy the current texture
|
||||
destroy();
|
||||
|
|
|
@ -69,7 +69,7 @@ class Texture2D {
|
|||
|
||||
// Create the texture
|
||||
void create(uint width, uint height, uint internalFormat, uint format, uint type,
|
||||
void* data = NULL) throw(std::invalid_argument);
|
||||
void* data = NULL);
|
||||
|
||||
// Destroy the texture
|
||||
void destroy();
|
||||
|
|
|
@ -26,8 +26,10 @@
|
|||
// Librairies
|
||||
#include "TextureReaderWriter.h"
|
||||
#include <string>
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
#ifdef USE_JPEG_TEXTURE
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
#endif
|
||||
|
||||
using namespace openglframework;
|
||||
using namespace std;
|
||||
|
@ -59,8 +61,7 @@ typedef struct {
|
|||
|
||||
// Load a texture from a file
|
||||
void TextureReaderWriter::loadTextureFromFile(const std::string& filename,
|
||||
Texture2D& textureToCreate)
|
||||
throw(runtime_error, invalid_argument){
|
||||
Texture2D& textureToCreate) {
|
||||
|
||||
// Get the extension of the file
|
||||
uint startPosExtension = filename.find_last_of(".");
|
||||
|
@ -70,9 +71,11 @@ void TextureReaderWriter::loadTextureFromFile(const std::string& filename,
|
|||
if (extension == "tga") {
|
||||
readTGAPicture(filename, textureToCreate);
|
||||
}
|
||||
#ifdef USE_JPEG_TEXTURE
|
||||
else if (extension == "jpg" || extension == "jpeg"){
|
||||
readJPEGPicture(filename, textureToCreate);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
|
||||
// Display an error message and throw an exception
|
||||
|
@ -84,9 +87,7 @@ void TextureReaderWriter::loadTextureFromFile(const std::string& filename,
|
|||
}
|
||||
|
||||
// Write a texture to a file
|
||||
void TextureReaderWriter::writeTextureToFile(const std::string& filename,
|
||||
const Texture2D& texture)
|
||||
throw(runtime_error, invalid_argument){
|
||||
void TextureReaderWriter::writeTextureToFile(const std::string& filename,const Texture2D& texture) {
|
||||
|
||||
// Get the extension of the file
|
||||
uint startPosExtension = filename.find_last_of(".");
|
||||
|
@ -96,9 +97,11 @@ void TextureReaderWriter::writeTextureToFile(const std::string& filename,
|
|||
if (extension == "tga") {
|
||||
writeTGAPicture(filename, texture);
|
||||
}
|
||||
#ifdef USE_JPEG_TEXTURE
|
||||
else if (extension == "jpg" || extension == "jpeg"){
|
||||
writeJPEGPicture(filename, texture);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
|
||||
// Display an error message and throw an exception
|
||||
|
@ -110,8 +113,7 @@ void TextureReaderWriter::writeTextureToFile(const std::string& filename,
|
|||
}
|
||||
|
||||
// Load a TGA picture
|
||||
void TextureReaderWriter::readTGAPicture(const std::string &filename,
|
||||
Texture2D& textureToCreate) throw(runtime_error) {
|
||||
void TextureReaderWriter::readTGAPicture(const std::string &filename, Texture2D& textureToCreate) {
|
||||
|
||||
// Open the file
|
||||
std::ifstream stream(filename.c_str(), std::ios::binary);
|
||||
|
@ -156,8 +158,7 @@ void TextureReaderWriter::readTGAPicture(const std::string &filename,
|
|||
|
||||
|
||||
// Write a TGA picture
|
||||
void TextureReaderWriter::writeTGAPicture(const std::string& filename,
|
||||
const Texture2D& texture) throw(runtime_error) {
|
||||
void TextureReaderWriter::writeTGAPicture(const std::string& filename, const Texture2D& texture) {
|
||||
assert(texture.getID() != 0);
|
||||
|
||||
// Bind the corresponding texture
|
||||
|
@ -219,9 +220,10 @@ void TextureReaderWriter::writeTGAPicture(const std::string& filename,
|
|||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
#ifdef USE_JPEG_TEXTURE
|
||||
|
||||
// Read a JPEG picture
|
||||
void TextureReaderWriter::readJPEGPicture(const std::string& filename,
|
||||
Texture2D& textureToCreate) throw(std::runtime_error) {
|
||||
void TextureReaderWriter::readJPEGPicture(const std::string& filename, Texture2D& textureToCreate) {
|
||||
|
||||
struct jpeg_decompress_struct info;
|
||||
struct jpeg_error_mgr error;
|
||||
|
@ -276,8 +278,7 @@ void TextureReaderWriter::readJPEGPicture(const std::string& filename,
|
|||
}
|
||||
|
||||
// Write a JPEG picture
|
||||
void TextureReaderWriter::writeJPEGPicture(const std::string& filename,
|
||||
const Texture2D& texture) throw(std::runtime_error) {
|
||||
void TextureReaderWriter::writeJPEGPicture(const std::string& filename, const Texture2D& texture) {
|
||||
|
||||
struct jpeg_compress_struct info;
|
||||
struct jpeg_error_mgr error;
|
||||
|
@ -327,3 +328,5 @@ void TextureReaderWriter::writeJPEGPicture(const std::string& filename,
|
|||
// Free allocated memory
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,34 +52,26 @@ class TextureReaderWriter {
|
|||
TextureReaderWriter();
|
||||
|
||||
// Read a TGA picture
|
||||
static void readTGAPicture(const std::string& filename,
|
||||
Texture2D& textureToCreate) throw(std::runtime_error);
|
||||
static void readTGAPicture(const std::string& filename, Texture2D& textureToCreate);
|
||||
|
||||
// Write a TGA picture
|
||||
static void writeTGAPicture(const std::string& filename,
|
||||
const Texture2D& texture) throw(std::runtime_error);
|
||||
static void writeTGAPicture(const std::string& filename, const Texture2D& texture);
|
||||
|
||||
// Read a JPEG picture
|
||||
static void readJPEGPicture(const std::string& filename,
|
||||
Texture2D& textureToCreate) throw(std::runtime_error);
|
||||
static void readJPEGPicture(const std::string& filename, Texture2D& textureToCreate);
|
||||
|
||||
// Write a JPEG picture
|
||||
static void writeJPEGPicture(const std::string& filename,
|
||||
const Texture2D& texture) throw(std::runtime_error);
|
||||
static void writeJPEGPicture(const std::string& filename, const Texture2D& texture);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
// Load a texture from a file
|
||||
static void loadTextureFromFile(const std::string& filename,
|
||||
Texture2D& textureToCreate)
|
||||
throw(std::runtime_error, std::invalid_argument);
|
||||
static void loadTextureFromFile(const std::string& filename, Texture2D& textureToCreate);
|
||||
|
||||
// Write a texture to a file
|
||||
static void writeTextureToFile(const std::string& filename,
|
||||
const Texture2D& texture)
|
||||
throw(std::runtime_error, std::invalid_argument);
|
||||
static void writeTextureToFile(const std::string& filename, const Texture2D& texture);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ struct Color {
|
|||
// Constructor
|
||||
Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) {}
|
||||
|
||||
// Constructor
|
||||
// Copy-constructor
|
||||
Color(const Color& color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
|
||||
|
||||
// Destructor
|
||||
|
|
|
@ -31,6 +31,7 @@ uniform vec3 light0SpecularColor; // Light 0 specular color
|
|||
uniform float shininess; // Shininess
|
||||
uniform sampler2D texture; // Texture
|
||||
uniform bool isTexture; // True if we need to use the texture
|
||||
uniform vec4 vertexColor; // Vertex color
|
||||
|
||||
// Varying variables
|
||||
varying vec3 vertexPosCameraSpace; // Camera-space position of the vertex
|
||||
|
@ -43,7 +44,7 @@ void main() {
|
|||
vec3 ambient = lightAmbientColor;
|
||||
|
||||
// Get the texture color
|
||||
vec3 textureColor = vec3(1);
|
||||
vec3 textureColor = vertexColor.rgb;
|
||||
if (isTexture) textureColor = texture2D(texture, texCoords).rgb;
|
||||
|
||||
// Compute the surface normal vector
|
||||
|
@ -57,8 +58,8 @@ void main() {
|
|||
// Compute the specular term of light 0
|
||||
vec3 V = normalize(-vertexPosCameraSpace);
|
||||
vec3 H0 = normalize(V + L0);
|
||||
float specularFactor = pow(max(dot(N, H0), 0), shininess);
|
||||
if (diffuseFactor < 0) specularFactor = 0.0;
|
||||
float specularFactor = pow(max(dot(N, H0), 0.0), shininess);
|
||||
if (diffuseFactor < 0.0) specularFactor = 0.0;
|
||||
vec3 specular = light0SpecularColor * specularFactor;
|
||||
|
||||
// Compute the final color
|
||||
|
|
32
examples/cubes/CMakeLists.txt
Normal file
32
examples/cubes/CMakeLists.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Minimum cmake version required
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
# Project configuration
|
||||
PROJECT(Cubes)
|
||||
|
||||
# Where to build the executable
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin/cubes/)
|
||||
|
||||
# Copy the shaders used for the demo into the build directory
|
||||
FILE(COPY "${OPENGLFRAMEWORK_DIR}/src/shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
|
||||
|
||||
# Headers
|
||||
INCLUDE_DIRECTORIES("${OPENGLFRAMEWORK_DIR}/src/" "../common/")
|
||||
|
||||
# Source files
|
||||
SET(CUBES_SOURCES
|
||||
Cubes.cpp
|
||||
Scene.cpp
|
||||
Scene.cpp
|
||||
Scene.h
|
||||
"../common/Box.cpp"
|
||||
"../common/Box.h"
|
||||
"../common/Viewer.cpp"
|
||||
"../common/Viewer.h"
|
||||
)
|
||||
|
||||
# Create the executable
|
||||
ADD_EXECUTABLE(cubes ${CUBES_SOURCES})
|
||||
|
||||
# Link with libraries
|
||||
TARGET_LINK_LIBRARIES(cubes reactphysics3d openglframework)
|
|
@ -51,7 +51,7 @@ int main(int argc, char** argv) {
|
|||
viewer = new Viewer();
|
||||
Vector2 windowsSize = Vector2(800, 600);
|
||||
Vector2 windowsPosition = Vector2(100, 100);
|
||||
bool initOK = viewer->init(argc, argv, "ReactPhysics3D Examples - Falling Cubes", windowsSize, windowsPosition);
|
||||
bool initOK = viewer->init(argc, argv, "ReactPhysics3D Examples - Cubes", windowsSize, windowsPosition);
|
||||
if (!initOK) return 1;
|
||||
|
||||
// Create the scene
|
||||
|
@ -66,7 +66,12 @@ int main(int argc, char** argv) {
|
|||
glutMouseFunc(mouseButton);
|
||||
glutMotionFunc(mouseMotion);
|
||||
glutKeyboardFunc(keyboard);
|
||||
|
||||
#ifdef USE_FREEGLUT
|
||||
glutCloseFunc(finish);
|
||||
#else
|
||||
atexit(finish);
|
||||
#endif
|
||||
|
||||
// Glut main looop
|
||||
glutMainLoop();
|
||||
|
@ -114,7 +119,9 @@ void keyboard(unsigned char key, int x, int y) {
|
|||
|
||||
// Escape key
|
||||
case 27:
|
||||
glutLeaveMainLoop();
|
||||
#ifdef USE_FREEGLUT
|
||||
glutLeaveMainLoop();
|
||||
#endif
|
||||
break;
|
||||
|
||||
// Space bar
|
|
@ -45,7 +45,7 @@ Scene::Scene(GlutViewer* viewer) : mViewer(viewer), mLight0(0),
|
|||
mViewer->setScenePosition(center, radiusScene);
|
||||
|
||||
// Gravity vector in the dynamics world
|
||||
rp3d::Vector3 gravity(0, -9.81, 0);
|
||||
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
|
||||
|
||||
// Time step for the physics simulation
|
||||
rp3d::decimal timeStep = 1.0f / 60.0f;
|
||||
|
@ -65,16 +65,16 @@ Scene::Scene(GlutViewer* viewer) : mViewer(viewer), mLight0(0),
|
|||
float angle = i * 30.0f;
|
||||
openglframework::Vector3 position(radius * cos(angle),
|
||||
1 + i * (BOX_SIZE.y + 0.3f),
|
||||
radius * sin(angle));
|
||||
0);
|
||||
|
||||
// Create a cube and a corresponding rigid in the dynamics world
|
||||
Box* cube = new Box(BOX_SIZE, position , CUBE_MASS, mDynamicsWorld);
|
||||
Box* cube = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld);
|
||||
|
||||
cube->getRigidBody()->setIsMotionEnabled(true);
|
||||
cube->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = cube->getRigidBody()->getMaterial();
|
||||
material.setBounciness(0.4);
|
||||
material.setBounciness(rp3d::decimal(0.4));
|
||||
|
||||
// Add the box the list of box in the scene
|
||||
mBoxes.push_back(cube);
|
||||
|
@ -85,11 +85,11 @@ Scene::Scene(GlutViewer* viewer) : mViewer(viewer), mLight0(0),
|
|||
mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld);
|
||||
|
||||
// The floor must be a non-moving rigid body
|
||||
mFloor->getRigidBody()->setIsMotionEnabled(false);
|
||||
mFloor->getRigidBody()->enableMotion(false);
|
||||
|
||||
// Change the material properties of the floor rigid body
|
||||
rp3d::Material& material = mFloor->getRigidBody()->getMaterial();
|
||||
material.setBounciness(0.3);
|
||||
material.setBounciness(rp3d::decimal(0.3));
|
||||
|
||||
// Start the simulation
|
||||
startSimulation();
|
||||
|
@ -142,6 +142,15 @@ void Scene::simulate() {
|
|||
|
||||
mFloor->updateTransform();
|
||||
|
||||
// Set the color of the awake/sleeping bodies
|
||||
for (uint i=0; i<mBoxes.size(); i++) {
|
||||
if (mBoxes[i]->getRigidBody()->isSleeping()) {
|
||||
mBoxes[i]->setColor(Color(1, 0, 0, 1));
|
||||
}
|
||||
else {
|
||||
mBoxes[i]->setColor(Color(0, 1, 0, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,8 +172,8 @@ void Scene::render() {
|
|||
mPhongShader.setMatrix4x4Uniform("projectionMatrix", camera.getProjectionMatrix());
|
||||
mPhongShader.setVector3Uniform("light0PosCameraSpace",worldToCameraMatrix * mLight0.getOrigin());
|
||||
mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f));
|
||||
Color& diffCol = mLight0.getDiffuseColor();
|
||||
Color& specCol = mLight0.getSpecularColor();
|
||||
const Color& diffCol = mLight0.getDiffuseColor();
|
||||
const Color& specCol = mLight0.getSpecularColor();
|
||||
mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffCol.r, diffCol.g, diffCol.b));
|
||||
mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specCol.r, specCol.g, specCol.b));
|
||||
mPhongShader.setFloatUniform("shininess", 60.0f);
|
|
@ -34,8 +34,8 @@
|
|||
// Constants
|
||||
const int NB_SPHERES = 20; // 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 CUBE_MASS = 1.0f; // Box mass in kilograms
|
||||
const openglframework::Vector3 FLOOR_SIZE(50, 0.5f, 50); // 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
|
|
@ -1,17 +0,0 @@
|
|||
# Minimum cmake version required
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
# Project configuration
|
||||
PROJECT(FallingCubes)
|
||||
|
||||
# Copy the shaders used for the demo into the build directory
|
||||
FILE(COPY "../common/opengl-framework/src/shaders/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/")
|
||||
|
||||
# Headers
|
||||
INCLUDE_DIRECTORIES("../common/opengl-framework/src/" "../common/")
|
||||
|
||||
# Create the example executable using the
|
||||
# compiled reactphysics3d static library
|
||||
ADD_EXECUTABLE(fallingcubes FallingCubes.cpp Scene.cpp Scene.h "../common/Box.cpp" "../common/Box.h" "../common/Viewer.cpp" "../common/Viewer.h")
|
||||
|
||||
TARGET_LINK_LIBRARIES(fallingcubes reactphysics3d openglframework)
|
|
@ -4,14 +4,28 @@ cmake_minimum_required(VERSION 2.6)
|
|||
# Project configuration
|
||||
PROJECT(Joints)
|
||||
|
||||
# Where to build the executable
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin/joints/)
|
||||
|
||||
# Copy the shaders used for the demo into the build directory
|
||||
FILE(COPY "../common/opengl-framework/src/shaders/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/")
|
||||
FILE(COPY "${OPENGLFRAMEWORK_DIR}/src/shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
|
||||
|
||||
# Headers
|
||||
INCLUDE_DIRECTORIES("../common/opengl-framework/src/" "../common/")
|
||||
INCLUDE_DIRECTORIES("${OPENGLFRAMEWORK_DIR}/src/" "../common/")
|
||||
|
||||
# Create the example executable using the
|
||||
# compiled reactphysics3d static library
|
||||
ADD_EXECUTABLE(joints Joints.cpp Scene.cpp Scene.h "../common/Box.cpp" "../common/Box.h" "../common/Viewer.cpp" "../common/Viewer.h")
|
||||
# Source files
|
||||
SET(JOINTS_SOURCES
|
||||
Joints.cpp
|
||||
Scene.cpp
|
||||
Scene.h
|
||||
"../common/Box.cpp"
|
||||
"../common/Box.h"
|
||||
"../common/Viewer.cpp"
|
||||
"../common/Viewer.h"
|
||||
)
|
||||
|
||||
# Create the executable
|
||||
ADD_EXECUTABLE(joints ${JOINTS_SOURCES})
|
||||
|
||||
# Link with libraries
|
||||
TARGET_LINK_LIBRARIES(joints reactphysics3d openglframework)
|
||||
|
|
|
@ -66,7 +66,11 @@ int main(int argc, char** argv) {
|
|||
glutMouseFunc(mouseButton);
|
||||
glutMotionFunc(mouseMotion);
|
||||
glutKeyboardFunc(keyboard);
|
||||
#ifdef USE_FREEGLUT
|
||||
glutCloseFunc(finish);
|
||||
#else
|
||||
atexit(finish);
|
||||
#endif
|
||||
|
||||
// Glut main looop
|
||||
glutMainLoop();
|
||||
|
@ -114,7 +118,9 @@ void keyboard(unsigned char key, int x, int y) {
|
|||
|
||||
// Escape key
|
||||
case 27:
|
||||
glutLeaveMainLoop();
|
||||
#ifdef USE_FREEGLUT
|
||||
glutLeaveMainLoop();
|
||||
#endif
|
||||
break;
|
||||
|
||||
// Space bar
|
||||
|
|
|
@ -34,7 +34,6 @@ using namespace openglframework;
|
|||
Scene::Scene(GlutViewer* viewer) : mViewer(viewer), mLight0(0),
|
||||
mPhongShader("shaders/phong.vert",
|
||||
"shaders/phong.frag"), mIsRunning(false) {
|
||||
|
||||
// Move the light 0
|
||||
mLight0.translateWorld(Vector3(7, 15, 15));
|
||||
|
||||
|
@ -46,7 +45,7 @@ Scene::Scene(GlutViewer* viewer) : mViewer(viewer), mLight0(0),
|
|||
mViewer->setScenePosition(center, radiusScene);
|
||||
|
||||
// Gravity vector in the dynamics world
|
||||
rp3d::Vector3 gravity(0, -9.81, 0);
|
||||
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
|
||||
|
||||
// Time step for the physics simulation
|
||||
rp3d::decimal timeStep = 1.0f / 60.0f;
|
||||
|
@ -128,8 +127,8 @@ void Scene::simulate() {
|
|||
if (mIsRunning) {
|
||||
|
||||
// Update the motor speed of the Slider Joint (to move up and down)
|
||||
long double motorSpeed = 3 * cos(mDynamicsWorld->getPhysicsTime() * 1.5);
|
||||
mSliderJoint->setMotorSpeed(motorSpeed);
|
||||
long double motorSpeed = 2 * cos(mDynamicsWorld->getPhysicsTime() * 1.5);
|
||||
mSliderJoint->setMotorSpeed(rp3d::decimal(motorSpeed));
|
||||
|
||||
// Take a simulation step
|
||||
mDynamicsWorld->update();
|
||||
|
@ -167,8 +166,8 @@ void Scene::render() {
|
|||
mPhongShader.setVector3Uniform("light0PosCameraSpace",worldToCameraMatrix * mLight0.getOrigin());
|
||||
mPhongShader.setMatrix4x4Uniform("projectionMatrix", camera.getProjectionMatrix());
|
||||
mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f));
|
||||
Color& diffCol = mLight0.getDiffuseColor();
|
||||
Color& specCol = mLight0.getSpecularColor();
|
||||
const Color& diffCol = mLight0.getDiffuseColor();
|
||||
const Color& specCol = mLight0.getSpecularColor();
|
||||
mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffCol.r, diffCol.g, diffCol.b));
|
||||
mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specCol.r, specCol.g, specCol.b));
|
||||
mPhongShader.setFloatUniform("shininess", 60.0f);
|
||||
|
@ -206,14 +205,17 @@ void Scene::createBallAndSocketJoints() {
|
|||
mDynamicsWorld);
|
||||
|
||||
// The fist box cannot move
|
||||
if (i == 0) mBallAndSocketJointChainBoxes[i]->getRigidBody()->setIsMotionEnabled(false);
|
||||
else mBallAndSocketJointChainBoxes[i]->getRigidBody()->setIsMotionEnabled(true);
|
||||
if (i == 0) mBallAndSocketJointChainBoxes[i]->getRigidBody()->enableMotion(false);
|
||||
else mBallAndSocketJointChainBoxes[i]->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Add some angular velocity damping
|
||||
mBallAndSocketJointChainBoxes[i]->getRigidBody()->setAngularDamping(rp3d::decimal(0.2));
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = mBallAndSocketJointChainBoxes[i]->getRigidBody()->getMaterial();
|
||||
material.setBounciness(0.4);
|
||||
material.setBounciness(rp3d::decimal(0.4));
|
||||
|
||||
positionBox.y -= boxDimension.y + 0.5;
|
||||
positionBox.y -= boxDimension.y + 0.5f;
|
||||
}
|
||||
|
||||
// --------------- Create the joints --------------- //
|
||||
|
@ -240,34 +242,34 @@ void Scene::createSliderJoint() {
|
|||
// --------------- Create the first box --------------- //
|
||||
|
||||
// Position of the box
|
||||
openglframework::Vector3 positionBox1(0, 2.1, 0);
|
||||
openglframework::Vector3 positionBox1(0, 2.1f, 0);
|
||||
|
||||
// Create a box and a corresponding rigid in the dynamics world
|
||||
openglframework::Vector3 box1Dimension(2, 4, 2);
|
||||
mSliderJointBottomBox = new Box(box1Dimension, positionBox1 , CUBE_MASS, mDynamicsWorld);
|
||||
mSliderJointBottomBox = new Box(box1Dimension, positionBox1 , BOX_MASS, mDynamicsWorld);
|
||||
|
||||
// The fist box cannot move
|
||||
mSliderJointBottomBox->getRigidBody()->setIsMotionEnabled(false);
|
||||
mSliderJointBottomBox->getRigidBody()->enableMotion(false);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material1 = mSliderJointBottomBox->getRigidBody()->getMaterial();
|
||||
material1.setBounciness(0.4);
|
||||
material1.setBounciness(0.4f);
|
||||
|
||||
// --------------- Create the second box --------------- //
|
||||
|
||||
// Position of the box
|
||||
openglframework::Vector3 positionBox2(0, 4.2, 0);
|
||||
openglframework::Vector3 positionBox2(0, 4.2f, 0);
|
||||
|
||||
// Create a box and a corresponding rigid in the dynamics world
|
||||
openglframework::Vector3 box2Dimension(1.5, 4, 1.5);
|
||||
mSliderJointTopBox = new Box(box2Dimension, positionBox2 , CUBE_MASS, mDynamicsWorld);
|
||||
openglframework::Vector3 box2Dimension(1.5f, 4, 1.5f);
|
||||
mSliderJointTopBox = new Box(box2Dimension, positionBox2 , BOX_MASS, mDynamicsWorld);
|
||||
|
||||
// The second box is allowed to move
|
||||
mSliderJointTopBox->getRigidBody()->setIsMotionEnabled(true);
|
||||
mSliderJointTopBox->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material2 = mSliderJointTopBox->getRigidBody()->getMaterial();
|
||||
material2.setBounciness(0.4);
|
||||
material2.setBounciness(0.4f);
|
||||
|
||||
// --------------- Create the joint --------------- //
|
||||
|
||||
|
@ -276,10 +278,10 @@ void Scene::createSliderJoint() {
|
|||
rp3d::RigidBody* body2 = mSliderJointTopBox->getRigidBody();
|
||||
const rp3d::Vector3& body1Position = body1->getTransform().getPosition();
|
||||
const rp3d::Vector3& body2Position = body2->getTransform().getPosition();
|
||||
const rp3d::Vector3 anchorPointWorldSpace = 0.5 * (body2Position + body1Position);
|
||||
const rp3d::Vector3 anchorPointWorldSpace = rp3d::decimal(0.5) * (body2Position + body1Position);
|
||||
const rp3d::Vector3 sliderAxisWorldSpace = (body2Position - body1Position);
|
||||
rp3d::SliderJointInfo jointInfo(body1, body2, anchorPointWorldSpace, sliderAxisWorldSpace,
|
||||
-1.7, 1.7);
|
||||
rp3d::decimal(-1.7), rp3d::decimal(1.7));
|
||||
jointInfo.isMotorEnabled = true;
|
||||
jointInfo.motorSpeed = 0.0;
|
||||
jointInfo.maxMotorForce = 10000.0;
|
||||
|
@ -299,14 +301,14 @@ void Scene::createPropellerHingeJoint() {
|
|||
|
||||
// Create a box and a corresponding rigid in the dynamics world
|
||||
openglframework::Vector3 boxDimension(10, 1, 1);
|
||||
mPropellerBox = new Box(boxDimension, positionBox1 , CUBE_MASS, mDynamicsWorld);
|
||||
mPropellerBox = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld);
|
||||
|
||||
// The fist box cannot move
|
||||
mPropellerBox->getRigidBody()->setIsMotionEnabled(true);
|
||||
mPropellerBox->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = mPropellerBox->getRigidBody()->getMaterial();
|
||||
material.setBounciness(0.4);
|
||||
material.setBounciness(rp3d::decimal(0.4));
|
||||
|
||||
// --------------- Create the Hinge joint --------------- //
|
||||
|
||||
|
@ -319,8 +321,8 @@ void Scene::createPropellerHingeJoint() {
|
|||
const rp3d::Vector3 hingeAxisWorldSpace(0, 1, 0);
|
||||
rp3d::HingeJointInfo jointInfo(body1, body2, anchorPointWorldSpace, hingeAxisWorldSpace);
|
||||
jointInfo.isMotorEnabled = true;
|
||||
jointInfo.motorSpeed = -0.5 * PI;
|
||||
jointInfo.maxMotorTorque = 60.0;
|
||||
jointInfo.motorSpeed = - rp3d::decimal(0.5) * PI;
|
||||
jointInfo.maxMotorTorque = rp3d::decimal(60.0);
|
||||
jointInfo.isCollisionEnabled = false;
|
||||
|
||||
// Create the joint in the dynamics world
|
||||
|
@ -337,14 +339,14 @@ void Scene::createFixedJoints() {
|
|||
|
||||
// Create a box and a corresponding rigid in the dynamics world
|
||||
openglframework::Vector3 boxDimension(1.5, 1.5, 1.5);
|
||||
mFixedJointBox1 = new Box(boxDimension, positionBox1 , CUBE_MASS, mDynamicsWorld);
|
||||
mFixedJointBox1 = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld);
|
||||
|
||||
// The fist box cannot move
|
||||
mFixedJointBox1->getRigidBody()->setIsMotionEnabled(true);
|
||||
mFixedJointBox1->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material1 = mFixedJointBox1->getRigidBody()->getMaterial();
|
||||
material1.setBounciness(0.4);
|
||||
material1.setBounciness(rp3d::decimal(0.4));
|
||||
|
||||
// --------------- Create the second box --------------- //
|
||||
|
||||
|
@ -352,14 +354,14 @@ void Scene::createFixedJoints() {
|
|||
openglframework::Vector3 positionBox2(-5, 7, 0);
|
||||
|
||||
// Create a box and a corresponding rigid in the dynamics world
|
||||
mFixedJointBox2 = new Box(boxDimension, positionBox2 , CUBE_MASS, mDynamicsWorld);
|
||||
mFixedJointBox2 = new Box(boxDimension, positionBox2 , BOX_MASS, mDynamicsWorld);
|
||||
|
||||
// The second box is allowed to move
|
||||
mFixedJointBox2->getRigidBody()->setIsMotionEnabled(true);
|
||||
mFixedJointBox2->getRigidBody()->enableMotion(true);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material2 = mFixedJointBox2->getRigidBody()->getMaterial();
|
||||
material2.setBounciness(0.4);
|
||||
material2.setBounciness(rp3d::decimal(0.4));
|
||||
|
||||
// --------------- Create the first fixed joint --------------- //
|
||||
|
||||
|
@ -394,9 +396,9 @@ void Scene::createFloor() {
|
|||
mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld);
|
||||
|
||||
// The floor must be a non-moving rigid body
|
||||
mFloor->getRigidBody()->setIsMotionEnabled(false);
|
||||
mFloor->getRigidBody()->enableMotion(false);
|
||||
|
||||
// Change the material properties of the rigid body
|
||||
rp3d::Material& material = mFloor->getRigidBody()->getMaterial();
|
||||
material.setBounciness(0.3);
|
||||
material.setBounciness(rp3d::decimal(0.3));
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
// Constants
|
||||
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 CUBE_MASS = 1.0f; // Box mass in kilograms
|
||||
const float BOX_MASS = 1.0f; // Box mass in kilograms
|
||||
const float FLOOR_MASS = 100.0f; // Floor mass in kilograms
|
||||
const int NB_BALLSOCKETJOINT_BOXES = 7; // Number of Ball-And-Socket chain boxes
|
||||
const int NB_HINGE_BOXES = 7; // Number of Hinge chain boxes
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* *
|
||||
********************************************************************************/
|
||||
|
||||
// Libraries
|
||||
// Libraries
|
||||
#include "Body.h"
|
||||
#include "../collision/shapes/CollisionShape.h"
|
||||
|
||||
|
@ -31,7 +31,9 @@
|
|||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
Body::Body(bodyindex id) : mID(id) {
|
||||
Body::Body(bodyindex id)
|
||||
: mID(id), mIsAlreadyInIsland(false), mIsAllowedToSleep(true), mIsActive(true),
|
||||
mIsSleeping(false), mSleepTime(0) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,21 @@ class Body {
|
|||
/// ID of the body
|
||||
bodyindex mID;
|
||||
|
||||
/// True if the body has already been added in an island (for sleeping technique)
|
||||
bool mIsAlreadyInIsland;
|
||||
|
||||
/// True if the body is allowed to go to sleep for better efficiency
|
||||
bool mIsAllowedToSleep;
|
||||
|
||||
/// True if the body is active
|
||||
bool mIsActive;
|
||||
|
||||
/// True if the body is sleeping (for sleeping technique)
|
||||
bool mIsSleeping;
|
||||
|
||||
/// Elapsed time since the body velocity was bellow the sleep velocity
|
||||
decimal mSleepTime;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Private copy-constructor
|
||||
|
@ -68,6 +83,21 @@ class Body {
|
|||
/// Return the id of the body
|
||||
bodyindex getID() const;
|
||||
|
||||
/// Return whether or not the body is allowed to sleep
|
||||
bool isAllowedToSleep() const;
|
||||
|
||||
/// Set whether or not the body is allowed to go to sleep
|
||||
void setIsAllowedToSleep(bool isAllowedToSleep);
|
||||
|
||||
/// Return whether or not the body is sleeping
|
||||
bool isSleeping() const;
|
||||
|
||||
/// Return true if the body is active
|
||||
bool isActive() const;
|
||||
|
||||
/// Set the variable to know whether or not the body is sleeping
|
||||
virtual void setIsSleeping(bool isSleeping);
|
||||
|
||||
/// Smaller than operator
|
||||
bool operator<(const Body& body2) const;
|
||||
|
||||
|
@ -79,6 +109,10 @@ class Body {
|
|||
|
||||
/// Not equal operator
|
||||
bool operator!=(const Body& body2) const;
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class DynamicsWorld;
|
||||
};
|
||||
|
||||
// Return the id of the body
|
||||
|
@ -86,6 +120,43 @@ inline bodyindex Body::getID() const {
|
|||
return mID;
|
||||
}
|
||||
|
||||
// Return whether or not the body is allowed to sleep
|
||||
inline bool Body::isAllowedToSleep() const {
|
||||
return mIsAllowedToSleep;
|
||||
}
|
||||
|
||||
// Set whether or not the body is allowed to go to sleep
|
||||
inline void Body::setIsAllowedToSleep(bool isAllowedToSleep) {
|
||||
mIsAllowedToSleep = isAllowedToSleep;
|
||||
|
||||
if (!mIsAllowedToSleep) setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Return whether or not the body is sleeping
|
||||
inline bool Body::isSleeping() const {
|
||||
return mIsSleeping;
|
||||
}
|
||||
|
||||
// Return true if the body is active
|
||||
inline bool Body::isActive() const {
|
||||
return mIsActive;
|
||||
}
|
||||
|
||||
// Set the variable to know whether or not the body is sleeping
|
||||
inline void Body::setIsSleeping(bool isSleeping) {
|
||||
|
||||
if (isSleeping) {
|
||||
mSleepTime = decimal(0.0);
|
||||
}
|
||||
else {
|
||||
if (mIsSleeping) {
|
||||
mSleepTime = decimal(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
mIsSleeping = isSleeping;
|
||||
}
|
||||
|
||||
// Smaller than operator
|
||||
inline bool Body::operator<(const Body& body2) const {
|
||||
return (mID < body2.mID);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
// Libraries
|
||||
#include "CollisionBody.h"
|
||||
#include "../engine/ContactManifold.h"
|
||||
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace reactphysics3d;
|
||||
|
@ -32,8 +33,8 @@ using namespace reactphysics3d;
|
|||
// Constructor
|
||||
CollisionBody::CollisionBody(const Transform& transform, CollisionShape *collisionShape,
|
||||
bodyindex id)
|
||||
: Body(id), mCollisionShape(collisionShape), mTransform(transform),
|
||||
mIsActive(true), mHasMoved(false) {
|
||||
: Body(id), mCollisionShape(collisionShape), mTransform(transform),
|
||||
mHasMoved(false), mContactManifoldsList(NULL) {
|
||||
|
||||
assert(collisionShape);
|
||||
|
||||
|
@ -50,5 +51,24 @@ CollisionBody::CollisionBody(const Transform& transform, CollisionShape *collisi
|
|||
|
||||
// Destructor
|
||||
CollisionBody::~CollisionBody() {
|
||||
|
||||
assert(mContactManifoldsList == NULL);
|
||||
}
|
||||
|
||||
// Reset the contact manifold lists
|
||||
void CollisionBody::resetContactManifoldsList(MemoryAllocator& memoryAllocator) {
|
||||
|
||||
// Delete the linked list of contact manifolds of that body
|
||||
ContactManifoldListElement* currentElement = mContactManifoldsList;
|
||||
while (currentElement != NULL) {
|
||||
ContactManifoldListElement* nextElement = currentElement->next;
|
||||
|
||||
// Delete the current element
|
||||
currentElement->ContactManifoldListElement::~ContactManifoldListElement();
|
||||
memoryAllocator.release(currentElement, sizeof(ContactManifoldListElement));
|
||||
|
||||
currentElement = nextElement;
|
||||
}
|
||||
mContactManifoldsList = NULL;
|
||||
|
||||
assert(mContactManifoldsList == NULL);
|
||||
}
|
||||
|
|
|
@ -33,11 +33,15 @@
|
|||
#include "../mathematics/Transform.h"
|
||||
#include "../collision/shapes/AABB.h"
|
||||
#include "../collision/shapes/CollisionShape.h"
|
||||
#include "../memory/MemoryAllocator.h"
|
||||
#include "../configuration.h"
|
||||
|
||||
/// Namespace reactphysics3d
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class declarations
|
||||
struct ContactManifoldListElement;
|
||||
|
||||
// Class CollisionBody
|
||||
/**
|
||||
* This class represents a body that is able to collide with others
|
||||
|
@ -61,9 +65,6 @@ class CollisionBody : public Body {
|
|||
/// Interpolation factor used for the state interpolation
|
||||
decimal mInterpolationFactor;
|
||||
|
||||
/// True if the body is active (not sleeping)
|
||||
bool mIsActive;
|
||||
|
||||
/// True if the body is able to move
|
||||
bool mIsMotionEnabled;
|
||||
|
||||
|
@ -76,6 +77,9 @@ class CollisionBody : public Body {
|
|||
/// True if the body has moved during the last frame
|
||||
bool mHasMoved;
|
||||
|
||||
/// First element of the linked list of contact manifolds involving this body
|
||||
ContactManifoldListElement* mContactManifoldsList;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Private copy-constructor
|
||||
|
@ -84,6 +88,15 @@ class CollisionBody : public Body {
|
|||
/// Private assignment operator
|
||||
CollisionBody& operator=(const CollisionBody& body);
|
||||
|
||||
/// Reset the contact manifold lists
|
||||
void resetContactManifoldsList(MemoryAllocator& memoryAllocator);
|
||||
|
||||
/// Update the old transform with the current one.
|
||||
void updateOldTransform();
|
||||
|
||||
/// Update the Axis-Aligned Bounding Box coordinates
|
||||
void updateAABB();
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -94,24 +107,12 @@ class CollisionBody : public Body {
|
|||
/// Destructor
|
||||
virtual ~CollisionBody();
|
||||
|
||||
/// Return true if the body has moved during the last frame
|
||||
bool getHasMoved() const;
|
||||
|
||||
/// Set the hasMoved variable (true if the body has moved during the last frame)
|
||||
void setHasMoved(bool hasMoved);
|
||||
|
||||
/// Return the collision shape
|
||||
CollisionShape* getCollisionShape() const;
|
||||
|
||||
/// Set the collision shape
|
||||
void setCollisionShape(CollisionShape* collisionShape);
|
||||
|
||||
/// Return true for an active body
|
||||
bool getIsActive() const;
|
||||
|
||||
/// Set the isActive variable
|
||||
void setIsActive(bool isActive);
|
||||
|
||||
/// Return the current position and orientation
|
||||
const Transform& getTransform() const;
|
||||
|
||||
|
@ -127,35 +128,27 @@ class CollisionBody : public Body {
|
|||
/// Set the interpolation factor of the body
|
||||
void setInterpolationFactor(decimal factor);
|
||||
|
||||
/// Return if the rigid body can move
|
||||
bool getIsMotionEnabled() const;
|
||||
/// Return true if the rigid body is allowed to move
|
||||
bool isMotionEnabled() const;
|
||||
|
||||
/// Set the value to true if the body can move
|
||||
void setIsMotionEnabled(bool isMotionEnabled);
|
||||
/// Enable/disable the motion of the body
|
||||
void enableMotion(bool isMotionEnabled);
|
||||
|
||||
/// Return true if the body can collide with others bodies
|
||||
bool getIsCollisionEnabled() const;
|
||||
bool isCollisionEnabled() const;
|
||||
|
||||
/// Set the isCollisionEnabled value
|
||||
void setIsCollisionEnabled(bool isCollisionEnabled);
|
||||
/// Enable/disable the collision with this body
|
||||
void enableCollision(bool isCollisionEnabled);
|
||||
|
||||
/// Update the old transform with the current one.
|
||||
void updateOldTransform();
|
||||
/// Return the first element of the linked list of contact manifolds involving this body
|
||||
const ContactManifoldListElement* getContactManifoldsLists() const;
|
||||
|
||||
/// Update the Axis-Aligned Bounding Box coordinates
|
||||
void updateAABB();
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class DynamicsWorld;
|
||||
friend class CollisionDetection;
|
||||
};
|
||||
|
||||
// Return true if the body has moved during the last frame
|
||||
inline bool CollisionBody::getHasMoved() const {
|
||||
return mHasMoved;
|
||||
}
|
||||
|
||||
// Set the hasMoved variable (true if the body has moved during the last frame)
|
||||
inline void CollisionBody::setHasMoved(bool hasMoved) {
|
||||
mHasMoved = hasMoved;
|
||||
}
|
||||
|
||||
// Return the collision shape
|
||||
inline CollisionShape* CollisionBody::getCollisionShape() const {
|
||||
assert(mCollisionShape);
|
||||
|
@ -168,16 +161,6 @@ inline void CollisionBody::setCollisionShape(CollisionShape* collisionShape) {
|
|||
mCollisionShape = collisionShape;
|
||||
}
|
||||
|
||||
// Return true if the body is active
|
||||
inline bool CollisionBody::getIsActive() const {
|
||||
return mIsActive;
|
||||
}
|
||||
|
||||
// Set the isActive variable
|
||||
inline void CollisionBody::setIsActive(bool isActive) {
|
||||
mIsActive = isActive;
|
||||
}
|
||||
|
||||
// Return the interpolated transform for rendering
|
||||
inline Transform CollisionBody::getInterpolatedTransform() const {
|
||||
return Transform::interpolateTransforms(mOldTransform, mTransform, mInterpolationFactor);
|
||||
|
@ -189,13 +172,13 @@ inline void CollisionBody::setInterpolationFactor(decimal factor) {
|
|||
mInterpolationFactor = factor;
|
||||
}
|
||||
|
||||
// Return if the rigid body can move
|
||||
inline bool CollisionBody::getIsMotionEnabled() const {
|
||||
// Return true if the rigid body is allowed to move
|
||||
inline bool CollisionBody::isMotionEnabled() const {
|
||||
return mIsMotionEnabled;
|
||||
}
|
||||
|
||||
// Set the value to true if the body can move
|
||||
inline void CollisionBody::setIsMotionEnabled(bool isMotionEnabled) {
|
||||
// Enable/disable the motion of the body
|
||||
inline void CollisionBody::enableMotion(bool isMotionEnabled) {
|
||||
mIsMotionEnabled = isMotionEnabled;
|
||||
}
|
||||
|
||||
|
@ -221,12 +204,12 @@ inline const AABB& CollisionBody::getAABB() const {
|
|||
}
|
||||
|
||||
// Return true if the body can collide with others bodies
|
||||
inline bool CollisionBody::getIsCollisionEnabled() const {
|
||||
inline bool CollisionBody::isCollisionEnabled() const {
|
||||
return mIsCollisionEnabled;
|
||||
}
|
||||
|
||||
// Set the isCollisionEnabled value
|
||||
inline void CollisionBody::setIsCollisionEnabled(bool isCollisionEnabled) {
|
||||
// Enable/disable the collision with this body
|
||||
inline void CollisionBody::enableCollision(bool isCollisionEnabled) {
|
||||
mIsCollisionEnabled = isCollisionEnabled;
|
||||
}
|
||||
|
||||
|
@ -243,6 +226,11 @@ inline void CollisionBody::updateAABB() {
|
|||
mCollisionShape->updateAABB(mAabb, mTransform);
|
||||
}
|
||||
|
||||
// Return the first element of the linked list of contact manifolds involving this body
|
||||
inline const ContactManifoldListElement* CollisionBody::getContactManifoldsLists() const {
|
||||
return mContactManifoldsList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,23 +25,54 @@
|
|||
|
||||
// Libraries
|
||||
#include "RigidBody.h"
|
||||
#include "constraint/Joint.h"
|
||||
#include "../collision/shapes/CollisionShape.h"
|
||||
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
RigidBody::RigidBody(const Transform& transform, decimal mass, const Matrix3x3& inertiaTensorLocal,
|
||||
// Constructor
|
||||
RigidBody::RigidBody(const Transform& transform, decimal mass, const Matrix3x3& inertiaTensorLocal,
|
||||
CollisionShape *collisionShape, bodyindex id)
|
||||
: CollisionBody(transform, collisionShape, id), mInertiaTensorLocal(inertiaTensorLocal),
|
||||
mMass(mass), mInertiaTensorLocalInverse(inertiaTensorLocal.getInverse()),
|
||||
mMassInverse(decimal(1.0) / mass), mIsGravityEnabled(true) {
|
||||
mMassInverse(decimal(1.0) / mass), mIsGravityEnabled(true),
|
||||
mLinearDamping(decimal(0.0)), mAngularDamping(decimal(0.0)), mJointsList(NULL) {
|
||||
|
||||
assert(collisionShape);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
RigidBody::~RigidBody() {
|
||||
|
||||
assert(mJointsList == NULL);
|
||||
}
|
||||
|
||||
// Remove a joint from the joints list
|
||||
void RigidBody::removeJointFromJointsList(MemoryAllocator& memoryAllocator, const Joint* joint) {
|
||||
|
||||
assert(joint != NULL);
|
||||
assert(mJointsList != NULL);
|
||||
|
||||
// Remove the joint from the linked list of the joints of the first body
|
||||
if (mJointsList->joint == joint) { // If the first element is the one to remove
|
||||
JointListElement* elementToRemove = mJointsList;
|
||||
mJointsList = elementToRemove->next;
|
||||
elementToRemove->JointListElement::~JointListElement();
|
||||
memoryAllocator.release(elementToRemove, sizeof(JointListElement));
|
||||
}
|
||||
else { // If the element to remove is not the first one in the list
|
||||
JointListElement* currentElement = mJointsList;
|
||||
while (currentElement->next != NULL) {
|
||||
if (currentElement->next->joint == joint) {
|
||||
JointListElement* elementToRemove = currentElement->next;
|
||||
currentElement->next = elementToRemove->next;
|
||||
elementToRemove->JointListElement::~JointListElement();
|
||||
memoryAllocator.release(elementToRemove, sizeof(JointListElement));
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,10 +31,15 @@
|
|||
#include "CollisionBody.h"
|
||||
#include "../engine/Material.h"
|
||||
#include "../mathematics/mathematics.h"
|
||||
#include "../memory/MemoryAllocator.h"
|
||||
|
||||
/// Namespace reactphysics3d
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class declarations
|
||||
struct JointListElement;
|
||||
class Joint;
|
||||
|
||||
// Class RigidBody
|
||||
/**
|
||||
* This class represents a rigid body of the physics
|
||||
|
@ -80,6 +85,15 @@ class RigidBody : public CollisionBody {
|
|||
/// Material properties of the rigid body
|
||||
Material mMaterial;
|
||||
|
||||
/// Linear velocity damping factor
|
||||
decimal mLinearDamping;
|
||||
|
||||
/// Angular velocity damping factor
|
||||
decimal mAngularDamping;
|
||||
|
||||
/// First element of the linked list of joints involving this body
|
||||
JointListElement* mJointsList;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Private copy-constructor
|
||||
|
@ -88,6 +102,12 @@ class RigidBody : public CollisionBody {
|
|||
/// Private assignment operator
|
||||
RigidBody& operator=(const RigidBody& body);
|
||||
|
||||
/// Remove a joint from the joints list
|
||||
void removeJointFromJointsList(MemoryAllocator& memoryAllocator, const Joint* joint);
|
||||
|
||||
/// Set the inverse of the mass
|
||||
void setMassInverse(decimal massInverse);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -117,21 +137,6 @@ class RigidBody : public CollisionBody {
|
|||
/// Set the angular velocity
|
||||
void setAngularVelocity(const Vector3& angularVelocity);
|
||||
|
||||
/// Set the inverse of the mass
|
||||
void setMassInverse(decimal massInverse);
|
||||
|
||||
/// Return the current external force of the body
|
||||
Vector3 getExternalForce() const;
|
||||
|
||||
/// Set the current external force on the body
|
||||
void setExternalForce(const Vector3& force);
|
||||
|
||||
/// Return the current external torque of the body
|
||||
Vector3 getExternalTorque() const;
|
||||
|
||||
/// Set the current external torque of the body
|
||||
void setExternalTorque(const Vector3& torque);
|
||||
|
||||
/// Return the inverse of the mass of the body
|
||||
decimal getMassInverse() const;
|
||||
|
||||
|
@ -161,6 +166,37 @@ class RigidBody : public CollisionBody {
|
|||
|
||||
/// Set a new material for this rigid body
|
||||
void setMaterial(const Material& material);
|
||||
|
||||
/// Return the linear velocity damping factor
|
||||
decimal getLinearDamping() const;
|
||||
|
||||
/// Set the linear damping factor
|
||||
void setLinearDamping(decimal linearDamping);
|
||||
|
||||
/// Return the angular velocity damping factor
|
||||
decimal getAngularDamping() const;
|
||||
|
||||
/// Set the angular damping factor
|
||||
void setAngularDamping(decimal angularDamping);
|
||||
|
||||
/// Return the first element of the linked list of joints involving this body
|
||||
const JointListElement* getJointsList() const;
|
||||
|
||||
/// Set the variable to know whether or not the body is sleeping
|
||||
virtual void setIsSleeping(bool isSleeping);
|
||||
|
||||
/// Apply an external force to the body at its gravity center.
|
||||
void applyForceToCenter(const Vector3& force);
|
||||
|
||||
/// Apply an external force to the body at a given point (in world-coordinates).
|
||||
void applyForce(const Vector3& force, const Vector3& point);
|
||||
|
||||
/// Apply an external torque to the body.
|
||||
void applyTorque(const Vector3& torque);
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class DynamicsWorld;
|
||||
};
|
||||
|
||||
// Method that return the mass of the body
|
||||
|
@ -197,26 +233,6 @@ inline Matrix3x3 RigidBody::getInertiaTensorLocalInverse() const {
|
|||
return mInertiaTensorLocalInverse;
|
||||
}
|
||||
|
||||
// Return the external force on the body
|
||||
inline Vector3 RigidBody::getExternalForce() const {
|
||||
return mExternalForce;
|
||||
}
|
||||
|
||||
// Set the external force on the body
|
||||
inline void RigidBody::setExternalForce(const Vector3& force) {
|
||||
mExternalForce = force;
|
||||
}
|
||||
|
||||
// Return the current external torque on the body
|
||||
inline Vector3 RigidBody::getExternalTorque() const {
|
||||
return mExternalTorque;
|
||||
}
|
||||
|
||||
// Set the current external torque on the body
|
||||
inline void RigidBody::setExternalTorque(const Vector3& torque) {
|
||||
mExternalTorque = torque;
|
||||
}
|
||||
|
||||
// Return the inverse of the mass of the body
|
||||
inline decimal RigidBody::getMassInverse() const {
|
||||
return mMassInverse;
|
||||
|
@ -288,6 +304,102 @@ inline void RigidBody::setMaterial(const Material& material) {
|
|||
mMaterial = material;
|
||||
}
|
||||
|
||||
// Return the linear velocity damping factor
|
||||
inline decimal RigidBody::getLinearDamping() const {
|
||||
return mLinearDamping;
|
||||
}
|
||||
|
||||
// Set the linear damping factor
|
||||
inline void RigidBody::setLinearDamping(decimal linearDamping) {
|
||||
assert(linearDamping >= decimal(0.0));
|
||||
mLinearDamping = linearDamping;
|
||||
}
|
||||
|
||||
// Return the angular velocity damping factor
|
||||
inline decimal RigidBody::getAngularDamping() const {
|
||||
return mAngularDamping;
|
||||
}
|
||||
|
||||
// Set the angular damping factor
|
||||
inline void RigidBody::setAngularDamping(decimal angularDamping) {
|
||||
assert(angularDamping >= decimal(0.0));
|
||||
mAngularDamping = angularDamping;
|
||||
}
|
||||
|
||||
// Return the first element of the linked list of joints involving this body
|
||||
inline const JointListElement* RigidBody::getJointsList() const {
|
||||
return mJointsList;
|
||||
}
|
||||
|
||||
// Set the variable to know whether or not the body is sleeping
|
||||
inline void RigidBody::setIsSleeping(bool isSleeping) {
|
||||
|
||||
if (isSleeping) {
|
||||
mLinearVelocity.setToZero();
|
||||
mAngularVelocity.setToZero();
|
||||
mExternalForce.setToZero();
|
||||
mExternalTorque.setToZero();
|
||||
}
|
||||
|
||||
Body::setIsSleeping(isSleeping);
|
||||
}
|
||||
|
||||
// Apply an external force to the body at its gravity center.
|
||||
/// If the body is sleeping, calling this method will wake it up. Note that the
|
||||
/// force will we added to the sum of the applied forces and that this sum will be
|
||||
/// reset to zero at the end of each call of the DynamicsWorld::update() method.
|
||||
inline void RigidBody::applyForceToCenter(const Vector3& force) {
|
||||
// If it is a static body, do not apply any force
|
||||
if (!mIsMotionEnabled) return;
|
||||
|
||||
// Awake the body if it was sleeping
|
||||
if (mIsSleeping) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Add the force
|
||||
mExternalForce += force;
|
||||
}
|
||||
|
||||
// Apply an external force to the body at a given point (in world-coordinates).
|
||||
/// If the point is not at the center of gravity of the body, it will also
|
||||
/// generate some torque and therefore, change the angular velocity of the body.
|
||||
/// If the body is sleeping, calling this method will wake it up. Note that the
|
||||
/// force will we added to the sum of the applied forces and that this sum will be
|
||||
/// reset to zero at the end of each call of the DynamicsWorld::update() method.
|
||||
inline void RigidBody::applyForce(const Vector3& force, const Vector3& point) {
|
||||
|
||||
// If it is a static body, do not apply any force
|
||||
if (!mIsMotionEnabled) return;
|
||||
|
||||
// Awake the body if it was sleeping
|
||||
if (mIsSleeping) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Add the force and torque
|
||||
mExternalForce += force;
|
||||
mExternalTorque += (point - mTransform.getPosition()).cross(force);
|
||||
}
|
||||
|
||||
// Apply an external torque to the body.
|
||||
/// If the body is sleeping, calling this method will wake it up. Note that the
|
||||
/// force will we added to the sum of the applied torques and that this sum will be
|
||||
/// reset to zero at the end of each call of the DynamicsWorld::update() method.
|
||||
inline void RigidBody::applyTorque(const Vector3& torque) {
|
||||
|
||||
// If it is a static body, do not apply any force
|
||||
if (!mIsMotionEnabled) return;
|
||||
|
||||
// Awake the body if it was sleeping
|
||||
if (mIsSleeping) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Add the torque
|
||||
mExternalTorque += torque;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -82,7 +82,7 @@ void CollisionDetection::computeBroadPhase() {
|
|||
it != mWorld->getBodiesEndIterator(); it++) {
|
||||
|
||||
// If the body has moved
|
||||
if ((*it)->getHasMoved()) {
|
||||
if ((*it)->mHasMoved) {
|
||||
|
||||
// Notify the broad-phase that the body has moved
|
||||
mBroadPhaseAlgorithm->updateObject(*it, (*it)->getAABB());
|
||||
|
@ -112,6 +112,9 @@ void CollisionDetection::computeNarrowPhase() {
|
|||
|
||||
// Check if the two bodies are allowed to collide, otherwise, we do not test for collision
|
||||
if (mNoCollisionPairs.count(pair->getBodiesIndexPair()) > 0) continue;
|
||||
|
||||
// Check if the two bodies are sleeping, if so, we do no test collision between them
|
||||
if (body1->isSleeping() && body2->isSleeping()) continue;
|
||||
|
||||
// Select the narrow phase algorithm to use according to the two collision shapes
|
||||
NarrowPhaseAlgorithm& narrowPhaseAlgorithm = SelectNarrowPhaseAlgorithm(
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <iostream> // TODO : Delete this
|
||||
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
// Libraries
|
||||
#include <cassert>
|
||||
#include <typeinfo>
|
||||
#include "../../mathematics/Vector3.h"
|
||||
#include "../../mathematics/Matrix3x3.h"
|
||||
#include "AABB.h"
|
||||
|
|
|
@ -57,7 +57,7 @@ class CylinderShape : public CollisionShape {
|
|||
/// Radius of the base
|
||||
decimal mRadius;
|
||||
|
||||
/// Half height of the cone
|
||||
/// Half height of the cylinder
|
||||
decimal mHalfHeight;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
|
|
@ -92,8 +92,8 @@ const decimal DEFAULT_FRICTION_COEFFICIENT = decimal(0.3);
|
|||
/// Default bounciness factor for a rigid body
|
||||
const decimal DEFAULT_BOUNCINESS = decimal(0.5);
|
||||
|
||||
/// True if the deactivation (sleeping) of inactive bodies is enabled
|
||||
const bool DEACTIVATION_ENABLED = true;
|
||||
/// True if the spleeping technique is enabled
|
||||
const bool SPLEEPING_ENABLED = true;
|
||||
|
||||
/// Object margin for collision detection in meters (for the GJK-EPA Algorithm)
|
||||
const decimal OBJECT_MARGIN = decimal(0.04);
|
||||
|
@ -105,11 +105,22 @@ const decimal PERSISTENT_CONTACT_DIST_THRESHOLD = decimal(0.03);
|
|||
const decimal RESTITUTION_VELOCITY_THRESHOLD = decimal(1.0);
|
||||
|
||||
/// Number of iterations when solving the velocity constraints of the Sequential Impulse technique
|
||||
const uint DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS = 15;
|
||||
const uint DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS = 10;
|
||||
|
||||
/// Number of iterations when solving the position constraints of the Sequential Impulse technique
|
||||
const uint DEFAULT_POSITION_SOLVER_NB_ITERATIONS = 5;
|
||||
|
||||
/// Time (in seconds) that a body must stay still to be considered sleeping
|
||||
const float DEFAULT_TIME_BEFORE_SLEEP = 1.0f;
|
||||
|
||||
/// A body with a linear velocity smaller than the sleep linear velocity (in m/s)
|
||||
/// might enter sleeping mode.
|
||||
const decimal DEFAULT_SLEEP_LINEAR_VELOCITY = decimal(0.02);
|
||||
|
||||
/// A body with angular velocity smaller than the sleep angular velocity (in rad/s)
|
||||
/// might enter sleeping mode
|
||||
const decimal DEFAULT_SLEEP_ANGULAR_VELOCITY = decimal(3.0 * (PI / 180.0));
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,7 @@ const decimal BallAndSocketJoint::BETA = decimal(0.2);
|
|||
|
||||
// Constructor
|
||||
BallAndSocketJoint::BallAndSocketJoint(const BallAndSocketJointInfo& jointInfo)
|
||||
: Constraint(jointInfo), mImpulse(Vector3(0, 0, 0)) {
|
||||
: Joint(jointInfo), mImpulse(Vector3(0, 0, 0)) {
|
||||
|
||||
// Compute the local-space anchor point for each body
|
||||
mLocalAnchorPointBody1 = mBody1->getTransform().getInverse() * jointInfo.anchorPointWorldSpace;
|
||||
|
@ -73,25 +73,25 @@ void BallAndSocketJoint::initBeforeSolve(const ConstraintSolverData& constraintS
|
|||
|
||||
// Compute the matrix K=JM^-1J^t (3x3 matrix)
|
||||
decimal inverseMassBodies = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody1->getMassInverse();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody2->getMassInverse();
|
||||
}
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU1 * mI1 * skewSymmetricMatrixU1.getTranspose();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU2 * mI2 * skewSymmetricMatrixU2.getTranspose();
|
||||
}
|
||||
|
||||
// Compute the inverse mass matrix K^-1
|
||||
mInverseMassMatrix.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrix = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ void BallAndSocketJoint::warmstart(const ConstraintSolverData& constraintSolverD
|
|||
const decimal inverseMassBody1 = mBody1->getMassInverse();
|
||||
const decimal inverseMassBody2 = mBody2->getMassInverse();
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 linearImpulseBody1 = -mImpulse;
|
||||
|
@ -133,7 +133,7 @@ void BallAndSocketJoint::warmstart(const ConstraintSolverData& constraintSolverD
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 linearImpulseBody2 = mImpulse;
|
||||
|
@ -165,7 +165,7 @@ void BallAndSocketJoint::solveVelocityConstraint(const ConstraintSolverData& con
|
|||
const Vector3 deltaLambda = mInverseMassMatrix * (-Jv - mBiasVector);
|
||||
mImpulse += deltaLambda;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 linearImpulseBody1 = -deltaLambda;
|
||||
|
@ -175,7 +175,7 @@ void BallAndSocketJoint::solveVelocityConstraint(const ConstraintSolverData& con
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 linearImpulseBody2 = deltaLambda;
|
||||
|
@ -218,23 +218,23 @@ void BallAndSocketJoint::solvePositionConstraint(const ConstraintSolverData& con
|
|||
|
||||
// Recompute the inverse mass matrix K=J^TM^-1J of of the 3 translation constraints
|
||||
decimal inverseMassBodies = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
inverseMassBodies += inverseMassBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
inverseMassBodies += inverseMassBody2;
|
||||
}
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU1 * mI1 * skewSymmetricMatrixU1.getTranspose();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU2 * mI2 * skewSymmetricMatrixU2.getTranspose();
|
||||
}
|
||||
mInverseMassMatrix.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrix = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ void BallAndSocketJoint::solvePositionConstraint(const ConstraintSolverData& con
|
|||
const Vector3 lambda = mInverseMassMatrix * (-constraintError);
|
||||
|
||||
// Apply the impulse to the bodies of the joint (directly update the position/orientation)
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse
|
||||
const Vector3 linearImpulseBody1 = -lambda;
|
||||
|
@ -262,7 +262,7 @@ void BallAndSocketJoint::solvePositionConstraint(const ConstraintSolverData& con
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse
|
||||
const Vector3 linearImpulseBody2 = lambda;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define REACTPHYSICS3D_BALL_AND_SOCKET_JOINT_H
|
||||
|
||||
// Libraries
|
||||
#include "Constraint.h"
|
||||
#include "Joint.h"
|
||||
#include "../mathematics/mathematics.h"
|
||||
|
||||
namespace reactphysics3d {
|
||||
|
@ -37,7 +37,7 @@ namespace reactphysics3d {
|
|||
* This structure is used to gather the information needed to create a ball-and-socket
|
||||
* joint. This structure will be used to create the actual ball-and-socket joint.
|
||||
*/
|
||||
struct BallAndSocketJointInfo : public ConstraintInfo {
|
||||
struct BallAndSocketJointInfo : public JointInfo {
|
||||
|
||||
public :
|
||||
|
||||
|
@ -49,16 +49,17 @@ struct BallAndSocketJointInfo : public ConstraintInfo {
|
|||
/// Constructor
|
||||
BallAndSocketJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace)
|
||||
: ConstraintInfo(rigidBody1, rigidBody2, BALLSOCKETJOINT),
|
||||
: JointInfo(rigidBody1, rigidBody2, BALLSOCKETJOINT),
|
||||
anchorPointWorldSpace(initAnchorPointWorldSpace) {}
|
||||
};
|
||||
|
||||
// Class BallAndSocketJoint
|
||||
/**
|
||||
* This class represents a ball-and-socket joint that allows arbitrary rotation
|
||||
* between two bodies.
|
||||
* between two bodies. This joint has three degrees of freedom. It can be used to
|
||||
* create a chain of bodies for instance.
|
||||
*/
|
||||
class BallAndSocketJoint : public Constraint {
|
||||
class BallAndSocketJoint : public Joint {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -104,16 +105,6 @@ class BallAndSocketJoint : public Constraint {
|
|||
/// Private assignment operator
|
||||
BallAndSocketJoint& operator=(const BallAndSocketJoint& constraint);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
BallAndSocketJoint(const BallAndSocketJointInfo& jointInfo);
|
||||
|
||||
/// Destructor
|
||||
virtual ~BallAndSocketJoint();
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
|
@ -128,6 +119,16 @@ class BallAndSocketJoint : public Constraint {
|
|||
|
||||
/// Solve the position constraint (for position error correction)
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
BallAndSocketJoint(const BallAndSocketJointInfo& jointInfo);
|
||||
|
||||
/// Destructor
|
||||
virtual ~BallAndSocketJoint();
|
||||
};
|
||||
|
||||
// Return the number of bytes used by the joint
|
||||
|
|
|
@ -31,7 +31,8 @@ using namespace std;
|
|||
|
||||
// Constructor
|
||||
ContactPoint::ContactPoint(const ContactPointInfo& contactInfo)
|
||||
: Constraint(contactInfo), mNormal(contactInfo.normal),
|
||||
: mBody1(contactInfo.body1), mBody2(contactInfo.body2),
|
||||
mNormal(contactInfo.normal),
|
||||
mPenetrationDepth(contactInfo.penetrationDepth),
|
||||
mLocalPointOnBody1(contactInfo.localPoint1),
|
||||
mLocalPointOnBody2(contactInfo.localPoint2),
|
||||
|
@ -50,23 +51,3 @@ ContactPoint::ContactPoint(const ContactPointInfo& contactInfo)
|
|||
ContactPoint::~ContactPoint() {
|
||||
|
||||
}
|
||||
|
||||
// Initialize before solving the constraint
|
||||
void ContactPoint::initBeforeSolve(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
}
|
||||
|
||||
// Warm start the constraint (apply the previous impulse at the beginning of the step)
|
||||
void ContactPoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
}
|
||||
|
||||
// Solve the velocity constraint
|
||||
void ContactPoint::solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
}
|
||||
|
||||
// Solve the position constraint
|
||||
void ContactPoint::solvePositionConstraint(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#define REACTPHYSICS3D_CONTACT_POINT_H
|
||||
|
||||
// Libraries
|
||||
#include "Constraint.h"
|
||||
#include "../body/RigidBody.h"
|
||||
#include "../configuration.h"
|
||||
#include "../mathematics/mathematics.h"
|
||||
|
@ -43,7 +42,7 @@ namespace reactphysics3d {
|
|||
* informations are used to compute the contact set for a contact
|
||||
* between two bodies.
|
||||
*/
|
||||
struct ContactPointInfo : public ConstraintInfo {
|
||||
struct ContactPointInfo {
|
||||
|
||||
private:
|
||||
|
||||
|
@ -59,6 +58,12 @@ struct ContactPointInfo : public ConstraintInfo {
|
|||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// First rigid body of the constraint
|
||||
RigidBody* body1;
|
||||
|
||||
/// Second rigid body of the constraint
|
||||
RigidBody* body2;
|
||||
|
||||
/// Normal vector the the collision contact in world space
|
||||
const Vector3 normal;
|
||||
|
||||
|
@ -76,7 +81,7 @@ struct ContactPointInfo : public ConstraintInfo {
|
|||
/// Constructor
|
||||
ContactPointInfo(const Vector3& normal, decimal penetrationDepth,
|
||||
const Vector3& localPoint1, const Vector3& localPoint2)
|
||||
: ConstraintInfo(CONTACT), normal(normal), penetrationDepth(penetrationDepth),
|
||||
: normal(normal), penetrationDepth(penetrationDepth),
|
||||
localPoint1(localPoint1), localPoint2(localPoint2) {
|
||||
|
||||
}
|
||||
|
@ -85,15 +90,20 @@ struct ContactPointInfo : public ConstraintInfo {
|
|||
// Class ContactPoint
|
||||
/**
|
||||
* This class represents a collision contact point between two
|
||||
* bodies in the physics engine. The ContactPoint class inherits from
|
||||
* the Constraint class.
|
||||
* bodies in the physics engine.
|
||||
*/
|
||||
class ContactPoint : public Constraint {
|
||||
class ContactPoint {
|
||||
|
||||
protected :
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// First rigid body of the contact
|
||||
RigidBody* mBody1;
|
||||
|
||||
/// Second rigid body of the contact
|
||||
RigidBody* mBody2;
|
||||
|
||||
/// Normal vector of the contact (From body1 toward body2) in world space
|
||||
const Vector3 mNormal;
|
||||
|
||||
|
@ -143,7 +153,13 @@ class ContactPoint : public Constraint {
|
|||
ContactPoint(const ContactPointInfo& contactInfo);
|
||||
|
||||
/// Destructor
|
||||
virtual ~ContactPoint();
|
||||
~ContactPoint();
|
||||
|
||||
/// Return the reference to the body 1
|
||||
RigidBody* const getBody1() const;
|
||||
|
||||
/// Return the reference to the body 2
|
||||
RigidBody* const getBody2() const;
|
||||
|
||||
/// Return the normal vector of the contact
|
||||
Vector3 getNormal() const;
|
||||
|
@ -209,21 +225,19 @@ class ContactPoint : public Constraint {
|
|||
decimal getPenetrationDepth() const;
|
||||
|
||||
/// Return the number of bytes used by the contact point
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
/// Initialize before solving the constraint
|
||||
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
|
||||
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the velocity constraint
|
||||
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the position constraint
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
size_t getSizeInBytes() const;
|
||||
};
|
||||
|
||||
// Return the reference to the body 1
|
||||
inline RigidBody* const ContactPoint::getBody1() const {
|
||||
return mBody1;
|
||||
}
|
||||
|
||||
// Return the reference to the body 2
|
||||
inline RigidBody* const ContactPoint::getBody2() const {
|
||||
return mBody2;
|
||||
}
|
||||
|
||||
// Return the normal vector of the contact
|
||||
inline Vector3 ContactPoint::getNormal() const {
|
||||
return mNormal;
|
||||
|
|
|
@ -34,7 +34,7 @@ const decimal FixedJoint::BETA = decimal(0.2);
|
|||
|
||||
// Constructor
|
||||
FixedJoint::FixedJoint(const FixedJointInfo& jointInfo)
|
||||
: Constraint(jointInfo), mImpulseTranslation(0, 0, 0), mImpulseRotation(0, 0, 0) {
|
||||
: Joint(jointInfo), mImpulseTranslation(0, 0, 0), mImpulseRotation(0, 0, 0) {
|
||||
|
||||
// Compute the local-space anchor point for each body
|
||||
const Transform& transform1 = mBody1->getTransform();
|
||||
|
@ -81,25 +81,25 @@ void FixedJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
|||
|
||||
// Compute the matrix K=JM^-1J^t (3x3 matrix) for the 3 translation constraints
|
||||
decimal inverseMassBodies = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody1->getMassInverse();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody2->getMassInverse();
|
||||
}
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU1 * mI1 * skewSymmetricMatrixU1.getTranspose();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU2 * mI2 * skewSymmetricMatrixU2.getTranspose();
|
||||
}
|
||||
|
||||
// Compute the inverse mass matrix K^-1 for the 3 translation constraints
|
||||
mInverseMassMatrixTranslation.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixTranslation = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
|
@ -113,13 +113,13 @@ void FixedJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
|||
// Compute the inverse of the mass matrix K=JM^-1J^t for the 3 rotation
|
||||
// contraints (3x3 matrix)
|
||||
mInverseMassMatrixRotation.setToZero();
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotation += mI1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotation += mI2;
|
||||
}
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotation = mInverseMassMatrixRotation.getInverse();
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ void FixedJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
|||
const decimal inverseMassBody1 = mBody1->getMassInverse();
|
||||
const decimal inverseMassBody2 = mBody2->getMassInverse();
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 translation constraints
|
||||
Vector3 linearImpulseBody1 = -mImpulseTranslation;
|
||||
|
@ -167,7 +167,7 @@ void FixedJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 translation constraints
|
||||
Vector3 linearImpulseBody2 = mImpulseTranslation;
|
||||
|
@ -205,7 +205,7 @@ void FixedJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
(-JvTranslation - mBiasTranslation);
|
||||
mImpulseTranslation += deltaLambda;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 linearImpulseBody1 = -deltaLambda;
|
||||
|
@ -215,7 +215,7 @@ void FixedJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 linearImpulseBody2 = deltaLambda;
|
||||
|
@ -235,7 +235,7 @@ void FixedJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
Vector3 deltaLambda2 = mInverseMassMatrixRotation * (-JvRotation - mBiasRotation);
|
||||
mImpulseRotation += deltaLambda2;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
|
||||
const Vector3 angularImpulseBody1 = -deltaLambda2;
|
||||
|
@ -243,7 +243,7 @@ void FixedJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
// Apply the impulse to the body
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
|
||||
const Vector3 angularImpulseBody2 = deltaLambda2;
|
||||
|
@ -286,23 +286,23 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
|
||||
// Compute the matrix K=JM^-1J^t (3x3 matrix) for the 3 translation constraints
|
||||
decimal inverseMassBodies = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody1->getMassInverse();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody2->getMassInverse();
|
||||
}
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU1 * mI1 * skewSymmetricMatrixU1.getTranspose();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU2 * mI2 * skewSymmetricMatrixU2.getTranspose();
|
||||
}
|
||||
mInverseMassMatrixTranslation.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixTranslation = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
|
@ -313,7 +313,7 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
const Vector3 lambdaTranslation = mInverseMassMatrixTranslation * (-errorTranslation);
|
||||
|
||||
// Apply the impulse to the bodies of the joint
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse
|
||||
Vector3 linearImpulseBody1 = -lambdaTranslation;
|
||||
|
@ -328,7 +328,7 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse
|
||||
Vector3 linearImpulseBody2 = lambdaTranslation;
|
||||
|
@ -349,13 +349,13 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
// Compute the inverse of the mass matrix K=JM^-1J^t for the 3 rotation
|
||||
// contraints (3x3 matrix)
|
||||
mInverseMassMatrixRotation.setToZero();
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotation += mI1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotation += mI2;
|
||||
}
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotation = mInverseMassMatrixRotation.getInverse();
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
Vector3 lambdaRotation = mInverseMassMatrixRotation * (-errorRotation);
|
||||
|
||||
// Apply the impulse to the bodies of the joint
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
|
||||
const Vector3 angularImpulseBody1 = -lambdaRotation;
|
||||
|
@ -381,7 +381,7 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse
|
||||
const Vector3 angularImpulseBody2 = lambdaRotation;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define REACTPHYSICS3D_FIXED_JOINT_H
|
||||
|
||||
// Libraries
|
||||
#include "Constraint.h"
|
||||
#include "Joint.h"
|
||||
#include "../mathematics/mathematics.h"
|
||||
|
||||
namespace reactphysics3d {
|
||||
|
@ -37,7 +37,7 @@ namespace reactphysics3d {
|
|||
* This structure is used to gather the information needed to create a fixed
|
||||
* joint. This structure will be used to create the actual fixed joint.
|
||||
*/
|
||||
struct FixedJointInfo : public ConstraintInfo {
|
||||
struct FixedJointInfo : public JointInfo {
|
||||
|
||||
public :
|
||||
|
||||
|
@ -49,7 +49,7 @@ struct FixedJointInfo : public ConstraintInfo {
|
|||
/// Constructor
|
||||
FixedJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace)
|
||||
: ConstraintInfo(rigidBody1, rigidBody2, FIXEDJOINT),
|
||||
: JointInfo(rigidBody1, rigidBody2, FIXEDJOINT),
|
||||
anchorPointWorldSpace(initAnchorPointWorldSpace){}
|
||||
};
|
||||
|
||||
|
@ -58,7 +58,7 @@ struct FixedJointInfo : public ConstraintInfo {
|
|||
* This class represents a fixed joint that is used to forbid any translation or rotation
|
||||
* between two bodies.
|
||||
*/
|
||||
class FixedJoint : public Constraint {
|
||||
class FixedJoint : public Joint {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -116,16 +116,6 @@ class FixedJoint : public Constraint {
|
|||
/// Private assignment operator
|
||||
FixedJoint& operator=(const FixedJoint& constraint);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
FixedJoint(const FixedJointInfo& jointInfo);
|
||||
|
||||
/// Destructor
|
||||
virtual ~FixedJoint();
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
|
@ -140,6 +130,16 @@ class FixedJoint : public Constraint {
|
|||
|
||||
/// Solve the position constraint (for position error correction)
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
FixedJoint(const FixedJointInfo& jointInfo);
|
||||
|
||||
/// Destructor
|
||||
virtual ~FixedJoint();
|
||||
};
|
||||
|
||||
// Return the number of bytes used by the joint
|
||||
|
|
|
@ -35,7 +35,7 @@ const decimal HingeJoint::BETA = decimal(0.2);
|
|||
|
||||
// Constructor
|
||||
HingeJoint::HingeJoint(const HingeJointInfo& jointInfo)
|
||||
: Constraint(jointInfo), mImpulseTranslation(0, 0, 0), mImpulseRotation(0, 0),
|
||||
: Joint(jointInfo), mImpulseTranslation(0, 0, 0), mImpulseRotation(0, 0),
|
||||
mImpulseLowerLimit(0), mImpulseUpperLimit(0), mImpulseMotor(0),
|
||||
mIsLimitEnabled(jointInfo.isLimitEnabled), mIsMotorEnabled(jointInfo.isMotorEnabled),
|
||||
mLowerLimit(jointInfo.minAngleLimit), mUpperLimit(jointInfo.maxAngleLimit),
|
||||
|
@ -59,7 +59,7 @@ HingeJoint::HingeJoint(const HingeJointInfo& jointInfo)
|
|||
|
||||
// Compute the inverse of the initial orientation difference between the two bodies
|
||||
mInitOrientationDifferenceInv = transform2.getOrientation() *
|
||||
transform1.getOrientation().getInverse();
|
||||
transform1.getOrientation().getInverse();
|
||||
mInitOrientationDifferenceInv.normalize();
|
||||
mInitOrientationDifferenceInv.inverse();
|
||||
}
|
||||
|
@ -123,23 +123,23 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
|||
|
||||
// Compute the inverse mass matrix K=JM^-1J^t for the 3 translation constraints (3x3 matrix)
|
||||
decimal inverseMassBodies = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody1->getMassInverse();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody2->getMassInverse();
|
||||
}
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU1 * mI1 * skewSymmetricMatrixU1.getTranspose();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU2 * mI2 * skewSymmetricMatrixU2.getTranspose();
|
||||
}
|
||||
mInverseMassMatrixTranslation.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixTranslation = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
|
@ -155,11 +155,11 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
|||
Vector3 I1C2CrossA1(0, 0, 0);
|
||||
Vector3 I2B2CrossA1(0, 0, 0);
|
||||
Vector3 I2C2CrossA1(0, 0, 0);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
I1B2CrossA1 = mI1 * mB2CrossA1;
|
||||
I1C2CrossA1 = mI1 * mC2CrossA1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
I2B2CrossA1 = mI2 * mB2CrossA1;
|
||||
I2C2CrossA1 = mI2 * mC2CrossA1;
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
|||
mC2CrossA1.dot(I2C2CrossA1);
|
||||
const Matrix2x2 matrixKRotation(el11, el12, el21, el22);
|
||||
mInverseMassMatrixRotation.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotation = matrixKRotation.getInverse();
|
||||
}
|
||||
|
||||
|
@ -194,29 +194,33 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
|||
mImpulseMotor = 0.0;
|
||||
}
|
||||
|
||||
if (mIsLimitEnabled && (mIsLowerLimitViolated || mIsUpperLimitViolated)) {
|
||||
// If the motor or limits are enabled
|
||||
if (mIsMotorEnabled || (mIsLimitEnabled && (mIsLowerLimitViolated || mIsUpperLimitViolated))) {
|
||||
|
||||
// Compute the inverse of the mass matrix K=JM^-1J^t for the limits (1x1 matrix)
|
||||
// Compute the inverse of the mass matrix K=JM^-1J^t for the limits and motor (1x1 matrix)
|
||||
mInverseMassMatrixLimitMotor = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixLimitMotor += mA1.dot(mI1 * mA1);
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixLimitMotor += mA1.dot(mI2 * mA1);
|
||||
}
|
||||
mInverseMassMatrixLimitMotor = (mInverseMassMatrixLimitMotor > 0.0) ?
|
||||
decimal(1.0) / mInverseMassMatrixLimitMotor : decimal(0.0);
|
||||
|
||||
// Compute the bias "b" of the lower limit constraint
|
||||
mBLowerLimit = 0.0;
|
||||
if (mPositionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
mBLowerLimit = biasFactor * lowerLimitError;
|
||||
}
|
||||
if (mIsLimitEnabled) {
|
||||
|
||||
// Compute the bias "b" of the upper limit constraint
|
||||
mBUpperLimit = 0.0;
|
||||
if (mPositionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
mBUpperLimit = biasFactor * upperLimitError;
|
||||
// Compute the bias "b" of the lower limit constraint
|
||||
mBLowerLimit = 0.0;
|
||||
if (mPositionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
mBLowerLimit = biasFactor * lowerLimitError;
|
||||
}
|
||||
|
||||
// Compute the bias "b" of the upper limit constraint
|
||||
mBUpperLimit = 0.0;
|
||||
if (mPositionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
mBUpperLimit = biasFactor * upperLimitError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +247,7 @@ void HingeJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
|||
// Compute the impulse P=J^T * lambda for the motor constraint
|
||||
const Vector3 motorImpulse = -mImpulseMotor * mA1;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 translation constraints
|
||||
Vector3 linearImpulseBody1 = -mImpulseTranslation;
|
||||
|
@ -262,7 +266,7 @@ void HingeJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 translation constraints
|
||||
Vector3 linearImpulseBody2 = mImpulseTranslation;
|
||||
|
@ -306,7 +310,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
(-JvTranslation - mBTranslation);
|
||||
mImpulseTranslation += deltaLambdaTranslation;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 linearImpulseBody1 = -deltaLambdaTranslation;
|
||||
|
@ -316,7 +320,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 linearImpulseBody2 = deltaLambdaTranslation;
|
||||
|
@ -337,7 +341,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
Vector2 deltaLambdaRotation = mInverseMassMatrixRotation * (-JvRotation - mBRotation);
|
||||
mImpulseRotation += deltaLambdaRotation;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 rotation constraints
|
||||
const Vector3 angularImpulseBody1 = -mB2CrossA1 * deltaLambdaRotation.x -
|
||||
|
@ -346,7 +350,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
// Apply the impulse to the body
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 rotation constraints
|
||||
const Vector3 angularImpulseBody2 = mB2CrossA1 * deltaLambdaRotation.x +
|
||||
|
@ -372,7 +376,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
mImpulseLowerLimit = std::max(mImpulseLowerLimit + deltaLambdaLower, decimal(0.0));
|
||||
deltaLambdaLower = mImpulseLowerLimit - lambdaTemp;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint
|
||||
const Vector3 angularImpulseBody1 = -deltaLambdaLower * mA1;
|
||||
|
@ -380,7 +384,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
// Apply the impulse to the body
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint
|
||||
const Vector3 angularImpulseBody2 = deltaLambdaLower * mA1;
|
||||
|
@ -402,7 +406,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
mImpulseUpperLimit = std::max(mImpulseUpperLimit + deltaLambdaUpper, decimal(0.0));
|
||||
deltaLambdaUpper = mImpulseUpperLimit - lambdaTemp;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint
|
||||
const Vector3 angularImpulseBody1 = deltaLambdaUpper * mA1;
|
||||
|
@ -410,7 +414,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
// Apply the impulse to the body
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint
|
||||
const Vector3 angularImpulseBody2 = -deltaLambdaUpper * mA1;
|
||||
|
@ -423,6 +427,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
|
||||
// --------------- Motor --------------- //
|
||||
|
||||
// If the motor is enabled
|
||||
if (mIsMotorEnabled) {
|
||||
|
||||
// Compute J*v for the motor
|
||||
|
@ -435,7 +440,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
mImpulseMotor = clamp(mImpulseMotor + deltaLambdaMotor, -maxMotorImpulse, maxMotorImpulse);
|
||||
deltaLambdaMotor = mImpulseMotor - lambdaTemp;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor
|
||||
const Vector3 angularImpulseBody1 = -deltaLambdaMotor * mA1;
|
||||
|
@ -443,7 +448,7 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
|||
// Apply the impulse to the body
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor
|
||||
const Vector3 angularImpulseBody2 = deltaLambdaMotor * mA1;
|
||||
|
@ -506,23 +511,23 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
|
||||
// Compute the matrix K=JM^-1J^t (3x3 matrix) for the 3 translation constraints
|
||||
decimal inverseMassBodies = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody1->getMassInverse();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
inverseMassBodies += mBody2->getMassInverse();
|
||||
}
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU1 * mI1 * skewSymmetricMatrixU1.getTranspose();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
massMatrix += skewSymmetricMatrixU2 * mI2 * skewSymmetricMatrixU2.getTranspose();
|
||||
}
|
||||
mInverseMassMatrixTranslation.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixTranslation = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
|
@ -533,7 +538,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
const Vector3 lambdaTranslation = mInverseMassMatrixTranslation * (-errorTranslation);
|
||||
|
||||
// Apply the impulse to the bodies of the joint
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse
|
||||
Vector3 linearImpulseBody1 = -lambdaTranslation;
|
||||
|
@ -548,7 +553,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse
|
||||
Vector3 linearImpulseBody2 = lambdaTranslation;
|
||||
|
@ -571,11 +576,11 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
Vector3 I1C2CrossA1(0, 0, 0);
|
||||
Vector3 I2B2CrossA1(0, 0, 0);
|
||||
Vector3 I2C2CrossA1(0, 0, 0);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
I1B2CrossA1 = mI1 * mB2CrossA1;
|
||||
I1C2CrossA1 = mI1 * mC2CrossA1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
I2B2CrossA1 = mI2 * mB2CrossA1;
|
||||
I2C2CrossA1 = mI2 * mC2CrossA1;
|
||||
}
|
||||
|
@ -589,7 +594,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
mC2CrossA1.dot(I2C2CrossA1);
|
||||
const Matrix2x2 matrixKRotation(el11, el12, el21, el22);
|
||||
mInverseMassMatrixRotation.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotation = matrixKRotation.getInverse();
|
||||
}
|
||||
|
||||
|
@ -600,7 +605,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
Vector2 lambdaRotation = mInverseMassMatrixRotation * (-errorRotation);
|
||||
|
||||
// Apply the impulse to the bodies of the joint
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
|
||||
const Vector3 angularImpulseBody1 = -mB2CrossA1 * lambdaRotation.x -
|
||||
|
@ -613,7 +618,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse
|
||||
const Vector3 angularImpulseBody2 = mB2CrossA1 * lambdaRotation.x +
|
||||
|
@ -635,10 +640,10 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
|
||||
// Compute the inverse of the mass matrix K=JM^-1J^t for the limits (1x1 matrix)
|
||||
mInverseMassMatrixLimitMotor = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixLimitMotor += mA1.dot(mI1 * mA1);
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixLimitMotor += mA1.dot(mI2 * mA1);
|
||||
}
|
||||
mInverseMassMatrixLimitMotor = (mInverseMassMatrixLimitMotor > 0.0) ?
|
||||
|
@ -652,7 +657,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
decimal lambdaLowerLimit = mInverseMassMatrixLimitMotor * (-lowerLimitError );
|
||||
|
||||
// Apply the impulse to the bodies of the joint
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 angularImpulseBody1 = -lambdaLowerLimit * mA1;
|
||||
|
@ -664,7 +669,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 angularImpulseBody2 = lambdaLowerLimit * mA1;
|
||||
|
@ -685,7 +690,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
decimal lambdaUpperLimit = mInverseMassMatrixLimitMotor * (-upperLimitError);
|
||||
|
||||
// Apply the impulse to the bodies of the joint
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 angularImpulseBody1 = lambdaUpperLimit * mA1;
|
||||
|
@ -697,7 +702,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Vector3 angularImpulseBody2 = -lambdaUpperLimit * mA1;
|
||||
|
@ -732,7 +737,9 @@ void HingeJoint::enableMotor(bool isMotorEnabled) {
|
|||
mIsMotorEnabled = isMotorEnabled;
|
||||
mImpulseMotor = 0.0;
|
||||
|
||||
// TODO : Wake up the bodies of the joint here when sleeping is implemented
|
||||
// Wake up the two bodies of the joint
|
||||
mBody1->setIsSleeping(false);
|
||||
mBody2->setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Set the minimum angle limit
|
||||
|
@ -770,7 +777,9 @@ void HingeJoint::resetLimits() {
|
|||
mImpulseLowerLimit = 0.0;
|
||||
mImpulseUpperLimit = 0.0;
|
||||
|
||||
// TODO : Wake up the bodies of the joint here when sleeping is implemented
|
||||
// Wake up the two bodies of the joint
|
||||
mBody1->setIsSleeping(false);
|
||||
mBody2->setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Set the motor speed
|
||||
|
@ -780,7 +789,9 @@ void HingeJoint::setMotorSpeed(decimal motorSpeed) {
|
|||
|
||||
mMotorSpeed = motorSpeed;
|
||||
|
||||
// TODO : Wake up the bodies of the joint here when sleeping is implemented
|
||||
// Wake up the two bodies of the joint
|
||||
mBody1->setIsSleeping(false);
|
||||
mBody2->setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -792,7 +803,9 @@ void HingeJoint::setMaxMotorTorque(decimal maxMotorTorque) {
|
|||
assert(mMaxMotorTorque >= 0.0);
|
||||
mMaxMotorTorque = maxMotorTorque;
|
||||
|
||||
// TODO : Wake up the bodies of the joint here when sleeping is implemented
|
||||
// Wake up the two bodies of the joint
|
||||
mBody1->setIsSleeping(false);
|
||||
mBody2->setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define REACTPHYSICS3D_HINGE_JOINT_H
|
||||
|
||||
// Libraries
|
||||
#include "Constraint.h"
|
||||
#include "Joint.h"
|
||||
#include "../mathematics/mathematics.h"
|
||||
|
||||
namespace reactphysics3d {
|
||||
|
@ -37,7 +37,7 @@ namespace reactphysics3d {
|
|||
* This structure is used to gather the information needed to create a hinge joint.
|
||||
* This structure will be used to create the actual hinge joint.
|
||||
*/
|
||||
struct HingeJointInfo : public ConstraintInfo {
|
||||
struct HingeJointInfo : public JointInfo {
|
||||
|
||||
public :
|
||||
|
||||
|
@ -49,10 +49,10 @@ struct HingeJointInfo : public ConstraintInfo {
|
|||
/// Hinge rotation axis (in world-space coordinates)
|
||||
Vector3 rotationAxisWorld;
|
||||
|
||||
/// True if the slider limits are enabled
|
||||
/// True if the hinge joint limits are enabled
|
||||
bool isLimitEnabled;
|
||||
|
||||
/// True if the slider motor is enabled
|
||||
/// True if the hinge joint motor is enabled
|
||||
bool isMotorEnabled;
|
||||
|
||||
/// Minimum allowed rotation angle (in radian) if limits are enabled.
|
||||
|
@ -74,7 +74,7 @@ struct HingeJointInfo : public ConstraintInfo {
|
|||
HingeJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initRotationAxisWorld)
|
||||
: ConstraintInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
: JointInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
rotationAxisWorld(initRotationAxisWorld), isLimitEnabled(false),
|
||||
isMotorEnabled(false), minAngleLimit(-1), maxAngleLimit(1),
|
||||
|
@ -85,7 +85,7 @@ struct HingeJointInfo : public ConstraintInfo {
|
|||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initRotationAxisWorld,
|
||||
decimal initMinAngleLimit, decimal initMaxAngleLimit)
|
||||
: ConstraintInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
: JointInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
rotationAxisWorld(initRotationAxisWorld), isLimitEnabled(true),
|
||||
isMotorEnabled(false), minAngleLimit(initMinAngleLimit),
|
||||
|
@ -98,7 +98,7 @@ struct HingeJointInfo : public ConstraintInfo {
|
|||
const Vector3& initRotationAxisWorld,
|
||||
decimal initMinAngleLimit, decimal initMaxAngleLimit,
|
||||
decimal initMotorSpeed, decimal initMaxMotorTorque)
|
||||
: ConstraintInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
: JointInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
rotationAxisWorld(initRotationAxisWorld), isLimitEnabled(true),
|
||||
isMotorEnabled(false), minAngleLimit(initMinAngleLimit),
|
||||
|
@ -109,9 +109,10 @@ struct HingeJointInfo : public ConstraintInfo {
|
|||
// Class HingeJoint
|
||||
/**
|
||||
* This class represents a hinge joint that allows arbitrary rotation
|
||||
* between two bodies around a single axis.
|
||||
* between two bodies around a single axis. This joint has one degree of freedom. It
|
||||
* can be useful to simulate doors or pendulumns.
|
||||
*/
|
||||
class HingeJoint : public Constraint {
|
||||
class HingeJoint : public Joint {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -246,6 +247,21 @@ class HingeJoint : public Constraint {
|
|||
decimal computeCurrentHingeAngle(const Quaternion& orientationBody1,
|
||||
const Quaternion& orientationBody2);
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
/// Initialize before solving the constraint
|
||||
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
|
||||
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the velocity constraint
|
||||
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the position constraint (for position error correction)
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -294,21 +310,6 @@ class HingeJoint : public Constraint {
|
|||
|
||||
/// Return the intensity of the current torque applied for the joint motor
|
||||
decimal getMotorTorque(decimal timeStep) const;
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
/// Initialize before solving the constraint
|
||||
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
|
||||
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the velocity constraint
|
||||
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the position constraint (for position error correction)
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
};
|
||||
|
||||
// Return true if the limits or the joint are enabled
|
||||
|
|
|
@ -24,22 +24,21 @@
|
|||
********************************************************************************/
|
||||
|
||||
// Libraries
|
||||
#include "Constraint.h"
|
||||
#include "Joint.h"
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
Constraint::Constraint(const ConstraintInfo& constraintInfo)
|
||||
:mBody1(constraintInfo.body1), mBody2(constraintInfo.body2), mActive(true),
|
||||
mType(constraintInfo.type),
|
||||
mPositionCorrectionTechnique(constraintInfo.positionCorrectionTechnique),
|
||||
mIsCollisionEnabled(constraintInfo.isCollisionEnabled){
|
||||
Joint::Joint(const JointInfo& jointInfo)
|
||||
:mBody1(jointInfo.body1), mBody2(jointInfo.body2), mType(jointInfo.type),
|
||||
mPositionCorrectionTechnique(jointInfo.positionCorrectionTechnique),
|
||||
mIsCollisionEnabled(jointInfo.isCollisionEnabled), mIsAlreadyInIsland(false) {
|
||||
|
||||
assert(mBody1 != NULL);
|
||||
assert(mBody2 != NULL);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Constraint::~Constraint() {
|
||||
Joint::~Joint() {
|
||||
|
||||
}
|
|
@ -35,31 +35,57 @@
|
|||
namespace reactphysics3d {
|
||||
|
||||
// Enumeration for the type of a constraint
|
||||
enum ConstraintType {CONTACT, BALLSOCKETJOINT, SLIDERJOINT, HINGEJOINT, FIXEDJOINT};
|
||||
enum JointType {BALLSOCKETJOINT, SLIDERJOINT, HINGEJOINT, FIXEDJOINT};
|
||||
|
||||
// Class declarations
|
||||
struct ConstraintSolverData;
|
||||
class Joint;
|
||||
|
||||
// Structure ConstraintInfo
|
||||
// Structure JointListElement
|
||||
/**
|
||||
* This structure is used to gather the information needed to create a constraint.
|
||||
* This structure represents a single element of a linked list of joints
|
||||
*/
|
||||
struct ConstraintInfo {
|
||||
struct JointListElement {
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Pointer to the actual joint
|
||||
Joint* joint;
|
||||
|
||||
/// Next element of the list
|
||||
JointListElement* next;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
JointListElement(Joint* initJoint, JointListElement* initNext)
|
||||
:joint(initJoint), next(initNext){
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Structure JointInfo
|
||||
/**
|
||||
* This structure is used to gather the information needed to create a joint.
|
||||
*/
|
||||
struct JointInfo {
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// First rigid body of the constraint
|
||||
/// First rigid body of the joint
|
||||
RigidBody* body1;
|
||||
|
||||
/// Second rigid body of the constraint
|
||||
/// Second rigid body of the joint
|
||||
RigidBody* body2;
|
||||
|
||||
/// Type of the constraint
|
||||
ConstraintType type;
|
||||
/// Type of the joint
|
||||
JointType type;
|
||||
|
||||
/// True if the two bodies of the constraint are allowed to collide with each other
|
||||
/// True if the two bodies of the joint are allowed to collide with each other
|
||||
bool isCollisionEnabled;
|
||||
|
||||
/// Position correction technique used for the constraint (used for joints).
|
||||
|
@ -67,47 +93,41 @@ struct ConstraintInfo {
|
|||
JointsPositionCorrectionTechnique positionCorrectionTechnique;
|
||||
|
||||
/// Constructor
|
||||
ConstraintInfo(ConstraintType constraintType)
|
||||
JointInfo(JointType constraintType)
|
||||
: body1(NULL), body2(NULL), type(constraintType),
|
||||
positionCorrectionTechnique(NON_LINEAR_GAUSS_SEIDEL),
|
||||
isCollisionEnabled(true) {}
|
||||
|
||||
/// Constructor
|
||||
ConstraintInfo(RigidBody* rigidBody1, RigidBody* rigidBody2, ConstraintType constraintType)
|
||||
JointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2, JointType constraintType)
|
||||
: body1(rigidBody1), body2(rigidBody2), type(constraintType),
|
||||
positionCorrectionTechnique(NON_LINEAR_GAUSS_SEIDEL),
|
||||
isCollisionEnabled(true) {
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~ConstraintInfo() {}
|
||||
virtual ~JointInfo() {}
|
||||
|
||||
};
|
||||
|
||||
// Class Constraint
|
||||
// Class Joint
|
||||
/**
|
||||
* This abstract class represents a constraint in the physics engine.
|
||||
* A constraint can be a collision contact or a joint for
|
||||
* instance. Each constraint can be made of several "mathematical
|
||||
* constraints" needed to represent the main constraint.
|
||||
* This abstract class represents a joint between two bodies.
|
||||
*/
|
||||
class Constraint {
|
||||
class Joint {
|
||||
|
||||
protected :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Pointer to the first body of the constraint
|
||||
/// Pointer to the first body of the joint
|
||||
RigidBody* const mBody1;
|
||||
|
||||
/// Pointer to the second body of the constraint
|
||||
/// Pointer to the second body of the joint
|
||||
RigidBody* const mBody2;
|
||||
|
||||
/// True if the constraint is active
|
||||
bool mActive;
|
||||
|
||||
/// Type of the constraint
|
||||
const ConstraintType mType;
|
||||
/// Type of the joint
|
||||
const JointType mType;
|
||||
|
||||
/// Body 1 index in the velocity array to solve the constraint
|
||||
uint mIndexBody1;
|
||||
|
@ -121,23 +141,44 @@ class Constraint {
|
|||
/// True if the two bodies of the constraint are allowed to collide with each other
|
||||
bool mIsCollisionEnabled;
|
||||
|
||||
/// True if the joint has already been added into an island
|
||||
bool mIsAlreadyInIsland;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Private copy-constructor
|
||||
Constraint(const Constraint& constraint);
|
||||
Joint(const Joint& constraint);
|
||||
|
||||
/// Private assignment operator
|
||||
Constraint& operator=(const Constraint& constraint);
|
||||
Joint& operator=(const Joint& constraint);
|
||||
|
||||
/// Return true if the joint has already been added into an island
|
||||
bool isAlreadyInIsland() const;
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const = 0;
|
||||
|
||||
/// Initialize before solving the joint
|
||||
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData) = 0;
|
||||
|
||||
/// Warm start the joint (apply the previous impulse at the beginning of the step)
|
||||
virtual void warmstart(const ConstraintSolverData& constraintSolverData) = 0;
|
||||
|
||||
/// Solve the velocity constraint
|
||||
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) = 0;
|
||||
|
||||
/// Solve the position constraint
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData) = 0;
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Constraint(const ConstraintInfo& constraintInfo);
|
||||
Joint(const JointInfo& jointInfo);
|
||||
|
||||
/// Destructor
|
||||
virtual ~Constraint();
|
||||
virtual ~Joint();
|
||||
|
||||
/// Return the reference to the body 1
|
||||
RigidBody* const getBody1() const;
|
||||
|
@ -149,52 +190,48 @@ class Constraint {
|
|||
bool isActive() const;
|
||||
|
||||
/// Return the type of the constraint
|
||||
ConstraintType getType() const;
|
||||
JointType getType() const;
|
||||
|
||||
/// Return true if the collision between the two bodies of the constraint is enabled
|
||||
/// Return true if the collision between the two bodies of the joint is enabled
|
||||
bool isCollisionEnabled() const;
|
||||
|
||||
/// Return the number of bytes used by the constraint
|
||||
virtual size_t getSizeInBytes() const = 0;
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
/// Initialize before solving the constraint
|
||||
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData) = 0;
|
||||
|
||||
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
|
||||
virtual void warmstart(const ConstraintSolverData& constraintSolverData) = 0;
|
||||
|
||||
/// Solve the velocity constraint
|
||||
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) = 0;
|
||||
|
||||
/// Solve the position constraint
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData) = 0;
|
||||
friend class DynamicsWorld;
|
||||
friend class Island;
|
||||
friend class ConstraintSolver;
|
||||
};
|
||||
|
||||
// Return the reference to the body 1
|
||||
inline RigidBody* const Constraint::getBody1() const {
|
||||
inline RigidBody* const Joint::getBody1() const {
|
||||
return mBody1;
|
||||
}
|
||||
|
||||
// Return the reference to the body 2
|
||||
inline RigidBody* const Constraint::getBody2() const {
|
||||
inline RigidBody* const Joint::getBody2() const {
|
||||
return mBody2;
|
||||
}
|
||||
|
||||
// Return true if the constraint is active
|
||||
inline bool Constraint::isActive() const {
|
||||
return mActive;
|
||||
// Return true if the joint is active
|
||||
inline bool Joint::isActive() const {
|
||||
return (mBody1->isActive() && mBody2->isActive());
|
||||
}
|
||||
|
||||
// Return the type of the constraint
|
||||
inline ConstraintType Constraint::getType() const {
|
||||
// Return the type of the joint
|
||||
inline JointType Joint::getType() const {
|
||||
return mType;
|
||||
}
|
||||
|
||||
// Return true if the collision between the two bodies of the constraint is enabled
|
||||
inline bool Constraint::isCollisionEnabled() const {
|
||||
// Return true if the collision between the two bodies of the joint is enabled
|
||||
inline bool Joint::isCollisionEnabled() const {
|
||||
return mIsCollisionEnabled;
|
||||
}
|
||||
|
||||
// Return true if the joint has already been added into an island
|
||||
inline bool Joint::isAlreadyInIsland() const {
|
||||
return mIsAlreadyInIsland;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -33,7 +33,7 @@ const decimal SliderJoint::BETA = decimal(0.2);
|
|||
|
||||
// Constructor
|
||||
SliderJoint::SliderJoint(const SliderJointInfo& jointInfo)
|
||||
: Constraint(jointInfo), mImpulseTranslation(0, 0), mImpulseRotation(0, 0, 0),
|
||||
: Joint(jointInfo), mImpulseTranslation(0, 0), mImpulseRotation(0, 0, 0),
|
||||
mImpulseLowerLimit(0), mImpulseUpperLimit(0), mImpulseMotor(0),
|
||||
mIsLimitEnabled(jointInfo.isLimitEnabled), mIsMotorEnabled(jointInfo.isMotorEnabled),
|
||||
mLowerLimit(jointInfo.minTranslationLimit),
|
||||
|
@ -129,12 +129,12 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
|||
Vector3 I1R1PlusUCrossN2(0, 0, 0);
|
||||
Vector3 I2R2CrossN1(0, 0, 0);
|
||||
Vector3 I2R2CrossN2(0, 0, 0);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
sumInverseMass += mBody1->getMassInverse();
|
||||
I1R1PlusUCrossN1 = mI1 * mR1PlusUCrossN1;
|
||||
I1R1PlusUCrossN2 = mI1 * mR1PlusUCrossN2;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
sumInverseMass += mBody2->getMassInverse();
|
||||
I2R2CrossN1 = mI2 * mR2CrossN1;
|
||||
I2R2CrossN2 = mI2 * mR2CrossN2;
|
||||
|
@ -149,7 +149,7 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
|||
mR2CrossN2.dot(I2R2CrossN2);
|
||||
Matrix2x2 matrixKTranslation(el11, el12, el21, el22);
|
||||
mInverseMassMatrixTranslationConstraint.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixTranslationConstraint = matrixKTranslation.getInverse();
|
||||
}
|
||||
|
||||
|
@ -165,13 +165,13 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
|||
// Compute the inverse of the mass matrix K=JM^-1J^t for the 3 rotation
|
||||
// contraints (3x3 matrix)
|
||||
mInverseMassMatrixRotationConstraint.setToZero();
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotationConstraint += mI1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotationConstraint += mI2;
|
||||
}
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotationConstraint = mInverseMassMatrixRotationConstraint.getInverse();
|
||||
}
|
||||
|
||||
|
@ -184,15 +184,16 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
|||
mBRotation = biasFactor * decimal(2.0) * qError.getVectorV();
|
||||
}
|
||||
|
||||
// If the limits are enabled
|
||||
if (mIsLimitEnabled && (mIsLowerLimitViolated || mIsUpperLimitViolated)) {
|
||||
|
||||
// Compute the inverse of the mass matrix K=JM^-1J^t for the limits (1x1 matrix)
|
||||
mInverseMassMatrixLimit = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixLimit += mBody1->getMassInverse() +
|
||||
mR1PlusUCrossSliderAxis.dot(mI1 * mR1PlusUCrossSliderAxis);
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixLimit += mBody2->getMassInverse() +
|
||||
mR2CrossSliderAxis.dot(mI2 * mR2CrossSliderAxis);
|
||||
}
|
||||
|
@ -212,16 +213,20 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
|||
}
|
||||
}
|
||||
|
||||
// Compute the inverse of mass matrix K=JM^-1J^t for the motor (1x1 matrix)
|
||||
mInverseMassMatrixMotor = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
mInverseMassMatrixMotor += mBody1->getMassInverse();
|
||||
// If the motor is enabled
|
||||
if (mIsMotorEnabled) {
|
||||
|
||||
// Compute the inverse of mass matrix K=JM^-1J^t for the motor (1x1 matrix)
|
||||
mInverseMassMatrixMotor = 0.0;
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixMotor += mBody1->getMassInverse();
|
||||
}
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixMotor += mBody2->getMassInverse();
|
||||
}
|
||||
mInverseMassMatrixMotor = (mInverseMassMatrixMotor > 0.0) ?
|
||||
decimal(1.0) / mInverseMassMatrixMotor : decimal(0.0);
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
mInverseMassMatrixMotor += mBody2->getMassInverse();
|
||||
}
|
||||
mInverseMassMatrixMotor = (mInverseMassMatrixMotor > 0.0) ?
|
||||
decimal(1.0) / mInverseMassMatrixMotor : decimal(0.0);
|
||||
|
||||
// If warm-starting is not enabled
|
||||
if (!constraintSolverData.isWarmStartingActive) {
|
||||
|
@ -255,7 +260,7 @@ void SliderJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
|||
// Compute the impulse P=J^T * lambda for the motor constraint
|
||||
Vector3 impulseMotor = mImpulseMotor * mSliderAxisWorld;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints
|
||||
Vector3 linearImpulseBody1 = -mN1 * mImpulseTranslation.x - mN2 * mImpulseTranslation.y;
|
||||
|
@ -276,7 +281,7 @@ void SliderJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints
|
||||
Vector3 linearImpulseBody2 = mN1 * mImpulseTranslation.x + mN2 * mImpulseTranslation.y;
|
||||
|
@ -325,7 +330,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
Vector2 deltaLambda = mInverseMassMatrixTranslationConstraint * (-JvTranslation -mBTranslation);
|
||||
mImpulseTranslation += deltaLambda;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints
|
||||
const Vector3 linearImpulseBody1 = -mN1 * deltaLambda.x - mN2 * deltaLambda.y;
|
||||
|
@ -336,7 +341,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints
|
||||
const Vector3 linearImpulseBody2 = mN1 * deltaLambda.x + mN2 * deltaLambda.y;
|
||||
|
@ -356,7 +361,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
Vector3 deltaLambda2 = mInverseMassMatrixRotationConstraint * (-JvRotation - mBRotation);
|
||||
mImpulseRotation += deltaLambda2;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
|
||||
const Vector3 angularImpulseBody1 = -deltaLambda2;
|
||||
|
@ -364,7 +369,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
// Apply the impulse to the body
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
|
||||
const Vector3 angularImpulseBody2 = deltaLambda2;
|
||||
|
@ -390,7 +395,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
mImpulseLowerLimit = std::max(mImpulseLowerLimit + deltaLambdaLower, decimal(0.0));
|
||||
deltaLambdaLower = mImpulseLowerLimit - lambdaTemp;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint
|
||||
const Vector3 linearImpulseBody1 = -deltaLambdaLower * mSliderAxisWorld;
|
||||
|
@ -400,7 +405,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint
|
||||
const Vector3 linearImpulseBody2 = deltaLambdaLower * mSliderAxisWorld;
|
||||
|
@ -425,7 +430,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
mImpulseUpperLimit = std::max(mImpulseUpperLimit + deltaLambdaUpper, decimal(0.0));
|
||||
deltaLambdaUpper = mImpulseUpperLimit - lambdaTemp;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint
|
||||
const Vector3 linearImpulseBody1 = deltaLambdaUpper * mSliderAxisWorld;
|
||||
|
@ -435,7 +440,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += mI1 * angularImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint
|
||||
const Vector3 linearImpulseBody2 = -deltaLambdaUpper * mSliderAxisWorld;
|
||||
|
@ -462,7 +467,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
mImpulseMotor = clamp(mImpulseMotor + deltaLambdaMotor, -maxMotorImpulse, maxMotorImpulse);
|
||||
deltaLambdaMotor = mImpulseMotor - lambdaTemp;
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor
|
||||
const Vector3 linearImpulseBody1 = deltaLambdaMotor * mSliderAxisWorld;
|
||||
|
@ -470,7 +475,7 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
|||
// Apply the impulse to the body
|
||||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor
|
||||
const Vector3 linearImpulseBody2 = -deltaLambdaMotor * mSliderAxisWorld;
|
||||
|
@ -540,12 +545,12 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
Vector3 I1R1PlusUCrossN2(0, 0, 0);
|
||||
Vector3 I2R2CrossN1(0, 0, 0);
|
||||
Vector3 I2R2CrossN2(0, 0, 0);
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
sumInverseMass += mBody1->getMassInverse();
|
||||
I1R1PlusUCrossN1 = mI1 * mR1PlusUCrossN1;
|
||||
I1R1PlusUCrossN2 = mI1 * mR1PlusUCrossN2;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
sumInverseMass += mBody2->getMassInverse();
|
||||
I2R2CrossN1 = mI2 * mR2CrossN1;
|
||||
I2R2CrossN2 = mI2 * mR2CrossN2;
|
||||
|
@ -560,7 +565,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
mR2CrossN2.dot(I2R2CrossN2);
|
||||
Matrix2x2 matrixKTranslation(el11, el12, el21, el22);
|
||||
mInverseMassMatrixTranslationConstraint.setToZero();
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixTranslationConstraint = matrixKTranslation.getInverse();
|
||||
}
|
||||
|
||||
|
@ -570,7 +575,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
// Compute the Lagrange multiplier lambda for the 2 translation constraints
|
||||
Vector2 lambdaTranslation = mInverseMassMatrixTranslationConstraint * (-translationError);
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints
|
||||
const Vector3 linearImpulseBody1 = -mN1 * lambdaTranslation.x - mN2 * lambdaTranslation.y;
|
||||
|
@ -586,7 +591,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints
|
||||
const Vector3 linearImpulseBody2 = mN1 * lambdaTranslation.x + mN2 * lambdaTranslation.y;
|
||||
|
@ -608,13 +613,13 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
// Compute the inverse of the mass matrix K=JM^-1J^t for the 3 rotation
|
||||
// contraints (3x3 matrix)
|
||||
mInverseMassMatrixRotationConstraint.setToZero();
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotationConstraint += mI1;
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotationConstraint += mI2;
|
||||
}
|
||||
if (mBody1->getIsMotionEnabled() || mBody2->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled() || mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixRotationConstraint = mInverseMassMatrixRotationConstraint.getInverse();
|
||||
}
|
||||
|
||||
|
@ -627,7 +632,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
// Compute the Lagrange multiplier lambda for the 3 rotation constraints
|
||||
Vector3 lambdaRotation = mInverseMassMatrixRotationConstraint * (-errorRotation);
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
|
||||
const Vector3 angularImpulseBody1 = -lambdaRotation;
|
||||
|
@ -639,7 +644,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
|
||||
const Vector3 angularImpulseBody2 = lambdaRotation;
|
||||
|
@ -660,11 +665,11 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
|
||||
// Compute the inverse of the mass matrix K=JM^-1J^t for the limits (1x1 matrix)
|
||||
mInverseMassMatrixLimit = 0.0;
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
mInverseMassMatrixLimit += mBody1->getMassInverse() +
|
||||
mR1PlusUCrossSliderAxis.dot(mI1 * mR1PlusUCrossSliderAxis);
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
mInverseMassMatrixLimit += mBody2->getMassInverse() +
|
||||
mR2CrossSliderAxis.dot(mI2 * mR2CrossSliderAxis);
|
||||
}
|
||||
|
@ -678,7 +683,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
// Compute the Lagrange multiplier lambda for the lower limit constraint
|
||||
decimal lambdaLowerLimit = mInverseMassMatrixLimit * (-lowerLimitError);
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint
|
||||
const Vector3 linearImpulseBody1 = -lambdaLowerLimit * mSliderAxisWorld;
|
||||
|
@ -693,7 +698,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint
|
||||
const Vector3 linearImpulseBody2 = lambdaLowerLimit * mSliderAxisWorld;
|
||||
|
@ -716,7 +721,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
// Compute the Lagrange multiplier lambda for the upper limit constraint
|
||||
decimal lambdaUpperLimit = mInverseMassMatrixLimit * (-upperLimitError);
|
||||
|
||||
if (mBody1->getIsMotionEnabled()) {
|
||||
if (mBody1->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint
|
||||
const Vector3 linearImpulseBody1 = lambdaUpperLimit * mSliderAxisWorld;
|
||||
|
@ -731,7 +736,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
|||
q1 += Quaternion(0, w1) * q1 * decimal(0.5);
|
||||
q1.normalize();
|
||||
}
|
||||
if (mBody2->getIsMotionEnabled()) {
|
||||
if (mBody2->isMotionEnabled()) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint
|
||||
const Vector3 linearImpulseBody2 = -lambdaUpperLimit * mSliderAxisWorld;
|
||||
|
@ -768,7 +773,9 @@ void SliderJoint::enableMotor(bool isMotorEnabled) {
|
|||
mIsMotorEnabled = isMotorEnabled;
|
||||
mImpulseMotor = 0.0;
|
||||
|
||||
// TODO : Wake up the bodies of the joint here when sleeping is implemented
|
||||
// Wake up the two bodies of the joint
|
||||
mBody1->setIsSleeping(false);
|
||||
mBody2->setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Return the current translation value of the joint
|
||||
|
@ -830,7 +837,9 @@ void SliderJoint::resetLimits() {
|
|||
mImpulseLowerLimit = 0.0;
|
||||
mImpulseUpperLimit = 0.0;
|
||||
|
||||
// TODO : Wake up the bodies of the joint here when sleeping is implemented
|
||||
// Wake up the two bodies of the joint
|
||||
mBody1->setIsSleeping(false);
|
||||
mBody2->setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Set the motor speed
|
||||
|
@ -840,7 +849,9 @@ void SliderJoint::setMotorSpeed(decimal motorSpeed) {
|
|||
|
||||
mMotorSpeed = motorSpeed;
|
||||
|
||||
// TODO : Wake up the bodies of the joint here when sleeping is implemented
|
||||
// Wake up the two bodies of the joint
|
||||
mBody1->setIsSleeping(false);
|
||||
mBody2->setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -852,6 +863,8 @@ void SliderJoint::setMaxMotorForce(decimal maxMotorForce) {
|
|||
assert(mMaxMotorForce >= 0.0);
|
||||
mMaxMotorForce = maxMotorForce;
|
||||
|
||||
// TODO : Wake up the bodies of the joint here when sleeping is implemented
|
||||
// Wake up the two bodies of the joint
|
||||
mBody1->setIsSleeping(false);
|
||||
mBody2->setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace reactphysics3d {
|
|||
* This structure is used to gather the information needed to create a slider
|
||||
* joint. This structure will be used to create the actual slider joint.
|
||||
*/
|
||||
struct SliderJointInfo : public ConstraintInfo {
|
||||
struct SliderJointInfo : public JointInfo {
|
||||
|
||||
public :
|
||||
|
||||
|
@ -71,7 +71,7 @@ struct SliderJointInfo : public ConstraintInfo {
|
|||
SliderJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initSliderAxisWorldSpace)
|
||||
: ConstraintInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
: JointInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
sliderAxisWorldSpace(initSliderAxisWorldSpace),
|
||||
isLimitEnabled(false), isMotorEnabled(false), minTranslationLimit(-1.0),
|
||||
|
@ -82,7 +82,7 @@ struct SliderJointInfo : public ConstraintInfo {
|
|||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initSliderAxisWorldSpace,
|
||||
decimal initMinTranslationLimit, decimal initMaxTranslationLimit)
|
||||
: ConstraintInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
: JointInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
sliderAxisWorldSpace(initSliderAxisWorldSpace),
|
||||
isLimitEnabled(true), isMotorEnabled(false),
|
||||
|
@ -96,7 +96,7 @@ struct SliderJointInfo : public ConstraintInfo {
|
|||
const Vector3& initSliderAxisWorldSpace,
|
||||
decimal initMinTranslationLimit, decimal initMaxTranslationLimit,
|
||||
decimal initMotorSpeed, decimal initMaxMotorForce)
|
||||
: ConstraintInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
: JointInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
sliderAxisWorldSpace(initSliderAxisWorldSpace),
|
||||
isLimitEnabled(true), isMotorEnabled(true),
|
||||
|
@ -107,9 +107,11 @@ struct SliderJointInfo : public ConstraintInfo {
|
|||
|
||||
// Class SliderJoint
|
||||
/**
|
||||
* This class represents a slider joint.
|
||||
* This class represents a slider joint. This joint has a one degree of freedom.
|
||||
* It only allows relative translation of the bodies along a single direction and no
|
||||
* rotation.
|
||||
*/
|
||||
class SliderJoint : public Constraint {
|
||||
class SliderJoint : public Joint {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -245,6 +247,21 @@ class SliderJoint : public Constraint {
|
|||
/// Reset the limits
|
||||
void resetLimits();
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
/// Initialize before solving the constraint
|
||||
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
|
||||
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the velocity constraint
|
||||
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the position constraint (for position error correction)
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -296,21 +313,6 @@ class SliderJoint : public Constraint {
|
|||
|
||||
/// Return the intensity of the current force applied for the joint motor
|
||||
decimal getMotorForce(decimal timeStep) const;
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
/// Initialize before solving the constraint
|
||||
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
|
||||
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the velocity constraint
|
||||
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the position constraint (for position error correction)
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
};
|
||||
|
||||
// Return true if the limits or the joint are enabled
|
||||
|
|
|
@ -34,6 +34,7 @@ using namespace std;
|
|||
// Constructor
|
||||
CollisionWorld::CollisionWorld()
|
||||
: mCollisionDetection(this, mMemoryAllocator), mCurrentBodyID(0) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user