More updates on Bullet code and other things

git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@49 ea6a568a-9f4f-0410-981a-c910a81bb256
actorid
nkorslund 16 years ago
parent c094324ef2
commit 6277c7f17c

@ -122,6 +122,9 @@ Changelog:
- working on collision detection with Bullet
- working on fixing sound issues for windows (running out of sound
resources, music playback doesn't good)
- new key bindings:
t - toggle physics mode (walking, flying, ghost)
n - nighteye, toggle full ambient light
- added build files for CMake (with CMakeD) and Code::Blocks (neither
are tested yet)
- various minor changes and updates

@ -35,6 +35,9 @@ extern(C):
// Initialize the dynamic world. Returns non-zero if an error occurs.
int bullet_init();
// Switch to the next physics mode
void bullet_nextMode();
// Warp the player to a specific location.
void bullet_movePlayer(float x, float y, float z);

@ -64,6 +64,16 @@ btTriangleIndexVertexArray *g_currentMesh;
btHashedOverlappingPairCache* g_pairCache;
CustomOverlappingPairCallback *g_customPairCallback;
// Three physics modes: walking (with gravity and collision), flying
// (collision but no gravity) and ghost mode (fly through walls)
enum
{
PHYS_WALK,
PHYS_FLY,
PHYS_GHOST
};
int g_physMode;
// Include the player physics
#include "cpp_player.cpp"
@ -181,10 +191,34 @@ extern "C" int32_t bullet_init()
// Make sure this is zero at startup
g_currentMesh = NULL;
// Start out walking
g_physMode = PHYS_WALK;
// Success!
return 0;
}
// Switch to the next physics mode
extern "C" void bullet_nextMode()
{
g_physMode++;
if(g_physMode > PHYS_GHOST)
g_physMode = PHYS_WALK;
switch(g_physMode)
{
case PHYS_WALK:
cout << "Entering walking mode\n";
break;
case PHYS_FLY:
cout << "Entering flying mode\n";
break;
case PHYS_GHOST:
cout << "Entering ghost mode\n";
break;
}
}
// Warp the player to a specific location. We do not bother setting
// rotation, since it's completely irrelevant for collision detection.
extern "C" void bullet_movePlayer(float x, float y, float z)
@ -285,6 +319,8 @@ extern "C" void bullet_insertStatic(btCollisionShape *shape,
float *quat,
float scale)
{
// TODO: Good test case for scaled meshes: Aharunartus, some of the
// stairs inside the cavern currently don't collide
if(scale != 1.0)
{
cout << "WARNING: Cannot scale collision meshes yet (wanted "

@ -232,8 +232,6 @@ bool recoverFromPenetration()
g_dynamicsWorld->getDispatchInfo(),
g_dispatcher);
g_playerPosition = g_playerObject->getWorldTransform().getOrigin();
btScalar maxPen = 0.0;
for (int i = 0; i < g_pairCache->getNumOverlappingPairs(); i++)
{
@ -285,41 +283,56 @@ bool recoverFromPenetration()
// main function is responsible for player movement.
void playerStepCallback(btDynamicsWorld* dynamicsWorld, btScalar timeStep)
{
// Before moving, recover from current penetrations
// The walking direction is set from D code each frame, and the
// final player position is read back from D code after the
// simulation.
btVector3 walkStep = g_walkDirection * timeStep;
int numPenetrationLoops = 0;
g_touchingContact = false;
while (recoverFromPenetration())
{
numPenetrationLoops++;
g_touchingContact = true;
// Get the player position
g_playerPosition = g_playerObject->getWorldTransform().getOrigin();
// Make sure we don't stay here indefinitely
if (numPenetrationLoops > 4)
break;
if(g_physMode == PHYS_GHOST)
{
// Ghost mode - just move, no collision
g_playerPosition += walkStep;
}
else
{
// Collision detection is active
// Get the player position
btTransform xform;
xform = g_playerObject->getWorldTransform ();
g_playerPosition = xform.getOrigin();
// Before moving, recover from current penetrations
int numPenetrationLoops = 0;
g_touchingContact = false;
while (recoverFromPenetration())
{
numPenetrationLoops++;
g_touchingContact = true;
// Next, do the walk.
// Make sure we don't stay here indefinitely
if (numPenetrationLoops > 4)
break;
}
// TODO: Walking direction should be set from D code, and the final
// position should be retrieved back from C++. The walking direction
// always reflects the intentional action of an agent (ie. the
// player or the AI), but the end result comes from collision and
// physics.
// recoverFromPenetration updates g_playerPosition and the
// collision mesh, so they are still in sync at this point
btVector3 walkStep = g_walkDirection * timeStep;
// Next, do the walk. The following functions only updates
// g_playerPosition, they do not move the collision object.
stepUp();
stepForward(walkStep);
stepDown(timeStep);
if(g_physMode == PHYS_WALK)
{
stepUp();
stepForward(walkStep);
stepDown(timeStep);
}
else if(g_physMode == PHYS_FLY)
stepForward(walkStep);
else
cout << "WARNING: Unknown physics mode " << g_physMode << "!\n";
}
// Move the player (but keep rotation)
xform = g_playerObject->getWorldTransform ();
// Move the player collision mesh
btTransform xform = g_playerObject->getWorldTransform ();
xform.setOrigin (g_playerPosition);
g_playerObject->setWorldTransform (xform);
}

@ -240,6 +240,8 @@ struct ConfigManager
bind(Keys.Fullscreen, KC.F);
bind(Keys.ToggleBattleMusic, KC.SPACE);
bind(Keys.PhysMode, KC.T);
bind(Keys.Nighteye, KC.N);
bind(Keys.Debug, KC.G);
bind(Keys.Pause, KC.PAUSE, KC.P);

@ -221,6 +221,9 @@ extern(C) void d_handleKey(KC keycode, dchar text = 0)
case Keys.Mute: toggleMute(); break;
case Keys.Fullscreen: toggleFullscreen(); break;
case Keys.PhysMode: bullet_nextMode(); break;
case Keys.Nighteye: ogre_toggleLight(); break;
case Keys.Debug: ogre_debug(0); break;
case Keys.ScreenShot: takeScreenShot(); break;
case Keys.Pause: togglePause(); break;

@ -65,6 +65,8 @@ enum Keys
// These will not be part of the finished product
Fullscreen,
ToggleBattleMusic,
PhysMode, // Toggle physics mode between walking, flying and ghost
Nighteye, // Full ambient lighting
Debug,
// Misc
@ -248,6 +250,8 @@ struct KeyBindings
keyToString[Keys.Fullscreen] = "Toggle Fullscreen Mode";
keyToString[Keys.ToggleBattleMusic] = "Toggle Battle Music";
keyToString[Keys.PhysMode] = "Toggle Physics Mode";
keyToString[Keys.Nighteye] = "Toggle Nighteye";
keyToString[Keys.Debug] = "OGRE Test Action";
keyToString[Keys.Pause] = "Pause";

@ -49,11 +49,10 @@ abstract class Controlled : Extra
// Record with name and controller/extra data link
abstract class Named : Controlled
{
// Name of this object. This is used to refer to the object from .kf
// files.
char[] name;
//Extra extra;
//Controller controller;
override:
char[] toString()
{
@ -68,23 +67,8 @@ abstract class Named : Controlled
//super.read(f);
name = nifFile.getString();
debug(verbose) writefln("Name: %s", name);
/*
debug(verbose) writef("Extra ");
getIndex(f);
debug(verbose) writef("Controller ");
getIndex(f);
*/
super.read();
}
/*
void sortOut(Record[] list)
{
super.sortOut(list);
extra = lookup!(Extra)(list);
controller = lookup!(Controller)(list);
}
*/
}
class NiSequenceStreamHelper : Named {}

@ -147,6 +147,15 @@ class ShapeData : Record
if(nifFile.getInt != 0)
{
if(uvs == 0) nifFile.warn("Empty UV list");
// Only the 6 first bits are used as a count, the rest are
// (unknown) flags.
if(uvs > 0b111111)
{
nifFile.warn("UV count contains (unknown) flags");
uvs = uvs & 0b111111;
}
uvlist = nifFile.getArraySize!(float)(uvs*verts*2);
}
else if(uvs != 0) nifFile.warn("UV list was unexpectedly missing");
@ -528,6 +537,7 @@ class NiTriShapeData : ShapeData
debug(verbose) writefln("Number of faces: ", tris);
if(tris)
{
// Must have three times as many vertices as triangles
int cnt = nifFile.getIntIs(tris*3);
triangles = nifFile.getArraySize!(short)(cnt);
}

@ -70,6 +70,9 @@ void ogre_setFog(float rf, float gf, float bf,
// Create a simple sky dome
int ogre_makeSky();
// Toggle full ambient lighting on and off
void ogre_toggleLight();
// Enter main rendering loop
void ogre_startRendering();

@ -121,6 +121,8 @@ extern "C" void ogre_rotateCamera(float x, float y)
{
mCamera->yaw(Degree(-x));
mCamera->pitch(Degree(-y));
//g_light->setDirection(mCamera->getDirection());
}
// Get current camera position
@ -154,6 +156,8 @@ extern "C" void ogre_moveCamera(float x, float y, float z)
// is not affected by the rotation of the root node, so we must
// transform this manually.
mCamera->setPosition(Vector3(x,z,-y));
//g_light->setPosition(mCamera->getPosition());
}
// Rotate camera using Morrowind rotation specifiers

@ -163,7 +163,7 @@ extern "C" void ogre_initWindow()
std::cout << "ogre_initWindow finished\n";
}
// Make a scene, set the given ambient light
// Make a scene
extern "C" void ogre_makeScene()
{
// Get the SceneManager, in this case a generic one
@ -198,6 +198,53 @@ extern "C" void ogre_makeScene()
SceneNode *rt = mSceneMgr->getRootSceneNode();
root = rt->createChildSceneNode();
root->pitch(Degree(-90));
/*
g_light = mSceneMgr->createLight("carry");
g_light->setDiffuseColour(1,0.7,0.3);
g_light->setAttenuation(2000, 0, 0.008, 0);
*/
}
/*
// Toggle carryable light
extern "C" void ogre_toggleCarryLight()
{
if(g_spotOn == 0)
{
g_light->setVisible(true);
g_spotOn = 1;
}
else
{
g_light->setVisible(false);
g_spotOn = 0;
}
}
*/
// Toggle ambient light
extern "C" void ogre_toggleLight()
{
if(g_lightOn == 0)
{
std::cout << "Turning the lights up\n";
ColourValue half = 0.7*g_ambient + 0.3*ColourValue(1,1,1);
mSceneMgr->setAmbientLight(half);
g_lightOn = 1;
}
else if(g_lightOn == 1)
{
std::cout << "Turning the lights to full\n";
g_lightOn = 2;
mSceneMgr->setAmbientLight(ColourValue(1,1,1));
}
else
{
std::cout << "Setting lights to normal\n";
g_lightOn = 0;
mSceneMgr->setAmbientLight(g_ambient);
}
}
// Create a sky dome. Currently disabled since we aren't including the
@ -217,6 +264,7 @@ extern "C" Light* ogre_attachLight(char *name, SceneNode* base,
// This seems to look reasonably ok.
l->setAttenuation(3*radius, 0, 0, 12.0/(radius*radius));
//l->setAttenuation(5*radius, 0, 0, 8.0/(radius*radius));
// base might be null, sometimes lights don't have meshes
if(base) base->attachObject(l);
@ -233,8 +281,8 @@ extern "C" void ogre_toggleFullscreen()
extern "C" void ogre_setAmbient(float r, float g, float b, // Ambient light
float rs, float gs, float bs) // "Sunlight"
{
ColourValue c = ColourValue(r, g, b);
mSceneMgr->setAmbientLight(c);
g_ambient = ColourValue(r, g, b);
mSceneMgr->setAmbientLight(g_ambient);
// Create a "sun" that shines light downwards. It doesn't look
// completely right, but leave it for now.

@ -42,6 +42,14 @@ SceneManager *mSceneMgr;
Camera *mCamera;
Viewport *vp;
ColourValue g_ambient;
int g_lightOn = 0;
/*
int g_spotOn = 0;
Light *g_light;
*/
OIS::InputManager *mInputManager;
OIS::Mouse *mMouse;
OIS::Keyboard *mKeyboard;

@ -102,8 +102,8 @@ struct MeshLoader
// names later, in order to attach arms and legs on NPCs
// etc. Always ignore transformation of the first node? This is a
// problem, I don't know when to do this and when not to. Neither
// is always right. Update: It looks like we should always set
// noRot to false in exterior cells.
// is always right. Update: I originally thought noRot should be
// false for exteriors and true for interiors, but this isn't so.
NodePtr node = ogre_createNode(UniqueName(data.name).ptr, &data.trafo,
parent, cast(int)noRot);

@ -308,9 +308,9 @@ void main(char[][] args)
// Doors
foreach(ref LiveDoor ls; cd.doors)
putObject(ls.m.model, &ls.base.pos, ls.base.scale);
// Activators
// Activators (including beds etc)
foreach(ref LiveActivator ls; cd.activators)
putObject(ls.m.model, &ls.base.pos, ls.base.scale);
putObject(ls.m.model, &ls.base.pos, ls.base.scale, true);
// Potions
foreach(ref LivePotion ls; cd.potions)
putObject(ls.m.model, &ls.base.pos, ls.base.scale);

@ -31,6 +31,7 @@ Decrease SFX Volume=3
Mute Sound=m
Toggle Fullscreen Mode=f
Toggle Battle Music=space
Toggle Physics Mode=t
OGRE Test Action=g
Pause=pause,p
Screen Shot=print_screen
@ -41,3 +42,6 @@ Main Volume=0.7
Music Volume=0.5
SFX Volume=0.5
Enable Music=yes
[Game Files]
GameFile[0]=Morrowind.esm

Loading…
Cancel
Save