Пример #1
0
// Add intersections to queue
void AddIsects( const Ray3D &ray, const Box3D &box, PointQueue &isects )
{
  const unsigned nPairs = 3;
  Point3D rayEnd( ray.origin + ray.direction );

  for ( unsigned i = 0; i < nPairs; ++i )
  {
    unsigned j = ( i + 1 ) % nPairs, k = ( i + 2 ) % nPairs;

    if ( rayEnd[i] != ray.origin[i] )
    {
      for ( unsigned m = 0; m < 2; ++m)
      {
        float t = (!m) ? ( box.origin[i] - ray.origin[i] ) / ( ray.direction[i] )
                       : ( box.extent[i] - ray.origin[i] ) / ( ray.direction[i] );

        if ( t >= -epsilon && t <= 1.f + epsilon )
        {
          Point3D isect = ray.origin + t * ray.direction;
          if ( ( isect[j] >= box.origin[j] && isect[j] <= box.extent[j] ) &&
               ( isect[k] >= box.origin[k] && isect[k] <= box.extent[k] ) )
          {
            TimedPoint point = { t, isect };
            if ( isects.c.end() == std::find( isects.c.begin(), isects.c.end(), point ) )
              isects.push( point );
          }
        }
      }
    }
  }
}
//--------------------------------------------------------------
ofxBulletRaycastData ofxBulletWorldRigid::raycastTest( ofVec3f a_rayStart, ofVec3f a_rayEnd, short int a_filterMask) {
    ofxBulletRaycastData data;
    data.bHasHit = false;

    btVector3 rayStart( a_rayStart.x, a_rayStart.y, a_rayStart.z );
    btVector3 rayEnd( a_rayEnd.x, a_rayEnd.y, a_rayEnd.z );

    btCollisionWorld::ClosestRayResultCallback rayCallback( rayStart, rayEnd );
    rayCallback.m_collisionFilterMask = a_filterMask;
    world->rayTest( rayStart, rayEnd, rayCallback );

    if (rayCallback.hasHit()) {
        btRigidBody* body = btRigidBody::upcast( (btCollisionObject*)rayCallback.m_collisionObject );
        if (body) {
            data.bHasHit			= true;
            data.userData			= (ofxBulletUserData*)body->getUserPointer();
            data.body				= body;
            data.rayWorldPos		= a_rayEnd;
            btVector3 pickPos		= rayCallback.m_hitPointWorld;
            data.pickPosWorld		= ofVec3f(pickPos.getX(), pickPos.getY(), pickPos.getZ());
            btVector3 localPos		= body->getCenterOfMassTransform().inverse() * pickPos;
            data.localPivotPos		= ofVec3f(localPos.getX(), localPos.getY(), localPos.getZ() );
        }
    }
    return data;
}
bool CollisionManager::checkMovementCollision(CreatureObject* creature, float x, float z, float y, Zone* zone) {
	SortedVector<ManagedReference<QuadTreeEntry*> > closeObjects;
	zone->getInRangeObjects(x, y, 128, &closeObjects, true);

	//Vector3 rayStart(x, z + 0.25, y);
	//Vector3 rayStart(creature->getWorldPositionX(), creature->getWorldPositionZ(), creature->getPos)
	Vector3 rayStart = creature->getWorldPosition();
	rayStart.set(rayStart.getX(), rayStart.getY(), rayStart.getZ() + 0.25f);
	//Vector3 rayEnd(x + System::random(512), z + 0.3f, y + System::random(512));

	/*Vector3 rayEnd;
	rayEnd.set(targetPosition.getX(), targetPosition.getY(), targetPosition.getZ());*/

	Vector3 rayEnd(x, z + 0.25, y);

	float maxDistance = rayEnd.distanceTo(rayStart);

	if (maxDistance == 0)
		return false;

	printf("%f\n", maxDistance);

	SortedVector<IntersectionResult> results;
	results.setAllowDuplicateInsertPlan();

	printf("starting test\n");

	Triangle* triangle;

	for (int i = 0; i < closeObjects.size(); ++i) {
		SceneObject* object = dynamic_cast<SceneObject*>(closeObjects.get(i).get());

		if (object == NULL)
			continue;

		AABBTree* tree = getAABBTree(object, 255);

		if (tree == NULL)
			continue;

		Ray ray = convertToModelSpace(rayStart, rayEnd, object);

		//results.removeAll(10, 10);

		//ordered by intersection distance
		//tree->intersects(ray, maxDistance, results);

		float intersectionDistance;

		if (tree->intersects(ray, maxDistance, intersectionDistance, triangle, true)) {
			String str = object->getObjectTemplate()->getFullTemplateString();

			object->info("intersecting with me " + str, true);
			return true;
		}
	}

	return false;
}
Vector<float>* CollisionManager::getCellFloorCollision(float x, float y, CellObject* cellObject) {
	Vector<float>* collisions = NULL;

	ManagedReference<SceneObject*> rootObject = cellObject->getRootParent();

	if (rootObject == NULL)
		return NULL;

	SharedObjectTemplate* templateObject = rootObject->getObjectTemplate();

	if (templateObject == NULL)
		return NULL;

	PortalLayout* portalLayout = templateObject->getPortalLayout();

	if (portalLayout == NULL)
		return NULL;

	FloorMesh* mesh = portalLayout->getFloorMesh(cellObject->getCellNumber());

	if (mesh == NULL)
		return NULL;

	AABBTree* tree = mesh->getAABBTree();

	if (tree == NULL)
		return NULL;

	Vector3 rayStart(x, 16384.f, y);
	Vector3 rayEnd(x, -16384.f, y);

	Vector3 norm = rayEnd - rayStart;
	norm.normalize();

	Ray ray(rayStart, norm);

	SortedVector<IntersectionResult> results(3, 2);

	tree->intersects(ray, 16384 * 2, results);

	if (results.size() == 0)
		return NULL;

	collisions = new Vector<float>(results.size(), 1);

	for (int i = 0; i < results.size(); ++i) {
		float floorHeight = 16384 - results.get(i).getIntersectionDistance();

		collisions->add(floorHeight);
	}

	return collisions;
}
//--------------------------------------------------------------
ofxBulletRaycastData ofxBulletWorldSoft::raycastTest( ofVec3f a_rayStart, ofVec3f a_rayEnd, short int a_filterMask) {
	ofxBulletRaycastData data;
	data.bHasHit = false;
	if(_camera == NULL) {
		ofLog( OF_LOG_ERROR, "ofxBulletWorldSoft :: raycastTest : must set the camera first!!");
		return data;
	}
	
	btVector3 rayStart( a_rayStart.x, a_rayStart.y, a_rayStart.z );
	btVector3 rayEnd( a_rayEnd.x, a_rayEnd.y, a_rayEnd.z );
	
	btCollisionWorld::ClosestRayResultCallback rayCallback( rayStart, rayEnd );
	rayCallback.m_collisionFilterMask = a_filterMask;
	world->rayTest( rayStart, rayEnd, rayCallback );
	
	if (rayCallback.hasHit()) {
		if ( rayCallback.m_collisionObject->getInternalType() & btCollisionObject::CO_SOFT_BODY ) {
			// cast a ray into the soft body to get the point exactly
			//ofLogNotice("ofxBulletWorldSoft: soft body intersection");
			btSoftBody::sRayCast result;
#warning Casting (const btSoftBody*) to (btSoftBody*) -- not necessarily safe
			btSoftBody* body = (btSoftBody*)btSoftBody::upcast( rayCallback.m_collisionObject );
			if ( body->rayTest( rayStart, rayEnd, result ) ) {
				if ( result.fraction<1.0f ) {
					//ofLogNotice("ofxBulletWorldSoft") << "    at " << result.getFeatureName() << " index " << result.index;
				}
			}
			
		}
		else {
#warning Casting (const btRigidBody*) to (btRigidBody*) -- not necessarily safe
			btRigidBody* body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObject);
			if (body) {
				data.bHasHit			= true;
				data.userData			= (ofxBulletUserData*)body->getUserPointer();
				data.body				= body;
				data.rayWorldPos		= a_rayEnd;
				btVector3 pickPos		= rayCallback.m_hitPointWorld;
				data.pickPosWorld		= ofVec3f(pickPos.getX(), pickPos.getY(), pickPos.getZ());
				btVector3 localPos		= body->getCenterOfMassTransform().inverse() * pickPos;
				data.localPivotPos		= ofVec3f(localPos.getX(), localPos.getY(), localPos.getZ() );
			}
		}
	}
	return data;
}
Пример #6
0
void CollisionManager::getWorldFloorCollisions(float x, float y, Zone* zone, SortedVector<IntersectionResult>* result, const Vector<QuadTreeEntry*>& inRangeObjects) {
	Vector3 rayStart(x, 16384.f, y);
	Vector3 rayEnd(x, -16384.f, y);

	for (int i = 0; i < inRangeObjects.size(); ++i) {
		SceneObject* sceno = static_cast<SceneObject*>(inRangeObjects.get(i));

		AABBTree* aabbTree = getAABBTree(sceno, 255);

		if (aabbTree == NULL)
			continue;

		Ray ray = convertToModelSpace(rayStart, rayEnd, sceno);

		aabbTree->intersects(ray, 16384 * 2, *result);
	}
}
float CollisionManager::getWorldFloorCollision(float x, float y, Zone* zone, bool testWater) {
	SortedVector<ManagedReference<QuadTreeEntry*> > closeObjects;
	zone->getInRangeObjects(x, y, 128, &closeObjects, true);

	PlanetManager* planetManager = zone->getPlanetManager();

	if (planetManager == NULL)
		return 0.f;

	float height = 0;

	TerrainManager* terrainManager = planetManager->getTerrainManager();

	//need to include exclude affectors in the terrain calcs
	height = terrainManager->getHeight(x, y);

	Vector3 rayStart(x, 16384.f, y);
	Vector3 rayEnd(x, -16384.f, y);

	Triangle* triangle = NULL;

	if (testWater) {
		float waterHeight;

		if (terrainManager->getWaterHeight(x, y, waterHeight))
			if (waterHeight > height)
				height = waterHeight;
	}

	float intersectionDistance;

	for (int i = 0; i < closeObjects.size(); ++i) {
		BuildingObject* building = dynamic_cast<BuildingObject*>(closeObjects.get(i).get());

		if (building == NULL)
			continue;

		//building->getObjectTemplate()->get

		SharedObjectTemplate* templateObject = building->getObjectTemplate();

		if (templateObject == NULL)
			continue;

		PortalLayout* portalLayout = templateObject->getPortalLayout();

		if (portalLayout == NULL)
			continue;

		if (portalLayout->getFloorMeshNumber() == 0)
			continue;

		//find nearest entrance
		FloorMesh* exteriorFloorMesh = portalLayout->getFloorMesh(0); // get outside layout
		AABBTree* aabbTree = exteriorFloorMesh->getAABBTree();

		if (aabbTree == NULL)
			continue;

		Ray ray = convertToModelSpace(rayStart, rayEnd, building);

		if (aabbTree->intersects(ray, 16384 * 2, intersectionDistance, triangle, true)) {
			float floorHeight = 16384 - intersectionDistance;

			if (floorHeight > height)
				height = floorHeight;
		}
	}

	return height;
}
Пример #8
0
/*!
 * Lesson 01 - Hello Bullet
 * Create an irrlicht scene and a bullet world
 * Implement the integration, and build a foundation
 * for the other tutorials
 */
