Esempio n. 1
0
void Scene::createBulletTerrain() {
	Ogre::Terrain* baseTerrain = mTerrainGroup->getTerrain(0, 0);
	btHeightfieldTerrainShape* hfShape = new btHeightfieldTerrainShape(
			baseTerrain->getSize(), baseTerrain->getSize(), baseTerrain->getHeightData(), 1, 0, 0,
			2, PHY_FLOAT, false);
	// Min and max height were set to 0 to force the terrain to be completely flat
	hfShape->setUseDiamondSubdivision(true);

	// This scale is based on the tutorial, but it may not be true...
	float metersBetweenVerts = baseTerrain->getWorldSize() / (baseTerrain->getSize() - 1);
	btVector3 scale(metersBetweenVerts, metersBetweenVerts, 1);
	hfShape->setLocalScaling(scale);

	hfShape->setUserPointer((void*) SU_Terrain);

	btCollisionObject* colObj = new btCollisionObject();
	colObj->setCollisionShape(hfShape);
	colObj->setFriction(0.9); colObj->setRestitution(0.0);
	colObj->setCollisionFlags(colObj->getCollisionFlags() |
							  btCollisionObject::CF_STATIC_OBJECT |
							  btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
	mSim->getCollisionWorld()->getDynamicsWorld()->addCollisionObject(colObj);
	mSim->getCollisionWorld()->addShape(hfShape);

	// Border planes
	const float px[4] = {-1, 1, 0, 0};
	const float py[4] = { 0, 0,-1, 1};
	for (int i = 0; i < 4; ++i) {
		btVector3 vpl(px[i], py[i], 0);
		btCollisionShape* shp = new btStaticPlaneShape(vpl, 0);
		shp->setUserPointer((void*) SU_Border);

		btTransform tr;  tr.setIdentity();
		tr.setOrigin(vpl * -0.5 * worldSize);

		btCollisionObject* col = new btCollisionObject();
		col->setCollisionShape(shp);
		col->setWorldTransform(tr);
		col->setFriction(0.3);   //+
		col->setRestitution(0.0);
		col->setCollisionFlags(col->getCollisionFlags() |
							   btCollisionObject::CF_STATIC_OBJECT |
							   btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);

		mSim->getCollisionWorld()->getDynamicsWorld()->addCollisionObject(col);
		mSim->getCollisionWorld()->addShape(shp);
	}
}
Esempio n. 2
0
size_t generateVPLs(const Scene *scene, Random *random,
		size_t offset, size_t count, int maxDepth, bool prune, std::deque<VPL> &vpls) {
	if (maxDepth <= 1)
		return 0;

	static Sampler *sampler = NULL;
	if (!sampler) {
		Properties props("halton");
		props.setInteger("scramble", 0);
		sampler = static_cast<Sampler *> (PluginManager::getInstance()->
			createObject(MTS_CLASS(Sampler), props));
		sampler->configure();
	}

	const Sensor *sensor = scene->getSensor();
	Float time = sensor->getShutterOpen()
		+ 0.5f * sensor->getShutterOpenTime();

	const Frame stdFrame(Vector(1,0,0), Vector(0,1,0), Vector(0,0,1));

	while (vpls.size() < count) {
		sampler->setSampleIndex(++offset);

		PositionSamplingRecord pRec(time);
		DirectionSamplingRecord dRec;
		Spectrum weight = scene->sampleEmitterPosition(pRec,
			sampler->next2D());

		size_t start = vpls.size();

		/* Sample an emitted particle */
		const Emitter *emitter = static_cast<const Emitter *>(pRec.object);

		if (!emitter->isEnvironmentEmitter() && emitter->needsDirectionSample()) {
			VPL lumVPL(EPointEmitterVPL, weight);
			lumVPL.its.p = pRec.p;
			lumVPL.its.shFrame = pRec.n.isZero() ? stdFrame : Frame(pRec.n);
			lumVPL.emitter = emitter;
			appendVPL(scene, random, lumVPL, prune, vpls);

			weight *= emitter->sampleDirection(dRec, pRec, sampler->next2D());
		} else {
			/* Hack to get the proper information for directional VPLs */
			DirectSamplingRecord diRec(
				scene->getKDTree()->getAABB().getCenter(), pRec.time);

			Spectrum weight2 = emitter->sampleDirect(diRec, sampler->next2D())
				/ scene->pdfEmitterDiscrete(emitter);

			if (weight2.isZero())
				continue;

			VPL lumVPL(EDirectionalEmitterVPL, weight2);
			lumVPL.its.p = Point(0.0);
			lumVPL.its.shFrame = Frame(-diRec.d);
			lumVPL.emitter = emitter;
			appendVPL(scene, random, lumVPL, false, vpls);
			dRec.d = -diRec.d;

			Point2 offset = Warp::squareToUniformDiskConcentric(sampler->next2D());
			Vector perpOffset = Frame(diRec.d).toWorld(Vector(offset.x, offset.y, 0));
			BSphere geoBSphere = scene->getKDTree()->getAABB().getBSphere();
			pRec.p = geoBSphere.center + (perpOffset - dRec.d) * geoBSphere.radius;
			weight = weight2 * M_PI * geoBSphere.radius * geoBSphere.radius;
		}

		int depth = 2;
		Ray ray(pRec.p, dRec.d, time);
		Intersection its;

		while (!weight.isZero() && (depth < maxDepth || maxDepth == -1)) {
			if (!scene->rayIntersect(ray, its))
				break;

			const BSDF *bsdf = its.getBSDF();
			BSDFSamplingRecord bRec(its, sampler, EImportance);
			Spectrum bsdfVal = bsdf->sample(bRec, sampler->next2D());
			if (bsdfVal.isZero())
				break;

			/* Assuming that BSDF importance sampling is perfect,
				the following should equal the maximum albedo
				over all spectral samples */
			Float approxAlbedo = std::min((Float) 0.95f, bsdfVal.max());
			if (sampler->next1D() > approxAlbedo)
				break;
			else
				weight /= approxAlbedo;

			VPL vpl(ESurfaceVPL, weight);
			vpl.its = its;

			if (BSDF::getMeasure(bRec.sampledType) == ESolidAngle)
				appendVPL(scene, random, vpl, prune, vpls);

			weight *= bsdfVal;

			Vector wi = -ray.d, wo = its.toWorld(bRec.wo);
			ray = Ray(its.p, wo, 0.0f);

			/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
			Float wiDotGeoN = dot(its.geoFrame.n, wi),
				woDotGeoN = dot(its.geoFrame.n, wo);
			if (wiDotGeoN * Frame::cosTheta(bRec.wi) <= 0 ||
				woDotGeoN * Frame::cosTheta(bRec.wo) <= 0)
				break;

			/* Disabled for now -- this increases VPL weights
			   and accuracy is not really a big requirement */
			#if 0
				/* Adjoint BSDF for shading normals -- [Veach, p. 155] */
				weight *= std::abs(
					(Frame::cosTheta(bRec.wi) * woDotGeoN)/
					(Frame::cosTheta(bRec.wo) * wiDotGeoN));
			#endif

			++depth;
		}

		size_t end = vpls.size();
		for (size_t i=start; i<end; ++i)
			vpls[i].emitterScale = 1.0f / (end - start);
	}

	return offset;
}