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

View File

@ -18,9 +18,9 @@ namespace game
class BoundingAABB class BoundingAABB
{ {
private : private :
vec3 m_PointStart;
vec3 m_PointStop;
bool m_hasContact; //!< this bounding is on contact with something else ... 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 ... vec3 m_oldUserPosition; // this is due to the fact object are never centered ...
#ifdef DEBUG #ifdef DEBUG
ewol::Colored3DObject* m_displayBounding; ewol::Colored3DObject* m_displayBounding;
@ -55,6 +55,8 @@ namespace game
* @brief Get the current contact status * @brief Get the current contact status
*/ */
bool GetContactStatus(void) { return m_hasContact; }; 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/Element.h>
#include <ewol/game/Engine.h>
#include <ewol/renderer/ResourceManager.h> #include <ewol/renderer/ResourceManager.h>
static int32_t uniqueId = 0; static int32_t uniqueId = 0;
game::Element::Element(etk::UString meshResource) : game::Element::Element(etk::UString meshResource) :
m_engine(NULL),
m_resource(NULL), m_resource(NULL),
m_matrixNeedUpdate(true), m_matrixNeedUpdate(true),
m_scale(1,1,1), m_scale(1,1,1),
@ -23,7 +25,8 @@ game::Element::Element(etk::UString meshResource) :
m_uniqueId(uniqueId), m_uniqueId(uniqueId),
m_groupId(0), m_groupId(0),
m_type(0), m_type(0),
m_visible(true) m_visible(true),
m_static(false)
{ {
ewol::MeshObj* tmpObject = NULL; ewol::MeshObj* tmpObject = NULL;
// get a resources : // get a resources :
@ -99,11 +102,56 @@ void game::Element::ProcessPosition(float delta)
vec3 curentAcceleration(m_gravityForce + m_userAcceleration); vec3 curentAcceleration(m_gravityForce + m_userAcceleration);
m_speed += curentAcceleration*delta; m_speed += curentAcceleration*delta;
vec3 tmpPos = m_position +m_speed*delta; vec3 tmpPos = m_position +m_speed*delta;
// TODO : Detect collision of other elements ...
if (m_position != tmpPos) { 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_position = tmpPos;
m_matrixNeedUpdate = true; 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 namespace game
{ {
class Engine;
class Element class Element
{ {
protected: protected:
game::Engine* m_engine;
ewol::Mesh* m_resource; //!< Resource to display the element. ewol::Mesh* m_resource; //!< Resource to display the element.
game::BoundingAABB m_bounding; //!< Bounding of this element game::BoundingAABB m_bounding; //!< Bounding of this element
private: 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 ... 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 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_visible; //!< This is to know if the element is displayed or not ==> TODO : check if usefull ...
bool m_static; //!< This element is static...
public: public:
/** /**
* @brief Basic constructor. * @brief Basic constructor.
@ -55,6 +58,11 @@ namespace game
* @brief Basic destructor. * @brief Basic destructor.
*/ */
virtual ~Element(void); 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. * @brief Draw the element.
*/ */
@ -113,6 +121,15 @@ namespace game
m_scale = vect; m_scale = vect;
m_matrixNeedUpdate = true; 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 * @brief Rotate the current object
* @param[in] vect rotation angle * @param[in] vect rotation angle
@ -147,6 +164,14 @@ namespace game
{ {
return m_bounding; 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); bounding1.SetContactMode(false);
} }
} }
// Brut force bounding detection :
for (int32_t iii=0; iii<m_elements.Size() ; iii++) { for (int32_t iii=0; iii<m_elements.Size() ; iii++) {
if (NULL != m_elements[iii]) { if (NULL != m_elements[iii]) {
game::BoundingAABB& bounding1 = m_elements[iii]->GetBounding(); // If the element is static, the bounding detection is not needed...
for (int32_t jjj=iii+1; jjj<m_elements.Size() ; jjj++) { if (true) {//false == m_elements[iii]->GetStaticMode()) {
if (NULL!=m_elements[jjj]) { game::BoundingAABB& bounding1 = m_elements[iii]->GetBounding();
game::BoundingAABB& bounding2 = m_elements[jjj]->GetBounding(); for (int32_t jjj=iii+1; jjj<m_elements.Size() ; jjj++) {
if (true == bounding2.HasContact(bounding1)) { if (NULL!=m_elements[jjj]) {
bounding2.SetContactMode(true); game::BoundingAABB& bounding2 = m_elements[jjj]->GetBounding();
bounding1.SetContactMode(true); 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) void game::Engine::Draw(ewol::DrawProperty& displayProp)
{ {
//EWOL_DEBUG("Drawing the system"); //EWOL_DEBUG("Drawing the system");
@ -107,6 +129,9 @@ void game::Engine::Draw(ewol::DrawProperty& displayProp)
void game::Engine::AddElement(game::Element* newElement) void game::Engine::AddElement(game::Element* newElement)
{ {
bool find=false; 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++) { for (int32_t iii=0 ; iii<m_elements.Size() ; iii++) {
if (NULL == m_elements[iii]) { if (NULL == m_elements[iii]) {
m_elements[iii] = newElement; m_elements[iii] = newElement;
@ -116,6 +141,7 @@ void game::Engine::AddElement(game::Element* newElement)
} }
if (false==find) { if (false==find) {
m_elements.PushBack(newElement); 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. * @param[in] deltaTime delta time in µs from the previous call.
*/ */
void ProcessCollision(float deltaTime); void ProcessCollision(float deltaTime);
bool HasCollision(game::BoundingAABB& bounding, game::Element* currentElement);
/** /**
* @brief Display the environement. * @brief Display the environement.
*/ */

View File

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