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); }