Frustum Camera::GetSplitFrustum(float nearClip, float farClip) const { if (projectionDirty_) UpdateProjection(); nearClip = Max(nearClip, projNearClip_); farClip = Min(farClip, projFarClip_); if (farClip < nearClip) farClip = nearClip; Frustum ret; if (customProjection_) { // DefineSplit() needs to project the near & far distances, so can not use a combined view-projection matrix. // Transform to world space afterward instead ret.DefineSplit(projection_, nearClip, farClip); ret.Transform(GetEffectiveWorldTransform()); } else { if (!orthographic_) ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip, GetEffectiveWorldTransform()); else ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip, GetEffectiveWorldTransform()); } return ret; }
shared_ptr<SceneNode> CameraObjectParams::VCreateSceneNode(shared_ptr<Scene> pScene) { // size_t origsize = strlen(m_ModellFilename) + 1; // const size_t newsize = StaticMeshObjectParams::sk_MaxFileNameLen ; // size_t convertedChars = 0; // wchar_t meshFileName[newsize]; // mbstowcs_s(&convertedChars, meshFileName, origsize, m_ModellFilename, _TRUNCATE); // // origsize = strlen(m_FXFileName) + 1; // wchar_t effectFileName[newsize]; // mbstowcs_s(&convertedChars, effectFileName, origsize, m_FXFileName, _TRUNCATE); stringstream stmName; stmName << "Object"; stmName << (*m_Id); Frustum frustum; frustum.Init(D3DX_PI/4.0f, 1.0f, 0.1f, 10000.0f); CameraNode* node = DEBUG_CLIENTBLOCK CameraNode(m_Id, stmName.str(), m_Mat ,frustum); shared_ptr<SceneNode> cameraNode(node); pScene->SetCamera( shared_ptr<CameraNode>((CameraNode*)node) ); return cameraNode; }
Box3F PSSMLightShadowMap::_calcClipSpaceAABB(const Frustum& f, const MatrixF& transform, F32 farDist) { // Calculate frustum center Point3F center(0,0,0); for (U32 i = 0; i < 8; i++) { const Point3F& pt = f.getPoints()[i]; center += pt; } center /= 8; // Calculate frustum bounding sphere radius F32 radius = 0.0f; for (U32 i = 0; i < 8; i++) radius = getMax(radius, (f.getPoints()[i] - center).lenSquared()); radius = mFloor( mSqrt(radius) ); // Now build box for sphere Box3F result; Point3F radiusBox(radius, radius, radius); result.minExtents = center - radiusBox; result.maxExtents = center + radiusBox; // Transform to light projection space transform.mul(result); return result; }
// computes a frustum with given far and near planes Frustum BaseCamera::CalculateFrustum( float fNear, float fFar ) { noVec3 vZ = Normalize(m_to - m_from); noVec3 vX = Normalize(Cross(m_up, vZ)); noVec3 vY = Normalize(Cross(vZ, vX)); float fAspect = GetApp()->GetAspectRatio(); float fNearPlaneHalfHeight = tanf(m_fov * 0.5f) * fNear; float fNearPlaneHalfWidth = fNearPlaneHalfHeight * fAspect; float fFarPlaneHalfHeight = tanf(m_fov * 0.5f) * fFar; float fFarPlaneHalfWidth = fFarPlaneHalfHeight * fAspect; noVec3 vNearPlaneCenter = m_from + vZ * fNear; noVec3 vFarPlaneCenter = m_from + vZ * fFar; Frustum frustum; frustum.m_pPoints[0] = noVec3(vNearPlaneCenter - vX*fNearPlaneHalfWidth - vY*fNearPlaneHalfHeight); frustum.m_pPoints[1] = noVec3(vNearPlaneCenter - vX*fNearPlaneHalfWidth + vY*fNearPlaneHalfHeight); frustum.m_pPoints[2] = noVec3(vNearPlaneCenter + vX*fNearPlaneHalfWidth + vY*fNearPlaneHalfHeight); frustum.m_pPoints[3] = noVec3(vNearPlaneCenter + vX*fNearPlaneHalfWidth - vY*fNearPlaneHalfHeight); frustum.m_pPoints[4] = noVec3(vFarPlaneCenter - vX*fFarPlaneHalfWidth - vY*fFarPlaneHalfHeight); frustum.m_pPoints[5] = noVec3(vFarPlaneCenter - vX*fFarPlaneHalfWidth + vY*fFarPlaneHalfHeight); frustum.m_pPoints[6] = noVec3(vFarPlaneCenter + vX*fFarPlaneHalfWidth + vY*fFarPlaneHalfHeight); frustum.m_pPoints[7] = noVec3(vFarPlaneCenter + vX*fFarPlaneHalfWidth - vY*fFarPlaneHalfHeight); // update frustum AABB frustum.CalculateAABB(); return frustum; }
/** * Factory constructor. * * Initializes the different components so they are accessible when * the setup method is executed. */ GameFactory::GameFactory() { // Create a frame and viewport. this->frame = new SDLFrame(WINDOW_WIDTH, WINDOW_HEIGHT, 32); // Main viewport Viewport* viewport = new Viewport(*frame); camera = new Camera(*(new ViewingVolume())); camera->SetPosition(Vector<3,float>(-100,0,-10)); camera->LookAt(Vector<3,float>(0,0,0)); // Bind the camera to the viewport Frustum* frustum = new Frustum(*camera); frustum->SetFar(1000); viewport->SetViewingVolume(frustum); // Create a renderer. this->renderer = new Renderer(); this->renderer->SetFarPlane(50000.0); this->renderer->initialize.Attach(*(new TextureLoader())); // space leak // Add a rendering view to the renderer this->renderer->process.Attach(*(new MyRenderingView(*viewport))); }
void ShadowManager::splitFrustum(const Frustum<float> &frustum) { splittedDistance.clear(); splittedFrustum.clear(); float near = frustum.computeNearDistance(); float far = viewingShadowDistance; if(viewingShadowDistance < 0.0f) { far = frustum.computeFarDistance(); } float previousSplitDistance = near; for(unsigned int i=1; i<=nbShadowMaps; ++i) { float uniformSplit = near + (far - near) * (i/static_cast<float>(nbShadowMaps)); float logarithmicSplit = near * pow(far/near, i/static_cast<float>(nbShadowMaps)); float splitDistance = (percentageUniformSplit * uniformSplit) + ((1.0 - percentageUniformSplit) * logarithmicSplit); splittedDistance.push_back(splitDistance); splittedFrustum.push_back(frustum.splitFrustum(previousSplitDistance, splitDistance)); previousSplitDistance = splitDistance; } }
void CullSystem::Cull( Frustum& frus, TreeNode<VisCell>& node, std::vector<std::list<Ptr<Renderable>>>& outRenderables) { InterSectResult result = frus.InterSect(node.GetContent().GetAABB()); if ( !result==INTERSECTOUT ) { std::list<Ptr<Renderable>>::iterator iter = node.GetContent().GetRenderables().begin(); if (result== INTERSECTIN) { for (;iter!=node.GetContent().GetRenderables().end();iter++) { RenderType rType = (*iter)->GetRenderType(); outRenderables[rType].push_back((*iter)); } } else { for (;iter!=node.GetContent().GetRenderables().end();iter++) { if ( frus.InterSect((*iter)->GetSubMesh()->GetVertexBuffer()->GetBBox())!= INTERSECTOUT) { RenderType rType = (*iter)->GetRenderType(); outRenderables[rType].push_back((*iter)); } } } for (int i = 0 ;i<(int)node.GetChildren().size();i++) { Cull( frus,*node.GetChildren()[i],outRenderables ); } } }
void ShadowManager::onFrustumUpdate(const Frustum<float> &frustum) { frustumDistance = frustum.computeFarDistance() + frustum.computeNearDistance(); splitFrustum(frustum); updateShadowLights(); }
// // HumanView::HumanView - Chapter 10, page 272 // HumanView::HumanView(shared_ptr<IRenderer> renderer) { //InitAudio(); //m_pProcessManager = AC_NEW ProcessManager; //m_PointerRadius = 1; // we assume we are on a mouse enabled machine - if this were a tablet we should detect it here. m_ViewId = gc_InvalidGameViewId; // Added post press for move, new, and destroy actor events and others //RegisterAllDelegates(); m_BaseGameState = BGS_Initializing; // what is the current game state if(renderer) { // Moved to the HumanView class post press m_pScene.reset(AC_NEW ScreenElementScene(renderer)); Frustum frustum; frustum.Init(GCC_PI/4.0f, 1.0f, 1.0f, 10000.0f); m_pCamera.reset(AC_NEW CameraNode(&Mat4x4::g_Identity, frustum)); AC_ASSERT(m_pScene && m_pCamera && _T("Out of memory")); m_pScene->VAddChild(INVALID_ACTOR_ID, m_pCamera); m_pScene->SetCamera(m_pCamera); } // to be removed later m_currTick = 0; // time right now m_lastDraw = 0; m_runFullSpeed = false; }
void wiSPTree::getVisible(Node* node, Frustum& frustum, CulledList& objects, SortType sort, CullStrictness type){ if(!node) return; int contain_type = frustum.CheckBox(node->box.corners); if(!contain_type) return; else{ for(Cullable* object : node->objects) if( type==SP_TREE_LOOSE_CULL || (type==SP_TREE_STRICT_CULL && contain_type==BOX_FRUSTUM_INSIDE || (contain_type==BOX_FRUSTUM_INTERSECTS && frustum.CheckBox(object->bounds.corners)) ) ) { #ifdef SORT_SPTREE_CULL object->lastSquaredDistMulThousand=(long)(wiMath::Distance(object->bounds.getCenter(),frustum.getCamPos())*1000); if (sort == SP_TREE_SORT_PAINTER) object->lastSquaredDistMulThousand *= -1; #endif objects.insert(object); } if(node->count){ for (unsigned int i = 0; i<node->children.size(); ++i) getVisible(node->children[i],frustum,objects,sort,type); } } }
void AseFile::CheckVisibility(Frustum &f) { visible = f.BoxInFrustum(min,max); if(!visible)return; for(int i=0; i<objects.size(); i++) objects[i].visible = f.BoxInFrustum(objects[i].min,objects[i].max); }
TEST(box_frustum, no_intersection) { const int focal = 1000; const int principal_Point = 500; //-- Setup a circular camera rig or "cardioid". const int iNviews = 4; const int iNbPoints = 6; const NViewDataSet d = NRealisticCamerasRing( iNviews, iNbPoints, nViewDatasetConfigurator(focal, focal, principal_Point, principal_Point, 5, 0)); // Put the box out of field of the camera // (since camera are Y up, we move the box along Y axis) const Vec3 position(0, -4, 0); const Box box(position, sqrt(1.)); { std::ostringstream os; os << "box.ply"; Box::export_Ply(box, os.str()); } // Test with infinite Frustum for each camera { std::vector<Frustum> vec_frustum; for (int i = 0; i < iNviews; ++i) { const Frustum f(principal_Point * 2, principal_Point * 2, d._K[i], d._R[i], d._C[i]); EXPECT_FALSE(f.intersect(box)); EXPECT_FALSE(box.intersect(f)); std::ostringstream os; os << i << "frust.ply"; Frustum::export_Ply(f, os.str()); } } // Test with truncated frustum { // Build frustum with near and far plane defined by min/max depth per camera for (int i = 0; i < iNviews; ++i) { double minDepth = std::numeric_limits<double>::max(); double maxDepth = std::numeric_limits<double>::min(); for (int j = 0; j < iNbPoints; ++j) { const double depth = Depth(d._R[i], d._t[i], d._X.col(j)); if (depth < minDepth) minDepth = depth; if (depth > maxDepth) maxDepth = depth; } const Frustum f(principal_Point * 2, principal_Point * 2, d._K[i], d._R[i], d._C[i], minDepth, maxDepth); EXPECT_FALSE(f.intersect(box)); EXPECT_FALSE(box.intersect(f)); } } }
/* wizualizuje obszar widziany przez kamerę. TODO: ta funkcja jest WOLNA, nie powinna być używana w buildzie. Da się ją przyśpieszyć używając VBO - vertices będzie po prostu tablicą wierzchołków, a edges będzie tablicą indeksów (z dwoma polami do zignorowania) */ void Camera::fillScene(const Frustum<float>&, ProcessedScene &scene) const { if (this->getVisualizeBoundingVolume() == false) return; Frustum<float> thisFrustum = this->getFrustum(); vector3f viewPoint = thisFrustum.viewPoint; const std::vector<Polyhedron<float>::PolyhedronEdge>& edges = thisFrustum.getEdges(); const std::vector<vector3f>& vertices = thisFrustum.getVertices(); if (edges.size() == 0) return; std::vector<line3f> lines; lines.reserve(edges.size()); for (uint i = 0; i < edges.size(); ++i) lines.push_back(line3f(vertices[edges[i].num_v1], vertices[edges[i].num_v2])); GeometryTask task; task.transformation = getWorldToLocalR(); task.shaderType = ShaderType::Lines; task.shaderArgs = shared(new ShaderArgs<line3f> (&lines[0], lines.size())); task.useLights = false; scene.geometry.push_back(task); GeometryTask task2; task2.transformation = getWorldToLocalR(); task2.shaderType = ShaderType::Points; task2.shaderArgs = shared(new ShaderArgs<vector3f>(&viewPoint, 1)); task2.useLights = false; scene.geometry.push_back(task); }
void Pass::doPass (void) { Frustum camFrustum; std::vector<SceneObject*>::iterator objsIter; std::vector<std::string>::iterator scenesIter; std::vector<std::shared_ptr<SceneObject>> sceneObjects; prepareBuffers(); std::shared_ptr<Camera> &aCam = RENDERMANAGER->getCamera (m_CameraName); const float *a = (float *)((mat4 *)RENDERER->getProp(IRenderer::PROJECTION_VIEW_MODEL, Enums::MAT4))->getMatrix(); camFrustum.setFromMatrix (a); RENDERMANAGER->clearQueue(); scenesIter = m_SceneVector.begin(); for ( ; scenesIter != m_SceneVector.end(); ++scenesIter) { std::shared_ptr<IScene> &aScene = RENDERMANAGER->getScene (*scenesIter); { PROFILE("View Frustum Culling"); aScene->findVisibleSceneObjects(&sceneObjects, camFrustum, *aCam); // sceneObjects = aScene->getAllObjects(); } for (auto &so: sceneObjects) { RENDERMANAGER->addToQueue (so, m_MaterialMap); } } RENDERMANAGER->processQueue(); }
void Terrain::computeVisiable(TerrainObserverPtr observer, std::vector<TerrainChunkPtr>& visiable) noexcept { assert(observer); Matrix4x4 view; view.makeLookAt_lh(observer->getPosition(), observer->getLookat(), observer->getUpVector()); Frustum fru; fru.extract(view); for (auto& it : _chunks) { auto pos = observer->getPosition(); int p = convChunked(pos.x); int q = convChunked(pos.z); if (it->distance(p, q) > _radiusRender) { continue; } if (it->visiable(fru, _chunkSize)) { visiable.push_back(it); } } }
bool Plane::Intersects(const Frustum &frustum) const { bool sign = IsOnPositiveSide(frustum.CornerPoint(0)); for(int i = 1; i < 8; ++i) if (sign != IsOnPositiveSide(frustum.CornerPoint(i))) return true; return false; }
Frustum Frustum_Perspective(float fov, float aspect, float znear, float zfar) { Frustum out; frustum_plane_corners(out.near, fov, aspect, -znear); frustum_plane_corners(out.far, fov, aspect, -zfar); out.update_planes(); return out; }
Frustum Light::WorldFrustum() const { const Matrix3x4& transform = WorldTransform(); Matrix3x4 frustumTransform(transform.Translation(), transform.Rotation(), 1.0f); Frustum ret; ret.Define(fov, 1.0f, 1.0f, 0.0f, range, frustumTransform); return ret; }
TEST(box_frustum, intersection) { const int focal = 1000; const int principal_Point = 500; //-- Setup a circular camera rig or "cardioid". const int iNviews = 4; const int iNbPoints = 6; const NViewDataSet d = NRealisticCamerasRing( iNviews, iNbPoints, nViewDatasetConfigurator(focal, focal, principal_Point, principal_Point, 5, 0)); const Box box(Vec3::Zero(), sqrt(1.)); { std::ostringstream os; os << "box.ply"; Box::export_Ply(box, os.str()); } // Test with infinite Frustum for each camera { for (int i=0; i < iNviews; ++i) { const Frustum f (principal_Point*2, principal_Point*2, d._K[i], d._R[i], d._C[i]); EXPECT_TRUE(f.intersect(box)); EXPECT_TRUE(box.intersect(f)); EXPECT_TRUE(intersect({f, box})); std::ostringstream os; os << i << "frust.ply"; Frustum::export_Ply(f, os.str()); } } // Test with truncated frustum { // Build frustum with near and far plane defined by min/max depth per camera for (int i=0; i < iNviews; ++i) { double minDepth = std::numeric_limits<double>::max(); double maxDepth = std::numeric_limits<double>::min(); for (int j=0; j < iNbPoints; ++j) { const double depth = Depth(d._R[i], d._t[i], d._X.col(j)); if (depth < minDepth) minDepth = depth; if (depth > maxDepth) maxDepth = depth; } const Frustum f(principal_Point*2, principal_Point*2, d._K[i], d._R[i], d._C[i], minDepth, maxDepth); EXPECT_TRUE(f.intersect(box)); EXPECT_TRUE(box.intersect(f)); EXPECT_TRUE(intersect({f, box})); } } }
// カメラの変換手順としては offset -> rotation だがPose3Dの変換は rotation -> offsetなので注意! Frustum Camera3D::getNearFrustum() const { Frustum fr; float t = std::tan(getFov().get()/2); fr.setScale({t*getAspect(), t, getNearZ()*8}); auto& ps = getPose(); fr.setRot(ps.getRot()); fr.setOffset(ps.getOffset()); return fr; }
Frustum Frustum::Transformed(const Matrix3x4& transform) const { Frustum transformed; for (unsigned i = 0; i < NUM_FRUSTUM_VERTICES; ++i) transformed.vertices_[i] = transform * vertices_[i]; transformed.UpdatePlanes(); return transformed; }
ActorSet Shadow::calculateReceivers(const ActorSet &zoneActors, const mat4& lightProjectionMatrix, const mat4& lightViewMatrix) { Frustum f; f.CalculateFrustum(lightViewMatrix, lightProjectionMatrix); const ActorSet s = zoneActors.isWithin(f); return s; }
Frustum Light::GetFrustum() const { // Note: frustum is unaffected by node or parent scale Matrix3x4 frustumTransform(node_ ? Matrix3x4(node_->GetWorldPosition(), node_->GetWorldRotation(), 1.0f) : Matrix3x4::IDENTITY); Frustum ret; ret.Define(fov_, aspectRatio_, 1.0f, M_MIN_NEARCLIP, range_, frustumTransform); return ret; }
void SceneManager::updateQueuesRec( const Frustum &frustum1, const Frustum *frustum2, bool sorted, SceneNode &node, bool lightQueue, bool renderableQueue ) { if( !node._active ) return; if( node._type == SceneNodeTypes::Group ) { // LOD Vec3f nodePos( node._absTrans.c[3][0], node._absTrans.c[3][1], node._absTrans.c[3][2] ); float dist = (nodePos - frustum1.getOrigin()).length(); GroupNode *gn = (GroupNode *)&node; if( dist < gn->_minDist || dist >= gn->_maxDist ) return; } else if( lightQueue && node._type == SceneNodeTypes::Light ) { _lightQueue.push_back( &node ); } else if( renderableQueue && node._renderable ) { if( node._type == SceneNodeTypes::Emitter ) { // Emitters are a special case since we have to use their local bounding box // If the emitter is transformed particle positions don't change if( !frustum1.cullBox( *node.getLocalBBox() ) && (frustum2 == 0x0 || !frustum2->cullBox( *node.getLocalBBox() )) ) { if( sorted ) { node.tmpSortValue = nearestDistToAABB( frustum1.getOrigin(), node.getLocalBBox()->getMinCoords(), node.getLocalBBox()->getMaxCoords() ); } _renderableQueue.push_back( &node ); } } else { if( !frustum1.cullBox( node._bBox ) && (frustum2 == 0x0 || !frustum2->cullBox( node._bBox )) ) { if( sorted ) { node.tmpSortValue = nearestDistToAABB( frustum1.getOrigin(), node._bBox.getMinCoords(), node._bBox.getMaxCoords() ); } _renderableQueue.push_back( &node ); } } } // Recurse over children for( uint32 i = 0, s = (uint32)node._children.size(); i < s; ++i ) { updateQueuesRec( frustum1, frustum2, sorted, *node._children[i], lightQueue, renderableQueue ); } }
Frustum transform(const Frustum &frustum, const Transform &tr) { Frustum out = frustum; for (int i = 0; i < 4; i++) { out.near[i] = transform(out.near[i], tr); out.far[i] = transform(out.far[i], tr); } out.update_planes(); return out; }
void CascadedShadowMap::buildShadowMaps(Camera *camera, View *view, DirectLight *light) { //Profiler::getInstance()->startProfile("Build Shadow Maps"); float nSlice[] = {0.0, m_nSlices[0], m_nSlices[1], m_nSlices[2], 1.0}; Frustum *frustum = new Frustum(); frustum->getFrustum(camera, view); m_shadowMaps[3]->bind(); glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); glDisable(GL_CULL_FACE); for (int i=0; i<4; i++) { Camera *lightCamera = createLightCamera(nSlice[i],nSlice[i+1],camera,view,light); View *lightView = createLightView(nSlice[i],nSlice[i+1],camera,lightCamera,view,frustum); Frustum *lightFrustum = new Frustum(); lightFrustum->getOrthoFrustum(lightCamera,lightView); MatrixManager::getInstance()->putMatrix4(MODELVIEW, glm::mat4(1.0f)); MatrixManager::getInstance()->putMatrix4(PROJECTION, glm::mat4(1.0f)); m_shadowMaps[i]->bind(); glClearDepth(1.0); glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT); glPushAttrib( GL_VIEWPORT_BIT ); glViewport( 0, 0, m_nSize, m_nSize); lightView->use3D(false); GLSLProgram *glslProgram = ShaderManager::getInstance()->getShader("DirectShadow"); glslProgram->use(); glm::mat4 cameraMat = glm::mat4(1.0f); cameraMat = lightCamera->transformToMatrix(cameraMat); m_m4LightMatrix[i] = MatrixManager::getInstance()->getMatrix4(PROJECTION) * cameraMat; MatrixManager::getInstance()->putMatrix4(MODELVIEW, cameraMat); glslProgram->sendUniform("projectionMatrix", &MatrixManager::getInstance()->getMatrix4(PROJECTION)[0][0]); glBindAttribLocation(glslProgram->getHandle(), 0, "v_vertex"); SceneManager::getInstance()->draw("DirectShadow"); glslProgram->disable(); glPopAttrib(); m_shadowMaps[i]->unbind(); delete lightCamera; delete lightView; delete lightFrustum; } glEnable(GL_CULL_FACE); //Profiler::getInstance()->endProfile(); }
void generate_frustum_split_spheres(Slice<Sphere> spheres_out, float fov, float aspect, float znear, float zfar, float ratio) { float prev_zfar = znear; for (int i = 0; i < spheres_out.length; i++) { const float split = calculate_split(znear, zfar, i+1, spheres_out.length, ratio); Frustum f = Frustum_Perspective(fov, aspect, prev_zfar, split); spheres_out[i] = f.bounding_sphere(); prev_zfar = split; } }
Frustum Camera::GetViewSpaceFrustum() const { Frustum ret; if (!orthographic_) ret.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_); else ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), farClip_); return ret; }
float ShadowManager::computeNearZForSceneIndependentBox(const Frustum<float> &splittedFrustumLightSpace) const { float nearestPointFromLight = splittedFrustumLightSpace.getFrustumPoints()[0].Z; for(unsigned int i=1; i<splittedFrustumLightSpace.getFrustumPoints().size(); ++i) { if(splittedFrustumLightSpace.getFrustumPoints()[i].Z > nearestPointFromLight) { nearestPointFromLight = splittedFrustumLightSpace.getFrustumPoints()[i].Z; } } return nearestPointFromLight + frustumDistance; }
bool MD2Model::render( const RenderContext &rc ){ static Frustum f; new( &f ) Frustum( rc.getWorldFrustum(),-getRenderTform() ); if( !f.cull( rep->getBox() ) ) return false; if( anim_mode & 0x8000 ){ rep->render( this,trans_verts,anim_time,trans_time ); }else{ rep->render( this,render_a,render_b,render_t ); } return false; }