bool Laser::OnEvent( const SEvent& event ) { // Remember whether each key is down or up if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) { if(lastPosX != event.MouseInput.X) { if ( (event.MouseInput.X > ((SCREEN_WIDTH - CAMERA_VIEW_WIDTH)* 0.5f) ) && (event.MouseInput.X < ((SCREEN_WIDTH + CAMERA_VIEW_WIDTH)* 0.5f ) ) ) { ICameraSceneNode* cam = SceneManager->getActiveCamera(); const scene::SViewFrustum* f = cam->getViewFrustum(); core::vector3df farLeftUp = f->getFarLeftUp(); core::vector3df lefttoright = f->getFarRightUp() - farLeftUp; core::vector3df uptodown = f->getFarLeftDown() - farLeftUp; float diffX = lastPosX - event.MouseInput.X; core::vector3df currentPos = guidedLight->getPosition(); lefttoright.normalize(); core::vector3df finalPos = currentPos + (lefttoright * -diffX*0.5f) ; guidedLight->setPosition(finalPos); laserLight->setPosition(finalPos); lastPosX = event.MouseInput.X; } } if(lastPosY!= event.MouseInput.Y) { if ( (event.MouseInput.Y > ((SCREEN_HEIGHT - CAMERA_VIEW_HEIGHT)* 0.5f) ) && (event.MouseInput.Y < ((SCREEN_HEIGHT + CAMERA_VIEW_HEIGHT)* 0.5f ) ) ) { ICameraSceneNode* cam = SceneManager->getActiveCamera(); const scene::SViewFrustum* f = cam->getViewFrustum(); core::vector3df farLeftUp = f->getFarLeftUp(); core::vector3df lefttoright = f->getFarRightUp() - farLeftUp; core::vector3df uptodown = f->getFarLeftDown() - farLeftUp; float diffY = lastPosY - event.MouseInput.Y; core::vector3df currentPos = guidedLight->getPosition(); uptodown.normalize(); core::vector3df finalPos = currentPos + (uptodown * -diffY*0.5f) ; guidedLight->setPosition(finalPos); laserLight->setPosition(finalPos); lastPosY = event.MouseInput.Y; } } laserLight->setVisible(event.MouseInput.isLeftPressed()); return true; //consume } return false; }
// selectObject // detect list objs at rect void CDocument::selectObject( int x, int y, int w, int h, bool isControlHold ) { IView *pView = getIView(); ISceneManager *smgr = pView->getSceneMgr(); ICameraSceneNode *camera = smgr->getActiveCamera(); // if no camera if ( camera == NULL ) return; const SViewFrustum* viewFrustum = camera->getViewFrustum(); ISceneCollisionManager *collMan = smgr->getSceneCollisionManager(); int screenX = -1, screenY = -1; ArrayZoneIter iZone = m_zones.begin(), iEnd = m_zones.end(); while ( iZone != iEnd ) { ArrayGameObject* listObj = (*iZone)->getChilds(); ArrayGameObjectIter iObj = listObj->begin(), objEnd = listObj->end(); ISceneNode *pNode = NULL; while ( iObj != objEnd ) { CGameObject *pGameObj = (CGameObject*)(*iObj); pNode = pGameObj->getSceneNode(); if ( pNode != NULL && pGameObj->isVisible() ) { core::vector3df center = pGameObj->getPosition(); // check object is in frustum if ( viewFrustum->getBoundingBox().isPointInside( center ) ) { if ( pView->getScreenCoordinatesFrom3DPosition( center, &screenX, &screenY ) ) { if ( x <= screenX && screenX <= x + w && y <= screenY && screenY <= y + h ) { if ( isControlHold == false || pGameObj->getObjectState() == CGameObject::Normal ) m_selectObjects.push_back( pGameObj ); } // inselect } // getScreenCoordinatesFrom3DPosition } // frustum } iObj++; } iZone++; } }
//! renders the node. void COctTreeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (vertexType == -1 || !driver) return; ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera) return; bool isTransparentPass = SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; ++PassCount; driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); SViewFrustum frust = *camera->getViewFrustum(); //transform the frustum to the current absolute transformation core::matrix4 invTrans(AbsoluteTransformation); invTrans.makeInverse(); frust.transform(invTrans); /* //const core::aabbox3d<float> &box = frust.getBoundingBox(); */ switch(vertexType) { case video::EVT_STANDARD: { //StdOctTree->calculatePolys(box); StdOctTree->calculatePolys(frust); const OctTree<video::S3DVertex>::SIndexData* d = StdOctTree->getIndexData(); for (u32 i=0; i<Materials.size(); ++i) { if ( 0 == d[i].CurrentSize ) continue; const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(Materials[i].MaterialType); const bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(Materials[i]); driver->drawIndexedTriangleList( &StdMeshes[i].Vertices[0], StdMeshes[i].Vertices.size(), d[i].Indices, d[i].CurrentSize / 3); } } // for debug purposes only if (DebugDataVisible && !Materials.empty() && PassCount==1) { const core::aabbox3df& box = frust.getBoundingBox(); core::array< const core::aabbox3d<f32>* > boxes; video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { StdOctTree->getBoundingBoxes(box, boxes); for (u32 b=0; b!=boxes.size(); ++b) driver->draw3DBox(*boxes[b]); } if ( DebugDataVisible & scene::EDS_BBOX ) driver->draw3DBox(Box,video::SColor(0,255,0,0)); } } break; case video::EVT_2TCOORDS: { //LightMapOctTree->calculatePolys(box); LightMapOctTree->calculatePolys(frust); const OctTree<video::S3DVertex2TCoords>::SIndexData* d = LightMapOctTree->getIndexData(); for (u32 i=0; i<Materials.size(); ++i) { if ( 0 == d[i].CurrentSize ) continue; const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(Materials[i].MaterialType); const bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(Materials[i]); driver->drawIndexedTriangleList( &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(), d[i].Indices, d[i].CurrentSize / 3); } } // for debug purposes only if (DebugDataVisible && !Materials.empty() && PassCount==1) { const core::aabbox3d<float> &box = frust.getBoundingBox(); core::array< const core::aabbox3d<f32>* > boxes; video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { LightMapOctTree->getBoundingBoxes(box, boxes); for (u32 b=0; b<boxes.size(); ++b) driver->draw3DBox(*boxes[b]); } if ( DebugDataVisible & scene::EDS_BBOX ) driver->draw3DBox(Box,video::SColor(0,255,0,0)); } } break; case video::EVT_TANGENTS: { //TangentsOctTree->calculatePolys(box); TangentsOctTree->calculatePolys(frust); const OctTree<video::S3DVertexTangents>::SIndexData* d = TangentsOctTree->getIndexData(); for (u32 i=0; i<Materials.size(); ++i) { if ( 0 == d[i].CurrentSize ) continue; const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(Materials[i].MaterialType); const bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(Materials[i]); driver->drawIndexedTriangleList( &TangentsMeshes[i].Vertices[0], TangentsMeshes[i].Vertices.size(), d[i].Indices, d[i].CurrentSize / 3); } } // for debug purposes only if (DebugDataVisible && !Materials.empty() && PassCount==1) { const core::aabbox3d<float> &box = frust.getBoundingBox(); core::array< const core::aabbox3d<f32>* > boxes; video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { TangentsOctTree->getBoundingBoxes(box, boxes); for (u32 b=0; b<boxes.size(); ++b) driver->draw3DBox(*boxes[b]); } if ( DebugDataVisible & scene::EDS_BBOX ) driver->draw3DBox(Box,video::SColor(0,255,0,0)); } } break; } }
//! renders the node. void COctreeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (!driver) return; ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera) return; bool isTransparentPass = SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; ++PassCount; driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); if (Shadow) Shadow->updateShadowVolumes(); SViewFrustum frust = *camera->getViewFrustum(); //transform the frustum to the current absolute transformation if ( !AbsoluteTransformation.isIdentity() ) { core::matrix4 invTrans(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE); frust.transform(invTrans); } const core::aabbox3d<float> &box = frust.getBoundingBox(); if (BoxBased) StdOctree->calculatePolys(box); else StdOctree->calculatePolys(frust); const Octree::SIndexData* d = StdOctree->getIndexData(); for (u32 i=0; i<Materials.size(); ++i) { if ( 0 == d[i].CurrentSize ) continue; const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(Materials[i].MaterialType); const bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(Materials[i]); if (UseVBOs) { if (UseVisibilityAndVBOs) { scene::IIndexBuffer* oldBuffer = StdMeshes[i]->getIndexBuffer(); oldBuffer->grab(); StdMeshes[i]->setIndexBuffer(d[i].IndexBuffer); StdMeshes[i]->setDirty(scene::EBT_INDEX); driver->drawMeshBuffer ( StdMeshes[i] ); StdMeshes[i]->setIndexBuffer(oldBuffer); oldBuffer->drop(); StdMeshes[i]->setDirty(scene::EBT_INDEX); } else driver->drawMeshBuffer ( StdMeshes[i] ); } else driver->drawIndexedTriangleList(false, StdMeshes[i]->getVertexBuffer(), false, d[i].IndexBuffer, d[i].CurrentSize / 3); } } // for debug purposes only if (DebugDataVisible && !Materials.empty() && PassCount==1) { const core::aabbox3d<float> &box = frust.getBoundingBox(); core::array< const core::aabbox3d<f32>* > boxes; video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { StdOctree->getBoundingBoxes(box, boxes); for (u32 b=0; b<boxes.size(); ++b) driver->draw3DBox(*boxes[b]); } if ( DebugDataVisible & scene::EDS_BBOX ) driver->draw3DBox(Box,video::SColor(0,255,0,0)); } }
//! render void CParticleSystemSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera || !driver) return; #if 0 // calculate vectors for letting particles look to camera core::vector3df view(camera->getTarget() - camera->getAbsolutePosition()); view.normalize(); view *= -1.0f; #else const core::matrix4 &m = camera->getViewFrustum()->getTransform( video::ETS_VIEW ); const core::vector3df view ( -m[2], -m[6] , -m[10] ); #endif // reallocate arrays, if they are too small reallocateBuffers(); // create particle vertex data s32 idx = 0; for (u32 i=0; i<Particles.size(); ++i) { const SParticle& particle = Particles[i]; #if 0 core::vector3df horizontal = camera->getUpVector().crossProduct(view); horizontal.normalize(); horizontal *= 0.5f * particle.size.Width; core::vector3df vertical = horizontal.crossProduct(view); vertical.normalize(); vertical *= 0.5f * particle.size.Height; #else f32 f; f = 0.5f * particle.size.Width; const core::vector3df horizontal ( m[0] * f, m[4] * f, m[8] * f ); f = -0.5f * particle.size.Height; const core::vector3df vertical ( m[1] * f, m[5] * f, m[9] * f ); #endif Buffer->Vertices[0+idx].Pos = particle.pos + horizontal + vertical; Buffer->Vertices[0+idx].Color = particle.color; Buffer->Vertices[0+idx].Normal = view; Buffer->Vertices[1+idx].Pos = particle.pos + horizontal - vertical; Buffer->Vertices[1+idx].Color = particle.color; Buffer->Vertices[1+idx].Normal = view; Buffer->Vertices[2+idx].Pos = particle.pos - horizontal - vertical; Buffer->Vertices[2+idx].Color = particle.color; Buffer->Vertices[2+idx].Normal = view; Buffer->Vertices[3+idx].Pos = particle.pos - horizontal + vertical; Buffer->Vertices[3+idx].Color = particle.color; Buffer->Vertices[3+idx].Normal = view; idx +=4; } // render all core::matrix4 mat; if (!ParticlesAreGlobal) mat.setTranslation(AbsoluteTransformation.getTranslation()); driver->setTransform(video::ETS_WORLD, mat); driver->setMaterial(Buffer->Material); driver->drawVertexPrimitiveList(Buffer->getVertices(), Particles.size()*4, Buffer->getIndices(), Particles.size()*2, video::EVT_STANDARD, EPT_TRIANGLES,Buffer->getIndexType()); // for debug purposes only: if ( DebugDataVisible & scene::EDS_BBOX ) { driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); video::SMaterial deb_m; deb_m.Lighting = false; driver->setMaterial(deb_m); driver->draw3DBox(Buffer->BoundingBox, video::SColor(0,255,255,255)); } }
//! OnAnimate() is called just before rendering the whole scene. //! nodes may calculate or store animations here, and may do other useful things, //! dependent on what they are. void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) { //Alt + LM = Rotate around camera pivot //Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot) //Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed) if (node->getType() != ESNT_CAMERA) return; ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node); if (OldCamera != camera) { OldTarget = camera->getTarget(); OldCamera = camera; } Target = camera->getTarget(); const SViewFrustum* va = camera->getViewFrustum(); f32 nRotX = RotX; f32 nRotY = RotY; f32 nZoom = CurrentZoom; if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) ) { if (!Zooming) { ZoomStartX = MousePos.X; ZoomStartY = MousePos.Y; Zooming = true; nZoom = CurrentZoom; } else { f32 old = nZoom; nZoom += (ZoomStartX - MousePos.X) * ZoomSpeed; f32 targetMinDistance = 0.1f; if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close nZoom = targetMinDistance; if (nZoom < 0) nZoom = old; } } else { if (Zooming) { f32 old = CurrentZoom; CurrentZoom = CurrentZoom + (ZoomStartX - MousePos.X ) * ZoomSpeed; nZoom = CurrentZoom; if (nZoom < 0) nZoom = CurrentZoom = old; } Zooming = false; } // Translation --------------------------------- core::vector3df translate(OldTarget), UpVector(camera->getUpVector()); core::vector3df tvectX = Pos - Target; tvectX = tvectX.crossProduct(UpVector); tvectX.normalize(); core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown()); tvectY = tvectY.crossProduct(UpVector.Y > 0 ? Pos - Target : Target - Pos); tvectY.normalize(); if (isMouseKeyDown(2) && !Zooming) { if (!Translating) { TranslateStartX = MousePos.X; TranslateStartY = MousePos.Y; Translating = true; } else { translate += tvectX * (TranslateStartX - MousePos.X)*TranslateSpeed + tvectY * (TranslateStartY - MousePos.Y)*TranslateSpeed; } } else { if (Translating) { translate += tvectX * (TranslateStartX - MousePos.X)*TranslateSpeed + tvectY * (TranslateStartY - MousePos.Y)*TranslateSpeed; OldTarget = translate; } Translating = false; } // Rotation ------------------------------------ if (isMouseKeyDown(0) && !Zooming) { if (!Rotating) { RotateStartX = MousePos.X; RotateStartY = MousePos.Y; Rotating = true; nRotX = RotX; nRotY = RotY; } else { nRotX += (RotateStartX - MousePos.X) * RotateSpeed; nRotY += (RotateStartY - MousePos.Y) * RotateSpeed; } } else { if (Rotating) { RotX = RotX + (RotateStartX - MousePos.X) * RotateSpeed; RotY = RotY + (RotateStartY - MousePos.Y) * RotateSpeed; nRotX = RotX; nRotY = RotY; } Rotating = false; } // Set Pos ------------------------------------ Target = translate; Pos.X = nZoom + Target.X; Pos.Y = Target.Y; Pos.Z = Target.Z; Pos.rotateXYBy(nRotY, Target); Pos.rotateXZBy(-nRotX, Target); // Rotation Error ---------------------------- // jox: fixed bug: jitter when rotating to the top and bottom of y UpVector.set(0,1,0); UpVector.rotateXYBy(-nRotY); UpVector.rotateXZBy(-nRotX+180.f); camera->setPosition(Pos); camera->setTarget(Target); camera->setUpVector(UpVector); }
//! OnAnimate() is called just before rendering the whole scene. //! nodes may calculate or store animations here, and may do other useful things, //! dependent on what they are. void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs) { //Alt + LM = Rotate around camera pivot //Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot) //Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed) if (!node || node->getType() != ESNT_CAMERA) return; ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node); // If the camera isn't the active camera, and receiving input, then don't process it. if(!camera->isInputReceiverEnabled()) return; scene::ISceneManager * smgr = camera->getSceneManager(); if(smgr && smgr->getActiveCamera() != camera) return; if (OldCamera != camera) { OldTarget = camera->getTarget(); OldCamera = camera; LastCameraTarget = OldTarget; } else { OldTarget += camera->getTarget() - LastCameraTarget; } core::vector3df target = camera->getTarget(); f32 nRotX = RotX; f32 nRotY = RotY; f32 nZoom = CurrentZoom; if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) ) { if (!Zooming) { ZoomStart = MousePos; Zooming = true; nZoom = CurrentZoom; } else { const f32 targetMinDistance = 0.1f; nZoom += (ZoomStart.X - MousePos.X) * ZoomSpeed; if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close nZoom = targetMinDistance; } } else if (Zooming) { const f32 old = CurrentZoom; CurrentZoom = CurrentZoom + (ZoomStart.X - MousePos.X ) * ZoomSpeed; nZoom = CurrentZoom; if (nZoom < 0) nZoom = CurrentZoom = old; Zooming = false; } // Translation --------------------------------- core::vector3df translate(OldTarget), upVector(camera->getUpVector()); core::vector3df tvectX = Pos - target; tvectX = tvectX.crossProduct(upVector); tvectX.normalize(); const SViewFrustum* const va = camera->getViewFrustum(); core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown()); tvectY = tvectY.crossProduct(upVector.Y > 0 ? Pos - target : target - Pos); tvectY.normalize(); if (isMouseKeyDown(2) && !Zooming) { if (!Translating) { TranslateStart = MousePos; Translating = true; } else { translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; } } else if (Translating) { translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed + tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed; OldTarget = translate; Translating = false; } // Rotation ------------------------------------ if (isMouseKeyDown(0) && !Zooming) { if (!Rotating) { RotateStart = MousePos; Rotating = true; nRotX = RotX; nRotY = RotY; } else { nRotX += (RotateStart.X - MousePos.X) * RotateSpeed; nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; } } else if (Rotating) { RotX += (RotateStart.X - MousePos.X) * RotateSpeed; RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed; nRotX = RotX; nRotY = RotY; Rotating = false; } // Set Pos ------------------------------------ target = translate; Pos.X = nZoom + target.X; Pos.Y = target.Y; Pos.Z = target.Z; Pos.rotateXYBy(nRotY, target); Pos.rotateXZBy(-nRotX, target); // Rotation Error ---------------------------- // jox: fixed bug: jitter when rotating to the top and bottom of y upVector.set(0,1,0); upVector.rotateXYBy(-nRotY); upVector.rotateXZBy(-nRotX+180.f); camera->setPosition(Pos); camera->setTarget(target); camera->setUpVector(upVector); LastCameraTarget = camera->getTarget(); }
ISceneNode* CCombatSimulatorView::SelectNode(position2di mouse_pos) { scene::ISceneCollisionManager* pCollMgr = p_smgr->getSceneCollisionManager(); vector2d<s32> cursor = p_device->getCursorControl()->getPosition(); core::line3d<f32> ln(0,0,0,0,0,0); ICameraSceneNode* camera = p_smgr->getActiveCamera(); const scene::SViewFrustum* f = camera->getViewFrustum(); core::vector3df farLeftUp = f->getFarLeftUp(); core::vector3df lefttoright = f->getFarRightUp() - farLeftUp; core::vector3df uptodown = f->getFarLeftDown() - farLeftUp; RECT m_rect; this->GetWindowRect( &m_rect); f32 dx = (cursor.X + m_rect.left) / (f32) (m_rect.right - m_rect.left) ; f32 dy = (cursor.Y + m_rect.top) / (f32) (m_rect.bottom - m_rect.top); if (camera->isOrthogonal()) ln.start = f->cameraPosition + (lefttoright * (dx-0.5f)) + (uptodown * (dy-0.5f)); else ln.start = f->cameraPosition; ln.end = farLeftUp + (lefttoright * dx) + (uptodown * dy); if ( ln.start == ln.end ) return 0; ISceneNode* pNode = pCollMgr->getSceneNodeFromRayBB(ln, 0, true, p_ShipParent); if( pNode ) { irr::core::list<ISceneNode*> list = pNode->getChildren(); irr::core::list<ISceneNode*>::Iterator it = list.begin(); ESCENE_NODE_TYPE t = pNode->getType(); if (pNode->getType() == ESNT_SPHERE) pNode->setVisible(false); for (it;it != list.end(); it++) { if ((*it)->getType() ==ESNT_SPHERE) { if ( (*it)->isVisible()) (*it)->setVisible(false); else (*it)->setVisible(true); } } } return pNode; }
// render // ISceneNode implement void CGameStaticShadowSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera || !driver) return; const core::matrix4 &m = camera->getViewFrustum()->getTransform( video::ETS_VIEW ); const core::vector3df view ( -m[2], -m[6] , -m[10] ); // get shadow comp CShadowComponent* shadow = (CShadowComponent*)m_owner->getComponent(IObjectComponent::Shadow); if ( shadow == NULL ) return; // make buffer by shadow pos std::vector<video::S3DVertex>& listShadow = shadow->getListShadow(); int nShadow = (int)listShadow.size(); if ( nShadow > 0 ) { // create shadow mesh buffer reallocateBuffers(nShadow); s32 idx = 0; std::vector<video::S3DVertex>::iterator i = listShadow.begin(), end = listShadow.end(); while (i != end) { core::vector3df pos = i->Pos; core::vector3df nor = i->Normal; float width = 80.0f; float height = 80.0f; // set texcoord Buffer->Vertices[0+idx].TCoords.set(0.0f, 0.0f); Buffer->Vertices[1+idx].TCoords.set(0.0f, 1.0f); Buffer->Vertices[2+idx].TCoords.set(1.0f, 1.0f); Buffer->Vertices[3+idx].TCoords.set(1.0f, 0.0f); // calc plane position f32 f = 0.5f * width; core::vector3df horizontal ( f, 0, 0 ); f = -0.5f * height; core::vector3df vertical ( 0, 0, f ); // rotate plane core::quaternion quaternion; quaternion.rotationFromTo( core::vector3df(0.0f,1.0f,0.0f), nor ); core::matrix4 matrix = quaternion.getMatrix(); matrix.rotateVect(horizontal); matrix.rotateVect(vertical); // update buffer position Buffer->Vertices[0+idx].Pos = pos + horizontal + vertical; Buffer->Vertices[0+idx].Color = SColor(255,0,0,0); Buffer->Vertices[0+idx].Normal = nor; Buffer->Vertices[1+idx].Pos = pos + horizontal - vertical; Buffer->Vertices[1+idx].Color = SColor(255,0,0,0); Buffer->Vertices[1+idx].Normal = nor; Buffer->Vertices[2+idx].Pos = pos - horizontal - vertical; Buffer->Vertices[2+idx].Color = SColor(255,0,0,0); Buffer->Vertices[2+idx].Normal = nor; Buffer->Vertices[3+idx].Pos = pos - horizontal + vertical; Buffer->Vertices[3+idx].Color = SColor(255,0,0,0); Buffer->Vertices[3+idx].Normal = nor; idx += 4; Buffer->BoundingBox.addInternalPoint(pos); ++i; } // render all core::matrix4 mat; driver->setTransform(video::ETS_WORLD, mat); // render 2 face on nonbillboard particle Buffer->Material.BackfaceCulling = false; Buffer->Material.FrontfaceCulling = false; Buffer->Material.Lighting = false; driver->setMaterial(Buffer->Material); driver->drawVertexPrimitiveList( Buffer->getVertices(), nShadow*4, Buffer->getIndices(), nShadow*2, video::EVT_STANDARD, EPT_TRIANGLES, Buffer->getIndexType() ); } listShadow.clear(); }
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); }