forked from mirror/openmw-tes3mp
Started experimenting with Bullet
git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@46 ea6a568a-9f4f-0410-981a-c910a81bb256
This commit is contained in:
parent
4d37d36d1e
commit
1cfaeeb8fc
14 changed files with 371 additions and 53 deletions
23
Makefile
23
Makefile
|
@ -8,14 +8,18 @@ DMD=gdmd -version=Posix
|
||||||
# Some extra flags for niftool and bsatool
|
# Some extra flags for niftool and bsatool
|
||||||
NIFFLAGS=-debug=warnstd -debug=check -debug=statecheck -debug=strict -debug=verbose
|
NIFFLAGS=-debug=warnstd -debug=check -debug=statecheck -debug=strict -debug=verbose
|
||||||
|
|
||||||
# Compiler settings for Ogre + OIS. Change as needed.
|
# Compiler settings for Ogre + OIS.
|
||||||
CF_OIS=$(shell pkg-config --cflags OGRE OIS)
|
CF_OIS=$(shell pkg-config --cflags OGRE OIS)
|
||||||
OGCC=$(CXX) $(CXXFLAGS) $(CF_OIS)
|
OGCC=$(CXX) $(CXXFLAGS) $(CF_OIS)
|
||||||
|
|
||||||
# Compiler settings for ffmpeg. Change as needed.
|
# Compiler settings for ffmpeg.
|
||||||
CF_FFMPEG=$(shell pkg-config --cflags libavcodec libavformat)
|
CF_FFMPEG=$(shell pkg-config --cflags libavcodec libavformat)
|
||||||
AVGCC=$(CXX) $(CXXFLAGS) $(CF_FFMPEG)
|
AVGCC=$(CXX) $(CXXFLAGS) $(CF_FFMPEG)
|
||||||
|
|
||||||
|
# Settings for Bullet
|
||||||
|
CF_BULLET=-Iinclude/bullet
|
||||||
|
BGCC=$(CXX) $(CXXFLAGS) $(CF_BULLET)
|
||||||
|
|
||||||
# Ogre C++ files, on the form ogre/cpp_X.cpp. Only the first file is
|
# Ogre C++ files, on the form ogre/cpp_X.cpp. Only the first file is
|
||||||
# passed to the compiler, the rest are dependencies.
|
# passed to the compiler, the rest are dependencies.
|
||||||
ogre_cpp=ogre framelistener interface overlay bsaarchive
|
ogre_cpp=ogre framelistener interface overlay bsaarchive
|
||||||
|
@ -23,10 +27,14 @@ ogre_cpp=ogre framelistener interface overlay bsaarchive
|
||||||
# FFmpeg files, in the form sound/cpp_X.cpp.
|
# FFmpeg files, in the form sound/cpp_X.cpp.
|
||||||
avcodec_cpp=avcodec
|
avcodec_cpp=avcodec
|
||||||
|
|
||||||
## No modifications should be required below this line. ##
|
# Bullet cpp files
|
||||||
|
bullet_cpp=bullet
|
||||||
|
|
||||||
|
#### No modifications should be required below this line. ####
|
||||||
|
|
||||||
ogre_cpp_files=$(ogre_cpp:%=ogre/cpp_%.cpp)
|
ogre_cpp_files=$(ogre_cpp:%=ogre/cpp_%.cpp)
|
||||||
avcodec_cpp_files=$(avcodec_cpp:%=sound/cpp_%.cpp)
|
avcodec_cpp_files=$(avcodec_cpp:%=sound/cpp_%.cpp)
|
||||||
|
bullet_cpp_files=$(bullet_cpp:%=bullet/cpp_%.cpp)
|
||||||
|
|
||||||
# All object files needed by openmw and esmtool
|
# All object files needed by openmw and esmtool
|
||||||
src := $(wildcard */*.d)
|
src := $(wildcard */*.d)
|
||||||
|
@ -47,7 +55,7 @@ obj_nif := $(src_nif:%.d=nifobjs/%.o)
|
||||||
all: openmw esmtool niftool bsatool bored
|
all: openmw esmtool niftool bsatool bored
|
||||||
|
|
||||||
# Only build C++ sources. Used when building from DSSS.
|
# Only build C++ sources. Used when building from DSSS.
|
||||||
cpp: cpp_ogre.o cpp_avcodec.o
|
cpp: cpp_ogre.o cpp_avcodec.o cpp_bullet.o
|
||||||
|
|
||||||
cpp_ogre.o: $(ogre_cpp_files)
|
cpp_ogre.o: $(ogre_cpp_files)
|
||||||
$(OGCC) -c $<
|
$(OGCC) -c $<
|
||||||
|
@ -55,6 +63,9 @@ cpp_ogre.o: $(ogre_cpp_files)
|
||||||
cpp_avcodec.o: $(avcodec_cpp_files)
|
cpp_avcodec.o: $(avcodec_cpp_files)
|
||||||
$(AVGCC) -c $<
|
$(AVGCC) -c $<
|
||||||
|
|
||||||
|
cpp_bullet.o: $(bullet_cpp_files)
|
||||||
|
$(BGCC) -c $<
|
||||||
|
|
||||||
objs/%.o: %.d
|
objs/%.o: %.d
|
||||||
dirname $@ | xargs mkdir -p
|
dirname $@ | xargs mkdir -p
|
||||||
$(DMD) -c $< -of$@
|
$(DMD) -c $< -of$@
|
||||||
|
@ -63,8 +74,8 @@ nifobjs/%.o: %.d
|
||||||
dirname $@ | xargs mkdir -p
|
dirname $@ | xargs mkdir -p
|
||||||
$(DMD) $(NIFFLAGS) -c $< -of$@
|
$(DMD) $(NIFFLAGS) -c $< -of$@
|
||||||
|
|
||||||
openmw: openmw.d cpp_ogre.o cpp_avcodec.o $(obj)
|
openmw: openmw.d cpp_ogre.o cpp_avcodec.o cpp_bullet.o $(obj)
|
||||||
$(DMD) $^ -of$@ -L-lopenal -L-lOgreMain -L-lOIS -L-lavcodec -L-lavformat
|
$(DMD) $^ -of$@ -L-lopenal -L-lOgreMain -L-lOIS -L-lavcodec -L-lavformat bullet/libBulletDynamics.a bullet/libBulletCollision.a bullet/libLinearMath.a
|
||||||
|
|
||||||
esmtool: esmtool.d cpp_ogre.o cpp_avcodec.o $(obj)
|
esmtool: esmtool.d cpp_ogre.o cpp_avcodec.o $(obj)
|
||||||
$(DMD) $^ -of$@ -L-lopenal -L-lOgreMain -L-lOIS -L-lavcodec -L-lavformat
|
$(DMD) $^ -of$@ -L-lopenal -L-lOgreMain -L-lOIS -L-lavcodec -L-lavformat
|
||||||
|
|
43
bullet/bindings.d
Normal file
43
bullet/bindings.d
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (bindings.d) is part of the OpenMW package.
|
||||||
|
|
||||||
|
OpenMW is distributed as free software: you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License
|
||||||
|
version 3, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
version 3 along with this program. If not, see
|
||||||
|
http://www.gnu.org/licenses/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module bullet.bindings;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This module is the interface between D and the C++ code that
|
||||||
|
* handles Bullet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern(C):
|
||||||
|
|
||||||
|
// Initialize the dynamic world. Returns non-zero if an error occurs.
|
||||||
|
int cpp_initBullet();
|
||||||
|
void cpp_timeStep(float delta);
|
||||||
|
void cpp_cleanupBullet();
|
||||||
|
|
||||||
|
// Insert a debug collision object
|
||||||
|
void cpp_insertBox(float x, float y, float z);
|
||||||
|
|
||||||
|
// Move the player's collision shape
|
||||||
|
int cpp_movePlayerCollision(float x, float y, float z,
|
||||||
|
float dx, float dy, float dz);
|
11
bullet/bullet.d
Normal file
11
bullet/bullet.d
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
module bullet.bullet;
|
||||||
|
|
||||||
|
import bullet.bindings;
|
||||||
|
|
||||||
|
void initBullet()
|
||||||
|
{
|
||||||
|
if(cpp_initBullet())
|
||||||
|
throw new Exception("Bullet setup failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanupBullet() { cpp_cleanupBullet(); }
|
196
bullet/cpp_bullet.cpp
Normal file
196
bullet/cpp_bullet.cpp
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
#include "btBulletCollisionCommon.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
btDefaultCollisionConfiguration* m_collisionConfiguration;
|
||||||
|
btCollisionDispatcher *m_dispatcher;
|
||||||
|
btBroadphaseInterface *m_broadphase;
|
||||||
|
//btSequentialImpulseConstraintSolver* m_solver;
|
||||||
|
//btDynamicsWorld *m_dynamicsWorld;
|
||||||
|
btCollisionWorld *m_collisionWorld;
|
||||||
|
|
||||||
|
//btCollisionObject* m_playerObject;
|
||||||
|
btConvexShape *playerShape;
|
||||||
|
|
||||||
|
extern "C" int32_t cpp_initBullet()
|
||||||
|
{
|
||||||
|
// Set up basic objects
|
||||||
|
m_collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||||
|
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
|
||||||
|
m_broadphase = new btDbvtBroadphase();
|
||||||
|
m_collisionWorld =
|
||||||
|
new btCollisionWorld(m_dispatcher, m_broadphase,
|
||||||
|
m_collisionConfiguration);
|
||||||
|
|
||||||
|
/*m_solver = new btSequentialImpulseConstraintSolver;
|
||||||
|
m_dynamicsWorld =
|
||||||
|
new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase,
|
||||||
|
m_solver, m_collisionConfiguration);
|
||||||
|
m_dynamicsWorld->setGravity(btVector3(0,-10,0));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Create player collision object
|
||||||
|
//playerShape = new btCylinderShape(btVector3(50, 50, 50));
|
||||||
|
playerShape = new btSphereShape(50);
|
||||||
|
|
||||||
|
/*
|
||||||
|
m_playerObject = new btCollisionObject ();
|
||||||
|
m_playerObject->setCollisionShape (m_shape);
|
||||||
|
m_playerObject->setCollisionFlags (btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Dynamic shapes:
|
||||||
|
|
||||||
|
// Re-using the same collision is better for memory usage and
|
||||||
|
// performance.
|
||||||
|
|
||||||
|
btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
|
||||||
|
//btCollisionShape* colShape = new btSphereShape(btScalar(1.));
|
||||||
|
//m_collisionShapes.push_back(colShape);
|
||||||
|
|
||||||
|
// Create Dynamic Objects
|
||||||
|
btTransform startTransform;
|
||||||
|
startTransform.setIdentity();
|
||||||
|
|
||||||
|
mass = 1.f;
|
||||||
|
|
||||||
|
colShape->calculateLocalInertia(mass,localInertia);
|
||||||
|
|
||||||
|
///create 125 (5x5x5) dynamic objects
|
||||||
|
#define ARRAY_SIZE_X 5
|
||||||
|
#define ARRAY_SIZE_Y 5
|
||||||
|
#define ARRAY_SIZE_Z 5
|
||||||
|
|
||||||
|
#define START_POS_X -5
|
||||||
|
#define START_POS_Y -5
|
||||||
|
#define START_POS_Z -3
|
||||||
|
|
||||||
|
float start_x = START_POS_X - ARRAY_SIZE_X/2;
|
||||||
|
float start_y = START_POS_Y;
|
||||||
|
float start_z = START_POS_Z - ARRAY_SIZE_Z/2;
|
||||||
|
|
||||||
|
for (int k=0;k<ARRAY_SIZE_Y;k++)
|
||||||
|
for (int i=0;i<ARRAY_SIZE_X;i++)
|
||||||
|
for(int j = 0;j<ARRAY_SIZE_Z;j++)
|
||||||
|
{
|
||||||
|
startTransform.setOrigin(btVector3(2.0*i + start_x,
|
||||||
|
10+2.0*k + start_y,
|
||||||
|
2.0*j + start_z));
|
||||||
|
|
||||||
|
btDefaultMotionState* myMotionState =
|
||||||
|
new btDefaultMotionState(startTransform);
|
||||||
|
|
||||||
|
btRigidBody::btRigidBodyConstructionInfo
|
||||||
|
rbInfo(mass,myMotionState,colShape,localInertia);
|
||||||
|
|
||||||
|
btRigidBody* body = new btRigidBody(rbInfo);
|
||||||
|
body->setActivationState(ISLAND_SLEEPING);
|
||||||
|
|
||||||
|
m_dynamicsWorld->addRigidBody(body);
|
||||||
|
body->setActivationState(ISLAND_SLEEPING);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int32_t cpp_movePlayerCollision(float x, float y, float z,
|
||||||
|
float dx, float dy, float dz)
|
||||||
|
{
|
||||||
|
btTransform start, end;
|
||||||
|
start.setIdentity();
|
||||||
|
end.setIdentity();
|
||||||
|
|
||||||
|
// The sweep test moves the shape from the old position to the
|
||||||
|
// new. The 0.1 offset in one of the coordinates is to make sure a
|
||||||
|
// sweep is performed even when the player does not move.
|
||||||
|
start.setOrigin(btVector3(x, y, z));
|
||||||
|
end.setOrigin(btVector3(x+dx,y+dy,z+dz));
|
||||||
|
|
||||||
|
btCollisionWorld::ClosestConvexResultCallback cb(btVector3(0,0,0),
|
||||||
|
btVector3(0,0,0));
|
||||||
|
|
||||||
|
m_collisionWorld->convexSweepTest(playerShape, start, end, cb);
|
||||||
|
|
||||||
|
if(cb.hasHit()) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void cpp_insertBox(float x, float y, float z)
|
||||||
|
{
|
||||||
|
btCollisionShape* groundShape =
|
||||||
|
new btSphereShape(50);
|
||||||
|
//new btBoxShape(btVector3(100,100,100));
|
||||||
|
|
||||||
|
btTransform groundTransform;
|
||||||
|
groundTransform.setIdentity();
|
||||||
|
groundTransform.setOrigin(btVector3(x,y,z));
|
||||||
|
|
||||||
|
btCollisionObject *obj = new btCollisionObject;
|
||||||
|
obj->setCollisionShape(groundShape);
|
||||||
|
obj->setWorldTransform(groundTransform);
|
||||||
|
|
||||||
|
m_collisionWorld->addCollisionObject(obj);
|
||||||
|
|
||||||
|
/*
|
||||||
|
m_collisionWorld->addCollisionObject(obj,
|
||||||
|
btBroadphaseProxy::DebrisFilter, // ??
|
||||||
|
btBroadphaseProxy::StaticFilter); // Only static objects
|
||||||
|
|
||||||
|
/*
|
||||||
|
btDefaultMotionState* myMotionState =
|
||||||
|
new btDefaultMotionState(groundTransform);
|
||||||
|
|
||||||
|
btRigidBody::btRigidBodyConstructionInfo
|
||||||
|
rbInfo(0, myMotionState, groundShape, btVector3(0,0,0));
|
||||||
|
|
||||||
|
btRigidBody* body = new btRigidBody(rbInfo);
|
||||||
|
|
||||||
|
// Add the body to the dynamics world
|
||||||
|
m_dynamicsWorld->addRigidBody(body);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
extern "C" void cpp_timeStep(float delta)
|
||||||
|
{
|
||||||
|
// TODO: Find what unit Bullet uses here
|
||||||
|
m_dynamicsWorld->stepSimulation(delta / 1000.f);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Cleanup in the reverse order of creation/initialization
|
||||||
|
extern "C" void cpp_cleanupBullet()
|
||||||
|
{
|
||||||
|
// Remove the rigidbodies from the dynamics world and delete them
|
||||||
|
for (int i=m_collisionWorld->getNumCollisionObjects()-1; i>=0 ;i--)
|
||||||
|
{
|
||||||
|
btCollisionObject* obj = m_collisionWorld->getCollisionObjectArray()[i];
|
||||||
|
/*
|
||||||
|
btRigidBody* body = btRigidBody::upcast(obj);
|
||||||
|
|
||||||
|
if (body && body->getMotionState())
|
||||||
|
delete body->getMotionState();
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_collisionWorld->removeCollisionObject( obj );
|
||||||
|
delete obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete collision shapes
|
||||||
|
/*
|
||||||
|
for (int j=0;j<m_collisionShapes.size();j++)
|
||||||
|
{
|
||||||
|
btCollisionShape* shape = m_collisionShapes[j];
|
||||||
|
delete shape;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
delete m_collisionWorld;
|
||||||
|
//delete m_solver;
|
||||||
|
delete m_broadphase;
|
||||||
|
delete m_dispatcher;
|
||||||
|
delete m_collisionConfiguration;
|
||||||
|
}
|
|
@ -334,8 +334,6 @@ struct ResourceManager
|
||||||
assert(ti.bsaFile == -1);
|
assert(ti.bsaFile == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ti.ml = null;
|
|
||||||
|
|
||||||
textureLookup[ti.name] = ti;
|
textureLookup[ti.name] = ti;
|
||||||
|
|
||||||
return ti;
|
return ti;
|
||||||
|
@ -447,7 +445,6 @@ struct TextureResource
|
||||||
int bsaFile; // If set to -1, the file is in the file system
|
int bsaFile; // If set to -1, the file is in the file system
|
||||||
int bsaIndex;
|
int bsaIndex;
|
||||||
char[] type; // Texture format, eg "tga" or "dds";
|
char[] type; // Texture format, eg "tga" or "dds";
|
||||||
ManualLoader ml;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -460,11 +457,13 @@ struct TextureResource
|
||||||
return bsaIndex == -1;
|
return bsaIndex == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*KILLME
|
||||||
// Returns true if resource is loaded
|
// Returns true if resource is loaded
|
||||||
bool isLoaded()
|
bool isLoaded()
|
||||||
{
|
{
|
||||||
return ml != null;
|
return ml != null;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// OLD STUFF
|
// OLD STUFF
|
||||||
|
@ -495,11 +494,5 @@ struct TextureResource
|
||||||
|
|
||||||
writefln(" Done\n");
|
writefln(" Done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void killBSAs()
|
|
||||||
{
|
|
||||||
foreach(BSAFile f; archives)
|
|
||||||
delete f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+/
|
+/
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
[openmw.d]
|
[openmw.d]
|
||||||
# Add libraries and the two C++ object files
|
# Add libraries and the two C++ object files
|
||||||
buildflags = -llOgreMain -llopenal -llOIS -llavcodec -llavformat cpp_ogre.o cpp_avcodec.o
|
buildflags = -llOgreMain -llopenal -llOIS -llavcodec -llavformat cpp_ogre.o cpp_avcodec.o cpp_bullet.o bullet/libBulletDynamics.a bullet/libBulletCollision.a bullet/libLinearMath.a
|
||||||
|
|
||||||
# Make sure the C++ object files are built first
|
# Make sure the C++ object files are built first
|
||||||
version(Windows) {
|
version(Windows) {
|
||||||
|
@ -34,7 +34,7 @@ prebuild += dsss clean niftool
|
||||||
[esmtool.d]
|
[esmtool.d]
|
||||||
# Because of interdepencies between the ESM code and the resource
|
# Because of interdepencies between the ESM code and the resource
|
||||||
# manager, we have to include all the C++ stuff.
|
# manager, we have to include all the C++ stuff.
|
||||||
buildflags = -llOgreMain -llopenal -llOIS -llavcodec -llavformat cpp_ogre.o cpp_avcodec.o
|
buildflags = -llOgreMain -llopenal -llOIS -llavcodec -llavformat cpp_ogre.o cpp_avcodec.o cpp_bullet.o bullet/libBulletDynamics.a bullet/libBulletCollision.a bullet/libLinearMath.a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -557,6 +557,13 @@ struct TES3File
|
||||||
file.seekCur(leftSub);
|
file.seekCur(leftSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the name and size before skipping
|
||||||
|
void skipHNSub(char[] name, uint size)
|
||||||
|
{
|
||||||
|
getSubNameIs(name);
|
||||||
|
skipHSubSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
// These read an entire sub-record, including the header. They also
|
// These read an entire sub-record, including the header. They also
|
||||||
// adjust and check leftSub and leftRecord variables through calling
|
// adjust and check leftSub and leftRecord variables through calling
|
||||||
// getSubHeader().
|
// getSubHeader().
|
||||||
|
|
|
@ -123,9 +123,9 @@ struct ExteriorCell
|
||||||
|
|
||||||
struct ExtCellHash
|
struct ExtCellHash
|
||||||
{
|
{
|
||||||
// This is a pretty good hash, gives no collisions at all for
|
// This is a pretty good hash, gives no collisions for all of
|
||||||
// Morrowind.esm and a table size of 2048, and very few collisions
|
// Morrowind.esm when the table size is 2048, and it gives very few
|
||||||
// overall. Not that it matters of course.
|
// collisions overall. Not that it matters that much.
|
||||||
static uint hash(uint val)
|
static uint hash(uint val)
|
||||||
{
|
{
|
||||||
uint res = cast(ushort)val;
|
uint res = cast(ushort)val;
|
||||||
|
@ -304,8 +304,7 @@ struct Land
|
||||||
// Save file position
|
// Save file position
|
||||||
getContext(context);
|
getContext(context);
|
||||||
|
|
||||||
// TODO: We don't decode these yet. Se ESLand.h from
|
// Skip these here. Load the actual data when the cell is loaded.
|
||||||
// Morrowindremake for a lot of hints.
|
|
||||||
if(isNextSub("VNML")) skipHSubSize(12675);
|
if(isNextSub("VNML")) skipHSubSize(12675);
|
||||||
if(isNextSub("VHGT")) skipHSubSize(4232);
|
if(isNextSub("VHGT")) skipHSubSize(4232);
|
||||||
if(isNextSub("WNAM")) skipHSubSize(81);
|
if(isNextSub("WNAM")) skipHSubSize(81);
|
||||||
|
@ -342,7 +341,8 @@ struct PathGrid
|
||||||
assert(state == LoadState.Unloaded);
|
assert(state == LoadState.Unloaded);
|
||||||
|
|
||||||
readHNExact(&data, data.sizeof, "DATA");
|
readHNExact(&data, data.sizeof, "DATA");
|
||||||
getHNString("NAME"); // Cell name, we don't really need it.
|
getHNString("NAME"); // Cell name, we don't really need it so just
|
||||||
|
// ignore it.
|
||||||
|
|
||||||
// Remember this file position
|
// Remember this file position
|
||||||
getContext(context);
|
getContext(context);
|
||||||
|
@ -352,7 +352,7 @@ struct PathGrid
|
||||||
{
|
{
|
||||||
int size = skipHSub();
|
int size = skipHSub();
|
||||||
if(size != 16*data.s2)
|
if(size != 16*data.s2)
|
||||||
fail("Path grid table size");
|
fail("Path grid table size mismatch");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size varies. Path grid chances? Connections? Multiples of 4
|
// Size varies. Path grid chances? Connections? Multiples of 4
|
||||||
|
|
|
@ -33,6 +33,8 @@ import core.config;
|
||||||
import scene.soundlist;
|
import scene.soundlist;
|
||||||
import scene.player;
|
import scene.player;
|
||||||
|
|
||||||
|
import bullet.bindings;
|
||||||
|
|
||||||
import ogre.bindings;
|
import ogre.bindings;
|
||||||
|
|
||||||
import input.keys;
|
import input.keys;
|
||||||
|
@ -246,6 +248,10 @@ void initializeInput()
|
||||||
{
|
{
|
||||||
cpp_moveCamera(position[0], position[1], position[2],
|
cpp_moveCamera(position[0], position[1], position[2],
|
||||||
rotation[0], rotation[1], rotation[2]);
|
rotation[0], rotation[1], rotation[2]);
|
||||||
|
|
||||||
|
// Insert a collision box close to the player
|
||||||
|
cpp_insertBox(position[0], position[1]+500, position[2]);
|
||||||
|
cpp_drawBox(position[0], position[1]+500, position[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO/FIXME: This should have been in config, but DMD's module
|
// TODO/FIXME: This should have been in config, but DMD's module
|
||||||
|
@ -294,29 +300,41 @@ extern(C) int d_frameStarted(float time)
|
||||||
if(pause) return 1;
|
if(pause) return 1;
|
||||||
|
|
||||||
const float moveSpeed = 900;
|
const float moveSpeed = 900;
|
||||||
|
float speed = moveSpeed * time;
|
||||||
|
|
||||||
// Check if the movement keys are pressed
|
// Check if the movement keys are pressed
|
||||||
float moveX = 0, moveY = 0, moveZ = 0;
|
float moveX = 0, moveY = 0, moveZ = 0;
|
||||||
|
float x, y, z;
|
||||||
|
|
||||||
if(isPressed(Keys.MoveLeft)) moveX -= moveSpeed;
|
if(isPressed(Keys.MoveLeft)) moveX -= speed;
|
||||||
if(isPressed(Keys.MoveRight)) moveX += moveSpeed;
|
if(isPressed(Keys.MoveRight)) moveX += speed;
|
||||||
if(isPressed(Keys.MoveForward)) moveZ -= moveSpeed;
|
if(isPressed(Keys.MoveForward)) moveZ -= speed;
|
||||||
if(isPressed(Keys.MoveBackward)) moveZ += moveSpeed;
|
if(isPressed(Keys.MoveBackward)) moveZ += speed;
|
||||||
if(isPressed(Keys.MoveUp)) moveY += moveSpeed;
|
if(isPressed(Keys.MoveUp)) moveY += speed;
|
||||||
if(isPressed(Keys.MoveDown)) moveY -= moveSpeed;
|
if(isPressed(Keys.MoveDown)) moveY -= speed;
|
||||||
|
|
||||||
// Move camera. We only support "ghost-mode" at the moment, so we
|
// Move the player. This is a temporary hack, we should do this more
|
||||||
// move without physics or collision detection.
|
// efficiently in C++.
|
||||||
cpp_moveCameraRel(moveX*time, moveY*time, moveZ*time);
|
if(moveX != 0 || moveY !=0 || moveZ != 0)
|
||||||
|
{
|
||||||
|
cpp_moveCameraRel(moveX, moveY, moveZ);
|
||||||
|
cpp_getCameraPos(&x, &y, &z);
|
||||||
|
bool nw = cpp_movePlayerCollision(x, y, z, moveX, moveY, moveZ) != 0;
|
||||||
|
|
||||||
|
if(nw != collides)
|
||||||
|
{
|
||||||
|
if(nw) writefln("Entered shape");
|
||||||
|
else writefln("Left shape");
|
||||||
|
collides = nw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sndCumTime += time;
|
sndCumTime += time;
|
||||||
if(sndCumTime > sndRefresh)
|
if(sndCumTime > sndRefresh)
|
||||||
{
|
{
|
||||||
float x, y, z;
|
|
||||||
float fx, fy, fz;
|
float fx, fy, fz;
|
||||||
float ux, uy, uz;
|
float ux, uy, uz;
|
||||||
|
|
||||||
cpp_getCameraPos(&x, &y, &z);
|
|
||||||
cpp_getCameraOrientation(&fx, &fy, &fz, &ux, &uy, &uz);
|
cpp_getCameraOrientation(&fx, &fy, &fz, &ux, &uy, &uz);
|
||||||
|
|
||||||
soundScene.update(x,y,z,fx,fy,fz,ux,uy,uz);
|
soundScene.update(x,y,z,fx,fy,fz,ux,uy,uz);
|
||||||
|
@ -326,3 +344,4 @@ extern(C) int d_frameStarted(float time)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool collides = false;
|
||||||
|
|
|
@ -45,9 +45,6 @@ import core.resource;
|
||||||
// these directly in D code, only pass them back to the C++ code.
|
// these directly in D code, only pass them back to the C++ code.
|
||||||
typedef void* NodePtr;
|
typedef void* NodePtr;
|
||||||
|
|
||||||
// Pointer to a manual loader class in C++.
|
|
||||||
typedef void* ManualLoader;
|
|
||||||
|
|
||||||
extern(C):
|
extern(C):
|
||||||
|
|
||||||
// Do engine configuration. Returns 0 if we should continue, 1 if
|
// Do engine configuration. Returns 0 if we should continue, 1 if
|
||||||
|
@ -152,3 +149,6 @@ void cpp_moveCameraRel(float x, float y, float z);
|
||||||
|
|
||||||
// Do some debug action. Check the menu for today's specials!
|
// Do some debug action. Check the menu for today's specials!
|
||||||
void cpp_debug(int i);
|
void cpp_debug(int i);
|
||||||
|
|
||||||
|
// Insert a 100x100x100 axis-aligned cube at x,y,z
|
||||||
|
void cpp_drawBox(float x, float y, float z);
|
||||||
|
|
|
@ -146,11 +146,13 @@ extern "C" void cpp_getCameraOrientation(float *fx, float *fy, float *fz,
|
||||||
*uz = up[1];
|
*uz = up[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move and rotate camera in place. Transforms Morrowind coordinates
|
// Move and rotate camera in place.
|
||||||
// to OGRE coordinates.
|
|
||||||
extern "C" void cpp_moveCamera(float x, float y, float z,
|
extern "C" void cpp_moveCamera(float x, float y, float z,
|
||||||
float r1, float r2, float r3)
|
float r1, float r2, float r3)
|
||||||
{
|
{
|
||||||
|
// Transforms Morrowind coordinates to OGRE coordinates. The camera
|
||||||
|
// is not affected by the rotation of the root node, so we must
|
||||||
|
// transform this manually.
|
||||||
mCamera->setPosition(Vector3(x,z,-y));
|
mCamera->setPosition(Vector3(x,z,-y));
|
||||||
|
|
||||||
// Rotation is probably not correct, but for now I have no reference
|
// Rotation is probably not correct, but for now I have no reference
|
||||||
|
|
|
@ -56,3 +56,23 @@ SceneNode *root;
|
||||||
#include "cpp_bsaarchive.cpp"
|
#include "cpp_bsaarchive.cpp"
|
||||||
#include "cpp_interface.cpp"
|
#include "cpp_interface.cpp"
|
||||||
#include "cpp_overlay.cpp"
|
#include "cpp_overlay.cpp"
|
||||||
|
|
||||||
|
// Testing
|
||||||
|
extern "C" void cpp_drawBox(float x, float y, float z)
|
||||||
|
{
|
||||||
|
// Create a plane aligned with the xy-plane.
|
||||||
|
/*
|
||||||
|
MeshManager::getSingleton().createPlane("box1",
|
||||||
|
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||||
|
Plane(Vector3::UNIT_X, 0),
|
||||||
|
100,100);
|
||||||
|
Entity *ent = mSceneMgr->createEntity( "box", "box1" );
|
||||||
|
*/
|
||||||
|
|
||||||
|
Entity *ent = mSceneMgr->createEntity( "box", SceneManager::PT_SPHERE);
|
||||||
|
ent->setCastShadows(false);
|
||||||
|
SceneNode *nd = root->createChildSceneNode();
|
||||||
|
nd->attachObject(ent);
|
||||||
|
//nd->setScale(0.5, 0.5, 0.5);
|
||||||
|
nd->setPosition(x,y,z);
|
||||||
|
}
|
||||||
|
|
9
openmw.d
9
openmw.d
|
@ -31,6 +31,8 @@ import std.file;
|
||||||
import ogre.ogre;
|
import ogre.ogre;
|
||||||
import ogre.bindings;
|
import ogre.bindings;
|
||||||
|
|
||||||
|
import bullet.bullet;
|
||||||
|
|
||||||
import scene.celldata;
|
import scene.celldata;
|
||||||
import scene.soundlist;
|
import scene.soundlist;
|
||||||
|
|
||||||
|
@ -219,10 +221,13 @@ void main(char[][] args)
|
||||||
{
|
{
|
||||||
// Warm up OGRE
|
// Warm up OGRE
|
||||||
setupOgre();
|
setupOgre();
|
||||||
|
|
||||||
// Clean up ogre when we're finished.
|
|
||||||
scope(exit) cleanupOgre();
|
scope(exit) cleanupOgre();
|
||||||
|
|
||||||
|
// Set up Bullet
|
||||||
|
initBullet();
|
||||||
|
scope(exit) cleanupBullet();
|
||||||
|
|
||||||
|
|
||||||
if(cd.inCell)
|
if(cd.inCell)
|
||||||
{
|
{
|
||||||
setAmbient(cd.ambi.ambient, cd.ambi.sunlight,
|
setAmbient(cd.ambi.ambient, cd.ambi.sunlight,
|
||||||
|
|
|
@ -39,7 +39,8 @@ import sound.audio;
|
||||||
import scene.player;
|
import scene.player;
|
||||||
|
|
||||||
// Base properties common to all live objects. Currently extremely
|
// Base properties common to all live objects. Currently extremely
|
||||||
// sketchy.
|
// sketchy. TODO: This will all be handled in Monster script at some
|
||||||
|
// point.
|
||||||
struct LiveObjectBase
|
struct LiveObjectBase
|
||||||
{
|
{
|
||||||
// Should this stuff be in here?
|
// Should this stuff be in here?
|
||||||
|
@ -92,7 +93,7 @@ struct LiveObjectBase
|
||||||
// ??
|
// ??
|
||||||
byte unam;
|
byte unam;
|
||||||
|
|
||||||
// Don't even get me started on script-related issues
|
// TODO: Scripts
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic version of a "live" object
|
// Generic version of a "live" object
|
||||||
|
@ -223,6 +224,21 @@ class CellData
|
||||||
|
|
||||||
loadReferences();
|
loadReferences();
|
||||||
|
|
||||||
|
// TODO: Set up landscape system here.
|
||||||
|
/*
|
||||||
|
with(esFile)
|
||||||
|
{
|
||||||
|
restoreContext(exCell.land.context, reg);
|
||||||
|
|
||||||
|
// TODO: Not all of these will be present at all times
|
||||||
|
readHNExact(,12675, "VNML");
|
||||||
|
readHNExact(,4232, "VHGT");
|
||||||
|
readHNExact(,81, "WNAM");
|
||||||
|
readHNExact(,12675, "VCLR");
|
||||||
|
readHNExact(,512, "VTEX");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
const float cellWidth = 8192;
|
const float cellWidth = 8192;
|
||||||
|
|
||||||
// TODO/FIXME: This is temporary
|
// TODO/FIXME: This is temporary
|
||||||
|
@ -243,7 +259,7 @@ class CellData
|
||||||
|
|
||||||
esFile.restoreContext(inCell.context, reg);
|
esFile.restoreContext(inCell.context, reg);
|
||||||
|
|
||||||
// TODO: Read this crap in loadcell.d
|
// TODO: Read this in loadcell.d
|
||||||
if(esFile.isNextSub("INTV") || esFile.isNextSub("WHGT"))
|
if(esFile.isNextSub("INTV") || esFile.isNextSub("WHGT"))
|
||||||
water = esFile.getHInt();
|
water = esFile.getHInt();
|
||||||
//writefln("Water height: ", water);
|
//writefln("Water height: ", water);
|
||||||
|
@ -555,12 +571,6 @@ class CellData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip this? Large chance that the same file will be used for
|
|
||||||
// the next cell load, and the rest of our system can handle
|
|
||||||
// that without closing or reopening the file.
|
|
||||||
|
|
||||||
//close(); // Close the file
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,8 +592,9 @@ struct CellFreelist
|
||||||
if(next) return list[--next];
|
if(next) return list[--next];
|
||||||
|
|
||||||
// Since these are reused, there's no waste in allocating on the
|
// Since these are reused, there's no waste in allocating on the
|
||||||
// stack here. Also, this is only semi-runtime (executed when
|
// heap here. Also, this is only semi-runtime (executed when
|
||||||
// loading a cell), thus a rare GC slow down is non-critical.
|
// loading a cell), thus an occational GC slow down is not
|
||||||
|
// critical.
|
||||||
return new CellData(new RegionManager("CELL"));
|
return new CellData(new RegionManager("CELL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue