示例#1
0
	int Java_zte_irrlib_scene_SceneNode_nativeAddCollisionResponseAnimator(
		JNIEnv *env, jobject defaultObj, jint selId, jobject jradius, jboolean bbox, jboolean octree, jint id)
	{
		ISceneNode* selNode = smgr->getSceneNodeFromId(selId);
		if (!selNode)
		{
			WARN_NODE_NOT_FOUND(selId, AddCollisionResponseAnimator);
			return -1;
		}
		
		ISceneNode* node = smgr->getSceneNodeFromId(id);
		if (!node)
		{
			WARN_NODE_NOT_FOUND(id, AddCollisionResponseAnimator);
			return -1;
		}
		
		ITriangleSelector* selector = 0;
		if (bbox) selector = smgr->createTriangleSelectorFromBoundingBox(selNode);
		else if (!octree) selector = smgr->createTriangleSelector(((IMeshSceneNode*)selNode)->getMesh(), selNode);
		else selector = smgr->createTriangleSelector(((IMeshSceneNode*)selNode)->getMesh(), selNode);
		
		node->updateAbsolutePosition();
		const aabbox3d<f32>& box = node->getTransformedBoundingBox();
		
		vector3df radius;
		if (jradius == 0)
			radius = box.MaxEdge-box.getCenter();
		else radius = utils->createvector3dfFromVector3d(env, jradius);
		
		vector3df translation = -(box.getCenter() - node->getAbsolutePosition());
		
		//LOGD("max, %f, %f, %f", box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z);
		//LOGD("min, %f, %f, %f", box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z);
		//LOGD("trans, %f, %f, %f", translation.X, translation.Y, translation.Z);
		ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(selector, node,
			radius,
			vector3df(),/*gravity*/
			translation,
			0.0005f
		);
		selector->drop();
		node->addAnimator(anim);
		anim->drop();
	}
static bool checkBBoxIntersection(IrrlichtDevice * device,
				ISceneManager * smgr)
{
	video::IVideoDriver* driver = device->getVideoDriver();

	// add camera
	scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();
	camera->setPosition(core::vector3df(30, 30, 30));
	camera->setTarget(core::vector3df(8.f, 8.f, 8.f));
	camera->setID(0);

	// add a cube to pick
	scene::ISceneNode* cube = smgr->addCubeSceneNode(30, 0, -1, core::vector3df(0,0,0),core::vector3df(30,40,50));

	bool result=true;
	for (u32 round=0; round<2; ++round)
	{
		driver->beginScene(true, true, video::SColor(100, 50, 50, 100));
		smgr->drawAll();
		driver->endScene();

		core::matrix4 invMat = cube->getAbsoluteTransformation();
		invMat.makeInverse();

		s32 hits=0;
		u32 start = device->getTimer()->getRealTime();
		for (u32 i=10; i<150; ++i)
		{
			for (u32 j=10; j<110; ++j)
			{
				const core::position2di pos(i, j);

				// get the line used for picking
				core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(pos, camera);

				invMat.transformVect(ray.start);
				invMat.transformVect(ray.end);

				hits += (cube->getBoundingBox().intersectsWithLine(ray)?1:0);
			}
		}
		u32 duration = device->getTimer()->getRealTime()-start;
		logTestString("bbox intersection checks %d hits (of 14000).\n", hits);
		hits = -hits;

		start = device->getTimer()->getRealTime();
		for (u32 i=10; i<150; ++i)
		{
			for (u32 j=10; j<110; ++j)
			{
				const core::position2di pos(i, j);

				// get the line used for picking
				core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(pos, camera);

				invMat.transformVect(ray.start);
				invMat.transformVect(ray.end);

				hits += (IntersectBox(ray.start, (ray.end-ray.start).normalize(), cube->getBoundingBox())?1:0);
			}
		}
		u32 duration2 = device->getTimer()->getRealTime()-start;
		logTestString("bbox intersection resulted in %d misses at a speed of %d (old) compared to %d (new).\n", abs(hits), duration, duration2);
		if (duration>(duration2*1.2f))
			logTestString("Consider replacement of bbox intersection test.\n");

		result &= (hits==0);
		assert(result);
		// second round without any hits, so check opposite direction
		camera->setTarget(core::vector3df(80.f, 80.f, 80.f));
	}

	ISceneNode* node = smgr->addSphereSceneNode(5.f, 16, 0, -1, core::vector3df(0, 0, 1), core::vector3df(), core::vector3df(0.3f, 0.3f, 0.3f));
	cube->remove();
	cube = smgr->addCubeSceneNode(10.f, 0, -1, core::vector3df(0, 6.5f, 1), core::vector3df(), core::vector3df(10, 0.1f, 1.f));
	camera->setPosition(core::vector3df(0, 0, 10));
	camera->setTarget(core::vector3df());

	u32 count=0;
	for (u32 i=0; i<30; ++i)
	{
		driver->beginScene(true, true, video::SColor(100, 50, 50, 100));
		smgr->drawAll();
		driver->endScene();

		count += node->getTransformedBoundingBox().intersectsWithBox(cube->getTransformedBoundingBox())?1:0;
		node->setPosition(node->getPosition()+core::vector3df(.5f,.5f,0));
		if (i==8 && count != 0)
			result=false;
		if (i==17 && count != 9)
			result=false;
	}
	if (count != 9)
		result=false;

	smgr->clear();

	return result;
}
void CImpostorSceneNode::renderNode(SNodeLink& Imp)
{
	ISceneNode* n = Imp.Node;

	updatePosAndVector(Imp);

	// remember old viewport and render target
	core::rect<s32> oldView = SceneManager->getVideoDriver()->getViewPort();

	if (!oldView.isRectCollided(Imp.NewPos))
		return;

	ICameraSceneNode* cam = SceneManager->getActiveCamera();
	cam->updateAbsolutePosition();

	core::vector3df camP = cam->getAbsolutePosition();
	f32 distance = camP.getDistanceFrom(n->getTransformedBoundingBox().getCenter());

	// project into screen

	core::vector3df pUL = SceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(Imp.NewPos.UpperLeftCorner, cam).getVector();
	pUL.setLength(distance);
	core::vector3df pLR = SceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(Imp.NewPos.LowerRightCorner, cam).getVector();
	pLR.setLength(distance);
	core::vector3df pUR = SceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(core::position2di(Imp.NewPos.LowerRightCorner.X, Imp.NewPos.UpperLeftCorner.Y), cam).getVector();
	pUR.setLength(distance);
	core::vector3df pLL = SceneManager->getSceneCollisionManager()->getRayFromScreenCoordinates(core::position2di(Imp.NewPos.UpperLeftCorner.X, Imp.NewPos.LowerRightCorner.Y), cam).getVector();
	pLL.setLength(distance);

	Imp.BilPos1 = camP + pUL;
	Imp.BilPos2 = camP + pLR;
	Imp.BilPos3 = camP + pUR;
	Imp.BilPos4 = camP + pLL;

	// translate and scale, but don't rotate
	core::matrix4 invMat = n->getAbsoluteTransformation();
	invMat.makeInverse();
	Imp.BilPos1 *= invMat.getScale();
	invMat.translateVect(Imp.BilPos1);
	Imp.BilPos2 *= invMat.getScale();
	invMat.translateVect(Imp.BilPos2);
	Imp.BilPos3 *= invMat.getScale();
	invMat.translateVect(Imp.BilPos3);
	Imp.BilPos4 *= invMat.getScale();
	invMat.translateVect(Imp.BilPos4);

	Imp.ScreenPos = Imp.NewPos;
	Imp.RotVec = Imp.NewVec;
	video::ITexture* rt = 0; // SceneManager->getVideoDriver()->getRenderTarget();

	// set up the camera and viewport for rendering
	ISceneManager* oldManager = n->getSceneManager();

	// set up the camera
	ICameraSceneNode* cam2= LocalManager->getActiveCamera();

	cam2->setPosition(cam->getAbsolutePosition());

	core::vector3df v = n->getTransformedBoundingBox().getCenter();
	cam2->setUpVector(cam->getUpVector());
	cam2->setTarget(cam->getTarget());
	cam2->updateAbsolutePosition();

	f32 scaleW = f32(oldView.getWidth()) / f32(Imp.ScreenPos.getWidth());
	f32 scaleH = f32(oldView.getHeight()) / f32(Imp.ScreenPos.getHeight());

	//f32 transW = f32(Impostors[i].ScreenPos.getWidth()/2) / (f32(oldView.getWidth()) - f32(Impostors[i].ScreenPos.getCenter().X));
	//f32 transH = f32(Impostors[i].ScreenPos.getHeight()/2) / (f32(oldView.getHeight()) - f32(Impostors[i].ScreenPos.getCenter().X));

	f32 transW = (f32(oldView.getCenter().X) - f32(Imp.ScreenPos.getCenter().X)) / f32(Imp.ScreenPos.getWidth());
	f32 transH = (f32(oldView.getCenter().Y) -  f32(Imp.ScreenPos.getCenter().Y)) / f32(Imp.ScreenPos.getHeight());

	core::matrix4 proj(cam->getProjectionMatrix());
	core::matrix4 zoom, trans;

	Imp.Time = Timer->getRealTime();

	zoom.setScale(core::vector3df(scaleW, scaleH, 1.0));
	trans.setTranslation(core::vector3df(transW*2,-transH*2,0.0));


	proj = zoom * proj;
#if defined(GENERATE_METHOD_1)
	proj = trans * proj;
#endif




	// set the correct render target and viewport
	setTarget(Imp);

	// draw the scene
	cam2->setProjectionMatrix(proj);
	E_CULLING_TYPE culltype = EAC_FRUSTUM_BOX;
	n->setAutomaticCulling(EAC_OFF);
	//cam2->render();
//	n->setSceneManager(LocalManager);
	n->OnRegisterSceneNode();
	LocalManager->drawAll();

	n->setAutomaticCulling(culltype);

	//s32 numberzzz = LocalManager->getParameters()->getAttributeAsInt("culled");

	// copy work buffer back
	s32 slot = Buffers[Imp.BufferID].SlotSize;
	//SceneManager->getGUIEnvironment()->getBuiltInFont()->draw(L"HI THERE!", core::rect<s32>(0, 0, slot, slot), video::SColor(), true, true);
	SceneManager->getVideoDriver()->setRenderTarget(Buffers[ Imp.BufferID].Texture, false, true);
	//SceneManager->getVideoDriver()->setRenderTarget(0);



	//LocalManager->getVideoDriver()->setViewPort( core::rect<s32>(0,0,TextureWidth,TextureWidth) );

	s32 d = TextureWidth / slot;
	s32 x = (Imp.SlotID % d) * slot;
	s32 y = (Imp.SlotID / d) * slot;

	//LocalManager->getVideoDriver()->setViewPort( core::rect<s32>(0,0,TextureWidth,TextureWidth) );
/*
	SceneManager->getVideoDriver()->draw2DRectangle(
		video::SColor(127,0,0,0),
		core::rect<s32>(x,y,x+slot,y+slot));
	SceneManager->getVideoDriver()->draw2DRectangle(
		video::SColor(100,0,0,0),
		core::rect<s32>(x,y,x+slot,y+slot));
	SceneManager->getVideoDriver()->draw2DRectangle(
		video::SColor(100,0,0,0),
		core::rect<s32>(x,y,x+slot,y+slot));
*/
	//SceneManager->getVideoDriver()->setTransform

	core::rect<s32> clipRect(x,y, x+slot,y+slot);

	video::SMaterial m;
	m.MaterialTypeParam =video::pack_texureBlendFunc(video::EBF_ONE, video::EBF_ONE_MINUS_DST_ALPHA, video::EMFN_MODULATE_1X);
	m.MaterialType = video::EMT_ONETEXTURE_BLEND;
	m.Lighting=false;
	m.ZBuffer = false;
	m.ZWriteEnable = false;
	m.TextureLayer[0].TextureWrapU = video::ETC_CLAMP;
	m.setTexture(0, WorkTexture);

	video::S3DVertex Vertices[6];

	Vertices[0] = video::S3DVertex(-1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,255,255,255), 0.0f, YDirection);
	Vertices[1] = video::S3DVertex(-1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,255,255,255), 0.0f, 0.0f);
	Vertices[2] = video::S3DVertex( 1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,255,255,255), 1.0f, 0.0f);
	Vertices[3] = video::S3DVertex( 1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,255,255,255), 1.0f, YDirection);
	Vertices[4] = video::S3DVertex(-1.0f, -1.0f, 0.0f,1,1,0, video::SColor(255,255,255,255), 0.0f, YDirection);
	Vertices[5] = video::S3DVertex( 1.0f,  1.0f, 0.0f,1,1,0, video::SColor(255,255,255,255), 1.0f, 0.0f);

	const u16 i1[] = {0,1,2,3,4,5};
	const u16 i2[] = {0,2,1,3,5,4};
	const u16* indices = i1;

	core::matrix4 matrix, matrix2;
	if (YDirection == -1.0f)
	{
		matrix2.setScale(core::vector3df(1.0f,-1.0f,1.0f));
		indices = i2;
	}
	LocalManager->getVideoDriver()->setViewPort( clipRect );
	LocalManager->getVideoDriver()->setMaterial(m);
	SceneManager->getVideoDriver()->setTransform(video::ETS_WORLD, matrix);
	SceneManager->getVideoDriver()->setTransform(video::ETS_PROJECTION, matrix2);
	SceneManager->getVideoDriver()->setTransform(video::ETS_VIEW, matrix);
	SceneManager->getVideoDriver()->drawIndexedTriangleList(&Vertices[0], 6, &indices[0], 2);
	LocalManager->getVideoDriver()->setViewPort(core::rect<s32>(0,0,TextureWidth, TextureWidth));

	//SceneManager->getVideoDriver()->draw2DImage(
	//	WorkTexture,
	//	core::position2di(x,y),
	//	core::rect<s32>(0,0,slot, slot),
	//	&clipRect,
	//	video::SColor(255,255,255,255),true);

	if (DebugDataVisible & EDS_IMPOSTOR_INFO && DebugFont)
	{
		core::stringw text;
		video::SColor col(255,255,0,0);
		core::rect<s32> clip(x, y, x+slot, 0);
		s32 third = s32(f32(slot)*0.5f);

		text=L"Buf: "; text+=Imp.BufferID;
		clip.UpperLeftCorner.Y = y+third;
		clip.LowerRightCorner.Y = y+ third*2;
		DebugFont->draw(text.c_str(), clip, col, true, true, &clip);

		text=L"Region: "; text+=Imp.SlotID;
		clip.UpperLeftCorner.Y = y+third*2;
		clip.LowerRightCorner.Y = y+slot;
		DebugFont->draw(text.c_str(), clip, col, true, true, &clip);
	}


	//core::rect<s32> blaView = SceneManager->getVideoDriver()->getViewPort();

	//SceneManager->getVideoDriver()->setTransform(video::ETS_WORLD, n->getAbsoluteTransformation());
	//SceneManager->getVideoDriver()->draw3DBox(n->getBoundingBox());

	// restore states
	SceneManager->getVideoDriver()->setRenderTarget(0, false, false);
	LocalManager->getVideoDriver()->setViewPort(oldView);

//	n->setSceneManager(oldManager);
}
void CImpostorSceneNode::OnRegisterSceneNode()
{
	if (!IsVisible)
		return;

	RenderCount++;

	// in here we:
	// decide which nodes need updates, add them to the queue
	// process the render queue
	//  allocate textures and mesh buffers if required
	// perform clean up tasks:
	//  garbage collection- free up spaces
	//  reorganise


	// get collision manager
	ISceneCollisionManager* colmgr = SceneManager->getSceneCollisionManager();

	// and the active camera
	ICameraSceneNode* cam = SceneManager->getActiveCamera();
	core::aabbox3df camBB = cam->getViewFrustum()->getBoundingBox();
	u32 now = Timer->getRealTime();

	// loop through all impostor nodes
	u32 i;
	for (i=0; i < Impostors.size(); ++i)
	{
		SNodeLink &Imp = Impostors[i];
		ISceneNode *n = Imp.Node;

		// skip invisible and culled nodes
		if (!n->isVisible() || !camBB.intersectsWithBox(n->getTransformedBoundingBox()))
		{
			//Culled++;
			Imp.IsActive = false;
			continue;
		}

		updatePosAndVector(Imp);

		// now we have the screen position...
		core::rect<s32> r = SceneManager->getVideoDriver()->getViewPort();

		if (!Imp.NewPos.isValid() || !r.isRectCollided(Imp.NewPos) )
		{
			// culled
			// Culled++;
			continue;
		}

		core::dimension2di newSize = Imp.NewPos.getSize();

		// Change in rotation: a.length >= a.dotProduct(b) <= -a.length
		f32 diff = 0;

		// far plane = never update, near plane = always update
		f32 far = cam->getFarValue();
		far *= far;
		f32 dist = Imp.Node->getAbsolutePosition().getDistanceFromSQ(cam->getAbsolutePosition());
		dist = 1.0 - (far/dist); // value between 0 and 1
		diff = dist;
		Imp.Score = dist;

		//s32 a = core::max_<s32>(Imp.NewPos.getWidth(), Imp.NewPos.getHeight());
		//diff *= f32(a);

		bool reRender = diff > Threshold;
		//reRender =true;

		reRender = reRender ||
			( !Imp.IsQueued && Imp.BufferID != -1 &&
			Buffers[Imp.BufferID].SlotSize < getTextureSizeFromSurfaceSize(core::max_<s32>(newSize.Width, newSize.Height)));

		// so small that we don't care about it
		if (newSize.Width < 4 || newSize.Height < 4)
		{
			Imp.IsActive = false;
			// object was culled
			//Culled++;
			continue;
		}

		// too large to fit in a texture slot
		if (newSize.Width > MaxSize || newSize.Height > MaxSize)
		{
			// get rid
			releaseSlot(Imp);
			Imp.IsActive = false;
		}
		else
		{
			Imp.IsActive = true;
		}

		if (Imp.IsActive && Imp.BufferID == -1 && !Imp.IsQueued )
			reRender = true;

		if (Imp.IsActive)
		{
			// impostor replaces the node
			if (reRender && now > Imp.Time + MinTime)
			{

				if (!Imp.IsQueued)
				{
					CacheMisses++;

					Imp.IsQueued = true;

					SRenderQueueItem q;
					q.Node = &Imp;
					//q.Value = val;

					RenderQueue.push_back(q);
				}
				else
				{
					//QueueHits++;
				}
			}
			else
			{
				// don't re-render the impostor texture, only draw it
				CacheHits++;
			}
		}
		if (!Imp.IsActive) // || ( Imp.BufferID == -1 && Imp.IsQueued))
		{
			// original node is visible
			n->OnRegisterSceneNode();
			// cache miss
			CacheMisses++;
		}
	}

	SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
}