int main(int argc, char *argv[]) {

    // Irrlicht grabs the cursor so it is not in the way of our visualisation
    // Window caption gets set.
    device->getCursorControl()->setVisible(0);
    device->setWindowCaption(L"Lesson 03 - Intro to Raycasting");

    // Set the camera backwards and viewing the origin; setting up the visualisation
    cam->setPosition(irr::core::vector3df(0, 2, -5));
    cam->setTarget(irr::core::vector3df(0, 2, 0));
    smgr->addLightSceneNode(0, irr::core::vector3df(2, 10, -2), irr::video::SColorf(4, 4, 4, 1));

    // Creating our scene
    createScene();

    // Use a timestamp to regulate the frames, and stepping the simulation
    irr::u32 timeStamp = timer->getTime(), deltaTime = 0;

    // Game loop
    while(!done) {

	// Code to record when the frame began
	deltaTime = timer->getTime() - timeStamp;
	timeStamp = timer->getTime();

	// Step the simulation
	updatePhysics(deltaTime);

	// Irrlicht draws the scene
	driver->beginScene(true, true, irr::video::SColor(0, 15, 192, 252));

	//Visualize the raycast for the camera. The line needs to only be as long as the ray cast that way we are not blazing through objects and it really helps show the concept of ray casting, and it is a more realistic laser sight

	// Need the name for this mathmatical formula
	irr::core::vector3df rayEnd(sin(cam->getRotation().Y * M_PI / 180.0f) * cos(cam->getRotation().X * M_PI / 180.0f) * 50.0f,
		       -1 * sin(cam->getRotation().X * M_PI / 180.0f) * 50.0f,
		       cos(cam->getRotation().Y * M_PI / 180.0f) * cos(cam->getRotation().X * M_PI / 180.0f) * 50.0f);

	// Reset the transformation matrix for the raycast
	irr::video::SMaterial m;
	m.Lighting=false;
	driver->setMaterial(m);
	driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());

	//Draw our laser sight
	driver->draw3DLine(cam->getPosition() + irr::core::vector3df(.1, .01, 0),
			   rayEnd,
			   irr::video::SColor(255, 255, 0, 0));
	
	smgr->drawAll();
	driver->endScene();
	device->run();
    }

    // clean up
    clearObjects();
    delete world;
    delete solver;
    delete dispatcher;
    delete broadphase;
    delete collisionConfiguration;
    device->drop();

   return 0;
}