[DEV] Change the bounding to the old AABB methode and start the catching of the tunel effects

This commit is contained in:
Edouard DUPIN 2013-01-04 22:52:56 +01:00
parent 93d3e62b8e
commit a468a3424a
8 changed files with 216 additions and 62 deletions

2
external/etk vendored

@ -1 +1 @@
Subproject commit 3b5aa7b84f5f41c72eccf3c2fecb6f8404401e9b
Subproject commit 52d5bd18102bed9321a620e29581c480d084d44d

View File

@ -13,10 +13,9 @@
game::BoundingAABB::BoundingAABB(void) :
m_hasContact(false),
m_center(0,0,0),
m_size(1,1,1),
m_oldUserPosition(0,0,0)
m_PointStart(-1,-1,-1),
m_PointStop(1,1,1),
m_hasContact(false)
{
#ifdef DEBUG
if (false == ewol::resource::Keep(m_displayBounding) ) {
@ -39,44 +38,38 @@ game::BoundingAABB::~BoundingAABB(void)
void game::BoundingAABB::Update(game::MeshObject& object, mat4& rotation, vec3& position, vec3& scale)
{
vec3 pointStart;
vec3 pointStop;
mat4 transformMatrix = etk::matTranslate(position)
* etk::matScale(scale)
* rotation;
for (int32_t iii=0; iii<object.m_vertices.Size(); iii++) {
vec3 point = transformMatrix * object.m_vertices[iii];
if (0 == iii) {
pointStart = point;
pointStop = point;
m_PointStart = point;
m_PointStop = point;
} else {
if (pointStart.x > point.x) {
pointStart.x = point.x;
} else if (pointStop.x < point.x) {
pointStop.x = point.x;
if (m_PointStart.x > point.x) {
m_PointStart.x = point.x;
} else if (m_PointStop.x < point.x) {
m_PointStop.x = point.x;
}
if (pointStart.y > point.y) {
pointStart.y = point.y;
} else if (pointStop.y < point.y) {
pointStop.y = point.y;
if (m_PointStart.y > point.y) {
m_PointStart.y = point.y;
} else if (m_PointStop.y < point.y) {
m_PointStop.y = point.y;
}
if (pointStart.z > point.z) {
pointStart.z = point.z;
} else if (pointStop.z < point.z) {
pointStop.z = point.z;
if (m_PointStart.z > point.z) {
m_PointStart.z = point.z;
} else if (m_PointStop.z < point.z) {
m_PointStop.z = point.z;
}
}
}
m_size = (pointStop - pointStart) / 2;
m_center = pointStop - m_size;
m_oldUserPosition = position;
#ifdef DEBUG
vec3 tmpBB(0.001,0.001,0.001);
vec3 tmpStart = pointStart - tmpBB;
vec3 tmpStop = pointStop + tmpBB;
vec3 tmpStart = m_PointStart - tmpBB;
vec3 tmpStop = m_PointStop + tmpBB;
// (start) X / Y
vec3 tmpPos = tmpStart;
m_vertices[0] = tmpStart;
@ -179,12 +172,16 @@ void game::BoundingAABB::Draw(void)
bool game::BoundingAABB::HasContact(game::BoundingAABB& obj)
{
if( (abs(m_center.x-obj.m_center.x) > m_size.x+obj.m_size.x)
|| (abs(m_center.y-obj.m_center.y) > m_size.y+obj.m_size.y)
|| (abs(m_center.z-obj.m_center.z) > m_size.z+obj.m_size.z) ) {
if( m_PointStart.x > obj.m_PointStop.x
|| m_PointStop.x < obj.m_PointStart.x
|| m_PointStart.y > obj.m_PointStop.y
|| m_PointStop.y < obj.m_PointStart.y
|| m_PointStart.z > obj.m_PointStop.z
|| m_PointStop.z < obj.m_PointStart.z) {
return false;
}
return true;
}

View File

@ -18,9 +18,9 @@ namespace game
class BoundingAABB
{
private :
vec3 m_PointStart;
vec3 m_PointStop;
bool m_hasContact; //!< this bounding is on contact with something else ...
vec3 m_center;
vec3 m_size;
vec3 m_oldUserPosition; // this is due to the fact object are never centered ...
#ifdef DEBUG
ewol::Colored3DObject* m_displayBounding;
@ -55,6 +55,8 @@ namespace game
* @brief Get the current contact status
*/
bool GetContactStatus(void) { return m_hasContact; };
vec3 Size(void) { return m_PointStop-m_PointStart; };
};
}

View File

@ -9,12 +9,14 @@
#include <ewol/game/Element.h>
#include <ewol/game/Engine.h>
#include <ewol/renderer/ResourceManager.h>
static int32_t uniqueId = 0;
game::Element::Element(etk::UString meshResource) :
m_engine(NULL),
m_resource(NULL),
m_matrixNeedUpdate(true),
m_scale(1,1,1),
@ -23,7 +25,8 @@ game::Element::Element(etk::UString meshResource) :
m_uniqueId(uniqueId),
m_groupId(0),
m_type(0),
m_visible(true)
m_visible(true),
m_static(false)
{
ewol::MeshObj* tmpObject = NULL;
// get a resources :
@ -99,11 +102,56 @@ void game::Element::ProcessPosition(float delta)
vec3 curentAcceleration(m_gravityForce + m_userAcceleration);
m_speed += curentAcceleration*delta;
vec3 tmpPos = m_position +m_speed*delta;
// TODO : Detect collision of other elements ...
if (m_position != tmpPos) {
// TODO : Detect collision of other elements ...
vec3 size = m_bounding.Size();
vec3 move = tmpPos - m_position;
vec3 moveAbs = move;
moveAbs.Abs();
if( ( 0 < size.x
&& moveAbs.x > 2*size.x )
|| ( 0 < size.y
&& moveAbs.y > 2*size.y )
|| ( 0 < size.z
&& moveAbs.z > 2*size.z )) {
int32_t maxIterations = 0;
// generate a subdivide channel to prevent tunel effects ...
// Get the smallest axis to test :
if( moveAbs.x >= moveAbs.y
&& moveAbs.x >= moveAbs.z) {
//Test on X :
//estimate the number of subdivision needed in recursive mode :
maxIterations = moveAbs.x/abs(size.x);
EWOL_DEBUG("XXX move with dist=" << move << "m <" << size*2 << "m");
} else if ( moveAbs.y >= moveAbs.x
&& moveAbs.y >= moveAbs.z) {
//Test on Y :
//estimate the number of subdivision needed in recursive mode :
maxIterations = moveAbs.y/abs(size.y);
EWOL_DEBUG("YYY move with dist=" << move << "m <" << size*2 << "m");
} else {
//Test on Z :
//estimate the number of subdivision needed in recursive mode :
maxIterations = moveAbs.z/abs(size.z);
EWOL_DEBUG("ZZZ move with dist=" << move << "m <" << size*2 << "m");
}
vec3 deltaMove = move/maxIterations;
vec3 tmppppPos = m_position;
game::BoundingAABB tmpBounding;
// linear test :
for (int32_t iii=0; iii<maxIterations-1 ; iii++) {
tmppppPos+=deltaMove;
tmpBounding.Update(m_resource->m_object, m_displayRotation, tmppppPos, m_scale);
if (true == m_engine->HasCollision(tmpBounding, this)) {
tmpPos = tmppppPos;
// the tunnel effect is catch ...
EWOL_CRITICAL("Tunel effect catch : (" << iii << "/" << maxIterations-1 << ")");
break;
}
}
}
m_position = tmpPos;
m_matrixNeedUpdate = true;
//EWOL_DEBUG("modify m_position=" << m_position << "m m_speed=" << m_speed << "m/s m_gravityForce=" << m_gravityForce << "+" << m_userAcceleration << "m/s2");
}
}

View File

@ -20,9 +20,11 @@
namespace game
{
class Engine;
class Element
{
protected:
game::Engine* m_engine;
ewol::Mesh* m_resource; //!< Resource to display the element.
game::BoundingAABB m_bounding; //!< Bounding of this element
private:
@ -45,6 +47,7 @@ namespace game
uint32_t m_groupId; //!< General group Id More than 65000 group can be really interesting to create supid game ...
int32_t m_type; //!< type of this element
bool m_visible; //!< This is to know if the element is displayed or not ==> TODO : check if usefull ...
bool m_static; //!< This element is static...
public:
/**
* @brief Basic constructor.
@ -55,6 +58,11 @@ namespace game
* @brief Basic destructor.
*/
virtual ~Element(void);
/**
* @brief Link with a specific engine.
* @param[in] engine Engine pointer
*/
void SetEngine(game::Engine* engine) { m_engine = engine; };
/**
* @brief Draw the element.
*/
@ -113,6 +121,15 @@ namespace game
m_scale = vect;
m_matrixNeedUpdate = true;
}
/**
* @brief Scale the element to an other size
* @param[in] proportion scale value in all direction ...
*/
void Scale(float proportion)
{
m_scale = vec3(proportion,proportion,proportion);
m_matrixNeedUpdate = true;
}
/**
* @brief Rotate the current object
* @param[in] vect rotation angle
@ -147,6 +164,14 @@ namespace game
{
return m_bounding;
}
/**
* @brief Set this element Static or not
*/
void SetStaticMode(bool newMode) { m_static = newMode; };
/**
* @brief Get the current static or dynamic mode
*/
bool GetStaticMode(void) { return m_static; };
};
};

View File

@ -69,16 +69,19 @@ void game::Engine::ProcessCollision(float deltaTime)
bounding1.SetContactMode(false);
}
}
// Brut force bounding detection :
for (int32_t iii=0; iii<m_elements.Size() ; iii++) {
if (NULL != m_elements[iii]) {
game::BoundingAABB& bounding1 = m_elements[iii]->GetBounding();
for (int32_t jjj=iii+1; jjj<m_elements.Size() ; jjj++) {
if (NULL!=m_elements[jjj]) {
game::BoundingAABB& bounding2 = m_elements[jjj]->GetBounding();
if (true == bounding2.HasContact(bounding1)) {
bounding2.SetContactMode(true);
bounding1.SetContactMode(true);
// If the element is static, the bounding detection is not needed...
if (true) {//false == m_elements[iii]->GetStaticMode()) {
game::BoundingAABB& bounding1 = m_elements[iii]->GetBounding();
for (int32_t jjj=iii+1; jjj<m_elements.Size() ; jjj++) {
if (NULL!=m_elements[jjj]) {
game::BoundingAABB& bounding2 = m_elements[jjj]->GetBounding();
if (true == bounding2.HasContact(bounding1)) {
bounding2.SetContactMode(true);
bounding1.SetContactMode(true);
}
}
}
}
@ -86,6 +89,25 @@ void game::Engine::ProcessCollision(float deltaTime)
}
}
bool game::Engine::HasCollision(game::BoundingAABB& bounding, game::Element* currentElement)
{
// Brut force bounding detection :
for (int32_t iii=0; iii<m_elements.Size() ; iii++) {
if (currentElement == m_elements[iii]) {
continue;
}
if (NULL != m_elements[iii]) {
if (true == bounding.HasContact(m_elements[iii]->GetBounding())) {
return true;
}
}
}
return false;
}
void game::Engine::Draw(ewol::DrawProperty& displayProp)
{
//EWOL_DEBUG("Drawing the system");
@ -107,6 +129,9 @@ void game::Engine::Draw(ewol::DrawProperty& displayProp)
void game::Engine::AddElement(game::Element* newElement)
{
bool find=false;
if (NULL == newElement) {
EWOL_ERROR("try to set a NULL pointer game::Element");
}
for (int32_t iii=0 ; iii<m_elements.Size() ; iii++) {
if (NULL == m_elements[iii]) {
m_elements[iii] = newElement;
@ -116,6 +141,7 @@ void game::Engine::AddElement(game::Element* newElement)
}
if (false==find) {
m_elements.PushBack(newElement);
newElement->SetEngine(this);
}
}

View File

@ -57,6 +57,7 @@ namespace game
* @param[in] deltaTime delta time in µs from the previous call.
*/
void ProcessCollision(float deltaTime);
bool HasCollision(game::BoundingAABB& bounding, game::Element* currentElement);
/**
* @brief Display the environement.
*/

View File

@ -39,9 +39,10 @@ ewol::MeshObj::MeshObj(etk::UString _fileName) :
etk::Vector< vec2 > uvTextures;
etk::Vector< vec3 > normals;
int32_t lineID = 0;
while (NULL != fileName.FileGets(inputDataLine, 2048) )
{
lineID++;
if (inputDataLine[0]=='v') {
if (inputDataLine[1]=='n') {
// Vertice normal : vn 0.000000 0.000000 -1.000000
@ -61,25 +62,77 @@ ewol::MeshObj::MeshObj(etk::UString _fileName) :
}
} else if (inputDataLine[0]=='f') {
// face : f 5/1/1 1/2/1 4/3/1*
uint32_t vertexIndex[3], uvIndex[3], normalIndex[3];
int32_t matches = sscanf(&inputDataLine[2], "%d/%d/%d %d/%d/%d %d/%d/%d\n",
uint32_t vertexIndex[4], uvIndex[4], normalIndex[4];
bool quadMode = true;
int32_t matches = sscanf(&inputDataLine[2], "%d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d\n",
&vertexIndex[0], &uvIndex[0], &normalIndex[0],
&vertexIndex[1], &uvIndex[1], &normalIndex[1],
&vertexIndex[2], &uvIndex[2], &normalIndex[2] );
if (9 != matches){
EWOL_ERROR("Parsing error in the .obj files : " << fileName);
continue;
&vertexIndex[2], &uvIndex[2], &normalIndex[2],
&vertexIndex[3], &uvIndex[3], &normalIndex[3] );
if (12 != matches){
// no normal mode :
matches = sscanf(&inputDataLine[2], "%d/%d %d/%d %d/%d %d/%d\n",
&vertexIndex[0], &uvIndex[0],
&vertexIndex[1], &uvIndex[1],
&vertexIndex[2], &uvIndex[2],
&vertexIndex[3], &uvIndex[3] );
if (8 != matches){
quadMode = false;
matches = sscanf(&inputDataLine[2], "%d/%d/%d %d/%d/%d %d/%d/%d\n",
&vertexIndex[0], &uvIndex[0], &normalIndex[0],
&vertexIndex[1], &uvIndex[1], &normalIndex[1],
&vertexIndex[2], &uvIndex[2], &normalIndex[2] );
if (9 != matches){
// no normal mode :
matches = sscanf(&inputDataLine[2], "%d/%d %d/%d %d/%d\n",
&vertexIndex[0], &uvIndex[0],
&vertexIndex[1], &uvIndex[1],
&vertexIndex[2], &uvIndex[2] );
if (6 != matches){
EWOL_ERROR("Parsing error in the .obj files : " << fileName << " (l=" << lineID << ") in 'f' section : \"" << &inputDataLine[2] << "\" expected : %d/%d(/%d) %d/%d(/%d) %d/%d(/%d) (%d/%d(/%d)) () for option");
continue;
}
}
}
}
indicesVertices.PushBack(vertexIndex[0]);
indicesVertices.PushBack(vertexIndex[1]);
indicesVertices.PushBack(vertexIndex[2]);
indicesUv.PushBack(uvIndex[0]);
indicesUv.PushBack(uvIndex[1]);
indicesUv.PushBack(uvIndex[2]);
indicesNormal.PushBack(normalIndex[0]);
indicesNormal.PushBack(normalIndex[1]);
indicesNormal.PushBack(normalIndex[2]);
if (true==quadMode) {
indicesVertices.PushBack(vertexIndex[0]);
indicesVertices.PushBack(vertexIndex[1]);
indicesVertices.PushBack(vertexIndex[2]);
// second triangle
indicesVertices.PushBack(vertexIndex[0]);
indicesVertices.PushBack(vertexIndex[2]);
indicesVertices.PushBack(vertexIndex[3]);
indicesUv.PushBack(uvIndex[0]);
indicesUv.PushBack(uvIndex[1]);
indicesUv.PushBack(uvIndex[2]);
// second triangle
indicesUv.PushBack(uvIndex[0]);
indicesUv.PushBack(uvIndex[2]);
indicesUv.PushBack(uvIndex[3]);
if (12 == matches) {
indicesNormal.PushBack(normalIndex[0]);
indicesNormal.PushBack(normalIndex[1]);
indicesNormal.PushBack(normalIndex[2]);
// second triangle
indicesNormal.PushBack(normalIndex[0]);
indicesNormal.PushBack(normalIndex[2]);
indicesNormal.PushBack(normalIndex[3]);
}
} else {
indicesVertices.PushBack(vertexIndex[0]);
indicesVertices.PushBack(vertexIndex[1]);
indicesVertices.PushBack(vertexIndex[2]);
indicesUv.PushBack(uvIndex[0]);
indicesUv.PushBack(uvIndex[1]);
indicesUv.PushBack(uvIndex[2]);
if (9 == matches) {
indicesNormal.PushBack(normalIndex[0]);
indicesNormal.PushBack(normalIndex[1]);
indicesNormal.PushBack(normalIndex[2]);
}
}
// TODO : Calculate normal when none is provided ...
} else if (inputDataLine[0]=='s') {
// ??? : s off
} else if (inputDataLine[0]=='#') {
@ -125,15 +178,17 @@ ewol::MeshObj::MeshObj(etk::UString _fileName) :
// Get the indices of its attributes
uint32_t vertexIndex = indicesVertices[iii];
uint32_t uvIndex = indicesUv[iii];
uint32_t normalIndex = indicesNormal[iii];
// Put the attributes in buffers
m_object.m_vertices.PushBack(vertices[vertexIndex-1]);
m_object.m_uvTextures.PushBack(uvTextures[uvIndex-1]);
m_object.m_normals.PushBack(normals[normalIndex-1]);
draw::Color tmpppp(0xFFFFFFFF);
draw::Colorf tmppppp(tmpppp);
m_coordColor.PushBack(tmppppp);
if (indicesNormal.Size()>iii) {
uint32_t normalIndex = indicesNormal[iii];
m_object.m_normals.PushBack(normals[normalIndex-1]);
}
}
}