void CollisionDetection::createConvexHull( Entity *entity, bool enemy ) { size_t vertex_count; size_t index_count; Ogre::Vector3 *vertices; unsigned long *indices; GetMeshInformation( entity->getMesh(), vertex_count, vertices, index_count, indices, Vector3( 0.0, 0.0, 0.0 ),//entity->getParentNode()->getPosition(), Ogre::Quaternion::IDENTITY, //entity->getParentNode()->getOrientation() Ogre::Vector3(1,1,1));//entity->getParentNode()->_getDerivedScale() );//Ogre::Vector3(1,1,1)); dFloat *vertexCloud = new dFloat[vertex_count*3]; for( int i = 0; i < vertex_count; i++ ) { vertexCloud[i*3] = vertices[i].x; vertexCloud[i*3+1] = vertices[i].y; vertexCloud[i*3+2] = vertices[i].z; } shapeID++; NewtonCollision *newCol = NewtonCreateConvexHull (newtonWorld, vertex_count, vertexCloud, 12, 0.0, shapeID, NULL); if(enemy) { enemyEnt = newCol; } else { NewtonBody* rigidBodyBox = NewtonCreateBody (newtonWorld, newCol); //PROBLEM with the line as this comand should work, but terminates the app;Possibly a c++ issue //NewtonReleaseCollision( newtonWorld, enemyCol); collisionsMap.insert(pair<Entity*,NewtonCollision*>(entity,newCol)); bodysMap.insert(pair<Entity*,NewtonBody*>(entity,rigidBodyBox)); } }
void SceneObject::updateData() { clear(); Ogre::Entity* entity = getSceneManager()->getEntity(mEntityName); if (entity != nullptr && !mMaterialName.empty()) { mVertexCount = 0; mIndexCount = 0; GetMeshInformation(entity->getMesh(), mVertexCount, mVertices, mIndexCount, mIndices, mTextureCoords, Ogre::Vector3::ZERO, Ogre::Quaternion::IDENTITY, Ogre::Vector3::UNIT_SCALE, mMaterialName); Ogre::MaterialPtr material = (Ogre::MaterialPtr)Ogre::MaterialManager::getSingleton().getByName(mMaterialName); if (!material.isNull()) { mTextureUnit = material->getTechnique(0)->getPass(0)->getTextureUnitState("gui"); if (mTextureUnit) { mTextureUnit->setTextureName(mTextureName); mUScale = mTextureUnit->getTextureUScale(); mVScale = mTextureUnit->getTextureVScale(); } } } }
bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result,Ogre::MovableObject* &target,float &closest_distance, const Ogre::uint32 queryMask) { target = NULL; // check we are initialised if (mRaySceneQuery != NULL) { // create a query object mRaySceneQuery->setRay(ray); mRaySceneQuery->setSortByDistance(true); mRaySceneQuery->setQueryMask(queryMask); // execute the query, returns a vector of hits if (mRaySceneQuery->execute().size() <= 0) { // raycast did not hit an objects bounding box return (false); } } else { //LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG; return (false); } // at this point we have raycast to a series of different objects bounding boxes. // we need to test these different objects to see which is the first polygon hit. // there are some minor optimizations (distance based) that mean we wont have to // check all of the objects most of the time, but the worst case scenario is that // we need to test every triangle of every object. //Ogre::Ogre::Real closest_distance = -1.0f; closest_distance = -1.0f; Ogre::Vector3 closest_result; Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults(); for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++) { // stop checking if we have found a raycast hit that is closer // than all remaining entities if ((closest_distance >= 0.0f) && (closest_distance < query_result[qr_idx].distance)) { break; } // Only check this result if its a hit against an Entity or // ManualObject. if ((query_result[qr_idx].movable != NULL) && (query_result[qr_idx].movable->isVisible()) && ((query_result[qr_idx].movable->getMovableType().compare("Entity") == 0) || (query_result[qr_idx].movable->getMovableType().compare("ManualObject") == 0))) { // get the entity to check Ogre::MovableObject *pmovable = static_cast<Ogre::MovableObject*>(query_result[qr_idx].movable); Ogre::MeshPtr mesh_ptr; if (query_result[qr_idx].movable->getMovableType().compare("Entity") == 0) { mesh_ptr = ((Ogre::Entity*)pmovable)->getMesh(); } else { // XXX: Does "Mesh" get replaced so we can get away with not // XXX: deleting it for now? mesh_ptr = ((Ogre::ManualObject*)pmovable)->convertToMesh("Mesh", "General"); } // mesh data to retrieve size_t vertex_count; size_t index_count; Ogre::Vector3 *vertices; Ogre::uint32 *indices; // get the mesh information GetMeshInformation(mesh_ptr, vertex_count, vertices, index_count, indices, pmovable->getParentNode()->_getDerivedPosition(), pmovable->getParentNode()->_getDerivedOrientation(), pmovable->getParentNode()->_getDerivedScale()); // test for hitting individual triangles on the mesh bool new_closest_found = false; for (size_t i = 0; i < index_count; i += 3) { // check for a hit against this triangle std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]], vertices[indices[i+1]], vertices[indices[i+2]], true, false); // if it was a hit check if its the closest if (hit.first) { if ((closest_distance < 0.0f) || (hit.second < closest_distance)) { // this is the closest so far, save it off closest_distance = hit.second; new_closest_found = true; } } } // free the verticies and indicies memory delete[] vertices; delete[] indices; // if we found a new closest raycast for this object, update the // closest_result before moving on to the next object. if (new_closest_found) { target = pmovable; closest_result = ray.getPoint(closest_distance); } } } // return the result if (closest_distance >= 0.0f) { // raycast success result = closest_result; return (true); } else { // raycast failed return (false); } }
/***************************************************************************//*! * @brief Raycast from a point in to the scene. * @param[in] point Point to analyse * @param[in] normal Direction * @param[out] result Result ( ONLY if return TRUE ) * @return TRUE if somethings found => {result} NOT EMPTY */ bool OgreMeshRay::raycastFromPoint(const Ogre::Vector3& point, const Ogre::Vector3& normal, Ogre::Vector3& result, std::string entityName) { // create the ray to test Ogre::Ray ray(point, normal); if (!m_raySceneQuery) return false; // create a query object m_raySceneQuery->setRay(ray); // execute the query, returns a vector of hits if (m_raySceneQuery->execute().size() <= 0) { // raycast did not hit an objects bounding box return false; } // at this point we have raycast to a series of different objects bounding boxes. // we need to test these different objects to see which is the first polygon hit. // there are some minor optimizations (distance based) that mean we wont have to // check all of the objects most of the time, but the worst case scenario is that // we need to test every triangle of every object. Ogre::Real closest_distance = -1.0f; Ogre::Vector3 closest_result; Ogre::RaySceneQueryResult& query_result = m_raySceneQuery->getLastResults(); for (size_t qr_idx = 0, size = query_result.size(); qr_idx < size; ++qr_idx) { // stop checking if we have found a raycast hit that is closer // than all remaining entities if (closest_distance >= 0.0f && closest_distance < query_result[qr_idx].distance) break; // only check this result if its a hit against an entity if (query_result[qr_idx].movable) { if (entityName != "" && query_result[qr_idx].movable->getName() != entityName) { std::cout << query_result[qr_idx].movable->getName() << "is not " << entityName << std::endl; continue; } std::cout << query_result[qr_idx].movable->getName() << "is truly " << entityName << std::endl; const std::string& movableType = query_result[qr_idx].movable->getMovableType(); // mesh data to retrieve size_t vertex_count; size_t index_count; Ogre::Vector3* vertices; unsigned long* indices; if (movableType == "ManualObject") { // get the entity to check Ogre::ManualObject* pentity = static_cast<Ogre::ManualObject*>(query_result[qr_idx].movable); // get the mesh information GetMeshInformation(pentity, vertex_count, vertices, index_count, indices, pentity->getParentNode()->_getDerivedPosition(), pentity->getParentNode()->_getDerivedOrientation(), pentity->getParentNode()->_getDerivedScale()); } else if (movableType == "Entity") { // get the entity to check Ogre::Entity *pentity = static_cast<Ogre::Entity*>(query_result[qr_idx].movable); // get the mesh information GetMeshInformation(pentity, vertex_count, vertices, index_count, indices, pentity->getParentNode()->_getDerivedPosition(), pentity->getParentNode()->_getDerivedOrientation(), pentity->getParentNode()->_getDerivedScale()); } else { continue; } // test for hitting individual triangles on the mesh bool new_closest_found = false; for (int i = 0; i < static_cast<int>(index_count); i += 3) { // check for a hit against this triangle std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]], vertices[indices[i + 1]], vertices[indices[i + 2]], true, false); // if it was a hit check if its the closest if (hit.first && (closest_distance < 0.0f || hit.second < closest_distance)) { // this is the closest so far, save it off closest_distance = hit.second; new_closest_found = true; } } // free the verticies and indicies memory delete[] vertices; delete[] indices; // if we found a new closest raycast for this object, update the // closest_result before moving on to the next object. if (new_closest_found) closest_result = ray.getPoint(closest_distance); } } // return the result if (closest_distance >= 0.0f) { // raycast success result = closest_result; return true; } // raycast failed return false; }
bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result,Ogre::MovableObject* &target,float &closest_distance, const Ogre::uint32 queryMask) { target = NULL; // check we are initialised if (mRaySceneQuery != NULL) { // create a query object mRaySceneQuery->setRay(ray); mRaySceneQuery->setSortByDistance(true); mRaySceneQuery->setQueryMask(queryMask); // execute the query, returns a vector of hits if (mRaySceneQuery->execute().size() <= 0) { // raycast did not hit an objects bounding box return (false); } } else { //LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG; return (false); } // at this point we have raycast to a series of different objects bounding boxes. // we need to test these different objects to see which is the first polygon hit. // there are some minor optimizations (distance based) that mean we wont have to // check all of the objects most of the time, but the worst case scenario is that // we need to test every triangle of every object. //Ogre::Ogre::Real closest_distance = -1.0f; closest_distance = -1.0f; Ogre::Vector3 closest_result; Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults(); #if 0 for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++) { const Ogre::RaySceneQueryResultEntry& result = query_result[qr_idx]; Ogre::Real distance = result.distance; Ogre::MovableObject* movable = static_cast<Ogre::MovableObject*>(result.movable); Ogre::SceneQuery::WorldFragment* worldFragment = result.worldFragment; if (movable) { const Ogre::String& type = movable->getMovableType(); const Ogre::String& name = movable->getName(); const Ogre::String& parentName = movable->getParentNode()->getName(); Ogre::uint32 flag = movable->getQueryFlags(); if (type.compare("Entity") == 0) { Ogre::Entity* ent = (Ogre::Entity*)movable; } std::ostrstream oss; oss<<"name:"<<name<<" distance:"<< distance <<" type:"<<type<<" flag:"<<flag<<" parent:"<<parentName<<std::endl; OutputDebugString(oss.str() ); } } #endif for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++) { // stop checking if we have found a raycast hit that is closer // than all remaining entities if ((closest_distance >= 0.0f) && (closest_distance < query_result[qr_idx].distance)) { break; } // only check this result if its a hit against an entity if ((query_result[qr_idx].movable != NULL) && (query_result[qr_idx].movable->getMovableType().compare("Entity") == 0)) { // get the entity to check Ogre::MovableObject *pentity = static_cast<Ogre::MovableObject*>(query_result[qr_idx].movable); // mesh data to retrieve size_t vertex_count; size_t index_count; Ogre::Vector3 *vertices = NULL; Ogre::uint32 *indices = NULL; // get the mesh information GetMeshInformation(((Ogre::Entity*)pentity)->getMesh(), vertex_count, vertices, index_count, indices, pentity->getParentNode()->_getDerivedPosition(), pentity->getParentNode()->_getDerivedOrientation(), pentity->getParentNode()->_getDerivedScale()); // test for hitting individual triangles on the mesh bool new_closest_found = false; for (size_t i = 0; i < index_count; i += 3) { // check for a hit against this triangle std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]], vertices[indices[i+1]], vertices[indices[i+2]], true, false); // if it was a hit check if its the closest if (hit.first) { if ((closest_distance < 0.0f) || (hit.second < closest_distance)) { // this is the closest so far, save it off closest_distance = hit.second; new_closest_found = true; } } } // free the verticies and indicies memory delete vertices; delete indices; // if we found a new closest raycast for this object, update the // closest_result before moving on to the next object. if (new_closest_found) { target = pentity; closest_result = ray.getPoint(closest_distance); } } } // return the result if (closest_distance >= 0.0f) { // raycast success result = closest_result; return (true); } else { // raycast failed return (false); } }
void CollisionDetection::addStaticTreeCollisionMesh( Entity *entity, string name) { bool meshCreated = false; NewtonCollision *treeCollision; std::stringstream out; out << name; string fileString = ConstManager::getString("cmesh_file_path"); fileString += out.str(); fileString.append(".cmesh"); cout << fileString<<endl; char *fileName = (char*) fileString.c_str(); if( !gernerateMeshes ) { FILE* meshFile; meshFile = fopen(fileName,"r"); if (meshFile!=NULL) { treeCollision = NewtonCreateCollisionFromSerialization (newtonWorld, myDeserializeCollisionCallbackFunction, meshFile); fclose (meshFile); meshCreated = true; } else { cout << "Colision detection could not read file.\nAttempting to create mesh from scratch" << endl; } } if( !meshCreated ) { treeCollision = NewtonCreateTreeCollision (newtonWorld, 0); NewtonTreeCollisionBeginBuild(treeCollision); size_t vertex_count; size_t index_count; Ogre::Vector3 *vertices; unsigned long *indices; GetMeshInformation( entity->getMesh(), vertex_count, vertices, index_count, indices, entity->getParentNode()->getPosition(), entity->getParentNode()->getOrientation(), entity->getParentNode()->_getDerivedScale()); /* Ogre::Vector3(), Ogre::Quaternion::IDENTITY, Ogre::Vector3(1,1,1)); */ dFloat vArray[9]; int i0, i1, i2; for (int i = 0; i < static_cast<int>(index_count); i += 3) { i0 = indices[i]; i1 = indices[i+1]; i2 = indices[i+2]; vArray[0] = vertices[i0].x; vArray[1] = vertices[i0].y; vArray[2] = vertices[i0].z; vArray[3] = vertices[i1].x; vArray[4] = vertices[i1].y; vArray[5] = vertices[i1].z; vArray[6] = vertices[i2].x; vArray[7] = vertices[i2].y; vArray[8] = vertices[i2].z; NewtonTreeCollisionAddFace(treeCollision, 3, vArray, sizeof(dFloat)*3, i); } NewtonTreeCollisionEndBuild(treeCollision, 1); FILE* meshFile; meshFile = fopen(fileName,"w"); if (meshFile!=NULL) { NewtonCollisionSerialize(newtonWorld, treeCollision, mySerializeCollisionCallbackFunction, meshFile); fclose (meshFile); } else { cout << "Colision detection could not write cmesh file." << endl; } } NewtonBody* rigidTree = NewtonCreateBody (newtonWorld, treeCollision); NewtonReleaseCollision (newtonWorld, treeCollision); NewtonBodySetMatrix (rigidTree, &idmatrix[0]); dFloat boxP0[3]; dFloat boxP1[3]; //possibly need this if we rely on newton //NewtonCollisionCalculateAABB (treeCollision, &idmatrix[0], &boxP0[0], &boxP1[0]); collisionsMap.insert(pair<Entity*,NewtonCollision*>(entity,treeCollision)); bodysMap.insert(pair<Entity*,NewtonBody*>(entity,rigidTree)); }
Ogre::Entity* RaycastToPolygon( const Ogre::Real& x, const Ogre::Real& y, Ogre::RaySceneQuery* Query, Ogre::Camera* Camera ) { Ogre::Ray MouseRay = Camera->getCameraToViewportRay( x, y ); Query->setRay( MouseRay ); Query->setSortByDistance( true ); Ogre::RaySceneQueryResult& QueryResult = Query->execute(); if( QueryResult.size() == 0 ) { return NULL; } // at this point we have raycast to a series of different objects bounding boxes. // we need to test these different objects to see which is the first polygon hit. // there are some minor optimizations (distance based) that mean we wont have to // check all of the objects most of the time, but the worst case scenario is that // we need to test every triangle of every object. Ogre::Real ClosestDistance = -1.0f; Ogre::Entity* ClosestResult; for( size_t QRIndex = 0; QRIndex < QueryResult.size(); QRIndex++ ) { // stop checking if we have found a raycast hit that is closer // than all remaining entities if( ( ClosestDistance >= 0.0f ) && ( ClosestDistance < QueryResult[QRIndex].distance ) ) break; // only check this result if its a hit against an entity if( ( QueryResult[QRIndex].movable != NULL ) && ( QueryResult[QRIndex].movable->getMovableType().compare("Entity") == 0 ) && QueryResult[QRIndex].movable->getName() != OVISE_SelectionBoxName ) { // get the entity to check Ogre::Entity* PEntity = static_cast<Ogre::Entity*>(QueryResult[QRIndex].movable); // mesh data to retrieve size_t VertexCount; size_t IndexCount; Ogre::Vector3* Vertices; unsigned long* Indices; // get the mesh information GetMeshInformation( PEntity->getMesh(), VertexCount, Vertices, IndexCount, Indices, PEntity->getParentSceneNode()->_getDerivedPosition(), PEntity->getParentSceneNode()->_getDerivedOrientation(), PEntity->getParentSceneNode()->_getDerivedScale() ); // test for hitting individual triangles on the mesh bool NewClosestFound = false; if( IndexCount == 0 ) // no triangles, e.g. pointcloud { NewClosestFound = true; ClosestDistance = QueryResult[QRIndex].distance; } else { for( int i = 0; i < static_cast<int>(IndexCount); i += 3 ) { // check for a hit against this triangle std::pair<bool, Ogre::Real> Hit = Ogre::Math::intersects( MouseRay, Vertices[Indices[i]], Vertices[Indices[i+1]], Vertices[Indices[i+2]], true, false); // if it was a hit check if its the closest if( Hit.first ) { if( ( ClosestDistance < 0.0f ) || ( Hit.second < ClosestDistance ) ) { // this is the closest so far, save it off ClosestDistance = Hit.second; NewClosestFound = true; } } } } // free the verticies and indicies memory delete[] Vertices; delete[] Indices; // if we found a new closest raycast for this object, update the // closest_result before moving on to the next object. if( NewClosestFound ) ClosestResult = PEntity; } } if( ClosestDistance < 0.0f ) { // raycast failed ClosestResult = NULL; } return ClosestResult; }