vector3 BoundingBoxClass::GetMinAABB(void) { vector3 v3Minimum; std::vector<vector3> vVertices = m_pModelMngr->GetVertices(m_sInstance); int nVertices = static_cast<int>(vVertices.size()); if (nVertices > 0) { v3Minimum = LocalToWorld(vVertices[0], m_pModelMngr->GetModelMatrix(m_sInstance)); for (int nVertex = 1; nVertex < nVertices; nVertex++) { vector3 checking = LocalToWorld(vVertices[nVertex], m_pModelMngr->GetModelMatrix(m_sInstance)); if (checking.x < v3Minimum.x) v3Minimum.x = checking.x; if (checking.y < v3Minimum.y) v3Minimum.y = checking.y; if (checking.z < v3Minimum.z) v3Minimum.z = checking.z; } } return v3Minimum; }
Quat Placeable::WorldOrientation() const { float3 translate; Quat rotate; float3 scale; LocalToWorld().Decompose(translate, rotate, scale); return rotate; }
float3 Placeable::WorldScale() const { float3 translate; Quat rotate; float3 scale; LocalToWorld().Decompose(translate, rotate, scale); return scale; }
Spectrum BSDF::Sample_f(const Vector3f &woWorld, Vector3f *wiWorld, const Point2f &u, Float *pdf, BxDFType type, BxDFType *sampledType) const { ProfilePhase pp(Prof::BSDFEvaluation); // Choose which _BxDF_ to sample int matchingComps = NumComponents(type); if (matchingComps == 0) { *pdf = 0; if (sampledType) *sampledType = BxDFType(0); return Spectrum(0); } int comp = std::min((int)std::floor(u[0] * matchingComps), matchingComps - 1); // Get _BxDF_ pointer for chosen component BxDF *bxdf = nullptr; int count = comp; for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i]->MatchesFlags(type) && count-- == 0) { bxdf = bxdfs[i]; break; } Assert(bxdf); // Remap _BxDF_ sample _u_ to $[0,1)^2$ Point2f uRemapped(u[0] * matchingComps - comp, u[1]); // Sample chosen _BxDF_ Vector3f wi, wo = WorldToLocal(woWorld); *pdf = 0; if (sampledType) *sampledType = bxdf->type; Spectrum f = bxdf->Sample_f(wo, &wi, uRemapped, pdf, sampledType); if (*pdf == 0) { if (sampledType) *sampledType = BxDFType(0); return 0; } *wiWorld = LocalToWorld(wi); // Compute overall PDF with all matching _BxDF_s if (!(bxdf->type & BSDF_SPECULAR) && matchingComps > 1) for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i] != bxdf && bxdfs[i]->MatchesFlags(type)) *pdf += bxdfs[i]->Pdf(wo, wi); if (matchingComps > 1) *pdf /= matchingComps; // Compute value of BSDF for sampled direction if (!(bxdf->type & BSDF_SPECULAR) && matchingComps > 1) { bool reflect = Dot(*wiWorld, ng) * Dot(woWorld, ng) > 0; f = 0.; for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i]->MatchesFlags(type) && ((reflect && (bxdfs[i]->type & BSDF_REFLECTION)) || (!reflect && (bxdfs[i]->type & BSDF_TRANSMISSION)))) f += bxdfs[i]->f(wo, wi); } return f; }
void OBB::Triangulate(int x, int y, int z, vec *outPos, vec *outNormal, float2 *outUV, bool ccwIsFrontFacing) const { AABB aabb(POINT_VEC_SCALAR(0), r*2.f); aabb.Triangulate(x, y, z, outPos, outNormal, outUV, ccwIsFrontFacing); float3x4 localToWorld = LocalToWorld(); assume(localToWorld.HasUnitaryScale()); // Transforming of normals will fail otherwise. localToWorld.BatchTransformPos(outPos, NumVerticesInTriangulation(x,y,z), sizeof(vec)); localToWorld.BatchTransformDir(outNormal, NumVerticesInTriangulation(x,y,z), sizeof(vec)); }
float3x4 Placeable::WorldToLocal() const { float3x4 tm = LocalToWorld(); #ifndef MATH_SILENT_ASSUME bool success = #endif tm.Inverse(); #ifndef MATH_SILENT_ASSUME assume(success); #endif return tm; }
Spectrum BSDF::Sample_f(const Vector &woW, Vector *wiW, float u1, float u2, float u3, float *pdf, BxDFType flags, BxDFType *sampledType) const { // Choose which _BxDF_ to sample int matchingComps = NumComponents(flags); if (matchingComps == 0) { *pdf = 0.f; return Spectrum(0.f); } int which = min(Floor2Int(u3 * matchingComps), matchingComps-1); BxDF *bxdf = NULL; int count = which; for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i]->MatchesFlags(flags)) if (count-- == 0) { bxdf = bxdfs[i]; break; } Assert(bxdf); // NOBOOK // Sample chosen _BxDF_ Vector wi; Vector wo = WorldToLocal(woW); *pdf = 0.f; Spectrum f = bxdf->Sample_f(wo, &wi, u1, u2, pdf); if (*pdf == 0.f) return 0.f; if (sampledType) *sampledType = bxdf->type; *wiW = LocalToWorld(wi); // Compute overall PDF with all matching _BxDF_s if (!(bxdf->type & BSDF_SPECULAR) && matchingComps > 1) { for (int i = 0; i < nBxDFs; ++i) { if (bxdfs[i] != bxdf && bxdfs[i]->MatchesFlags(flags)) *pdf += bxdfs[i]->Pdf(wo, wi); } } if (matchingComps > 1) *pdf /= matchingComps; // Compute value of BSDF for sampled direction if (!(bxdf->type & BSDF_SPECULAR)) { f = 0.; if (Dot(*wiW, ng) * Dot(woW, ng) > 0) // ignore BTDFs flags = BxDFType(flags & ~BSDF_TRANSMISSION); else // ignore BRDFs flags = BxDFType(flags & ~BSDF_REFLECTION); for (int i = 0; i < nBxDFs; ++i) if (bxdfs[i]->MatchesFlags(flags)) f += bxdfs[i]->f(wo, wi); } return f; }
//Move the active image slice by the specified amount void WITVolumeViz::MoveActiveImage(int amount) { if(!_vol) return; uint dim[4]; _vol->getDimension(dim[0], dim[1], dim[2], dim[3]); DTIVoxel lPos = DTIVoxel(3); WorldToLocal(_vol->getTransformMatrix(), _vPos, dim, lPos); DTISceneActorID i = ActiveImage(); if(i >=0 && i < 3) { lPos[i] += amount; // see if the new position exceeds the dimensions // since both are unsigned, a value of -1 will be mapped to 0xfffffff which is greater than dim[i] if(lPos[i] >= dim[i]) lPos[i] = (amount > 0) ? dim[i]-1 : 0; Vector3d vPos; LocalToWorld(_vol->getTransformMatrix(), lPos, vPos.v); SetPosition(vPos); } }
void UParticleModuleVelocityCone::Render3DPreview(FParticleEmitterInstance* Owner, const FSceneView* View,FPrimitiveDrawInterface* PDI) { #if WITH_EDITOR float ConeMaxAngle = 0.0f; float ConeMinAngle = 0.0f; Angle.GetOutRange(ConeMinAngle, ConeMaxAngle); float ConeMaxVelocity = 0.0f; float ConeMinVelocity = 0.0f; Velocity.GetOutRange(ConeMinVelocity, ConeMaxVelocity); float MaxLifetime = 0.0f; TArray<UParticleModule*>& Modules = Owner->SpriteTemplate->GetCurrentLODLevel(Owner)->Modules; for (int32 ModuleIndex = 0; ModuleIndex < Modules.Num(); ModuleIndex++) { UParticleModuleLifetimeBase* LifetimeMod = Cast<UParticleModuleLifetimeBase>(Modules[ModuleIndex]); if (LifetimeMod != NULL) { MaxLifetime = LifetimeMod->GetMaxLifetime(); break; } } const int32 ConeSides = 16; const float ConeRadius = ConeMaxVelocity * MaxLifetime; // Calculate direction transform const FVector DefaultDirection(0.0f, 0.0f, 1.0f); const FVector ForwardDirection = (Direction != FVector::ZeroVector)? Direction.GetSafeNormal(): DefaultDirection; FVector UpDirection(0.0f, 0.0f, 1.0f); FVector RightDirection(1.0f, 0.0f, 0.0f); if ((ForwardDirection != UpDirection) && (-ForwardDirection != UpDirection)) { RightDirection = UpDirection ^ ForwardDirection; UpDirection = ForwardDirection ^ RightDirection; } else { UpDirection = ForwardDirection ^ RightDirection; RightDirection = UpDirection ^ ForwardDirection; } FMatrix DirectionRotation; DirectionRotation.SetIdentity(); DirectionRotation.SetAxis(0, RightDirection.GetSafeNormal()); DirectionRotation.SetAxis(1, UpDirection.GetSafeNormal()); DirectionRotation.SetAxis(2, ForwardDirection); // Calculate the owning actor's scale and rotation UParticleLODLevel* LODLevel = Owner->SpriteTemplate->GetCurrentLODLevel(Owner); check(LODLevel); FVector OwnerScale(1.0f); FMatrix OwnerRotation(FMatrix::Identity); FVector LocalToWorldOrigin(0.0f); FMatrix LocalToWorld(FMatrix::Identity); if (Owner->Component) { AActor* Actor = Owner->Component->GetOwner(); if (Actor) { if (bApplyOwnerScale == true) { OwnerScale = Owner->Component->ComponentToWorld.GetScale3D(); } OwnerRotation = FQuatRotationMatrix(Actor->GetActorQuat()); } LocalToWorldOrigin = Owner->Component->ComponentToWorld.GetLocation(); LocalToWorld = Owner->Component->ComponentToWorld.ToMatrixWithScale().RemoveTranslation(); LocalToWorld.RemoveScaling(); } FMatrix Transform; Transform.SetIdentity(); // DrawWireCone() draws a cone down the X axis, but this cone's default direction is down Z const FRotationMatrix XToZRotation(FRotator((int32)(HALF_PI * 10430), 0, 0)); Transform *= XToZRotation; // Apply scale Transform.SetAxis(0, Transform.GetScaledAxis( EAxis::X ) * OwnerScale.X); Transform.SetAxis(1, Transform.GetScaledAxis( EAxis::Y ) * OwnerScale.Y); Transform.SetAxis(2, Transform.GetScaledAxis( EAxis::Z ) * OwnerScale.Z); // Apply direction transform Transform *= DirectionRotation; // Transform according to world and local space flags if (!LODLevel->RequiredModule->bUseLocalSpace && !bInWorldSpace) { Transform *= LocalToWorld; } else if (LODLevel->RequiredModule->bUseLocalSpace && bInWorldSpace) { Transform *= OwnerRotation; Transform *= LocalToWorld.InverseFast(); } else if (!bInWorldSpace) { Transform *= OwnerRotation; } // Apply translation Transform.SetOrigin(LocalToWorldOrigin); TArray<FVector> OuterVerts; TArray<FVector> InnerVerts; // Draw inner and outer cones DrawWireCone(PDI, InnerVerts, Transform, ConeRadius, ConeMinAngle, ConeSides, ModuleEditorColor, SDPG_World); DrawWireCone(PDI, OuterVerts, Transform, ConeRadius, ConeMaxAngle, ConeSides, ModuleEditorColor, SDPG_World); // Draw radial spokes for (int32 i = 0; i < ConeSides; ++i) { PDI->DrawLine( OuterVerts[i], InnerVerts[i], ModuleEditorColor, SDPG_World ); } #endif }
float3x4 OBB::WorldToLocal() const { float3x4 m = LocalToWorld(); m.InverseOrthogonal(); return m; }
RGB BSDF::Sample_f(const Vector &woWorld, Vector *wiWorld, const BSDFSample &bsdfSample, float *pdf, BxDFType flags, BxDFType *sampledType) const { int numComp = NumComponents(flags); if (numComp == 0) { *pdf = 0; if (sampledType) *sampledType = BxDFType(0); return 0; } int whichComp = min(Floor2Int(bsdfSample.uComponent * numComp), numComp - 1); int count = whichComp; BxDF *bxdf = nullptr; //被选中的Bxdf for (int i = 0; i < mNumBxdf; ++i) { if (mBxdfs[i]->MatchesFlag(flags) && count-- == 0) { //这技巧 GOOD bxdf = mBxdfs[i]; break; } } Vector wo = WorldToLocal(woWorld); //获得局部坐标下的wo Vector wi; *pdf = 0.f; RGB f = bxdf->Sample_f(wo, &wi, bsdfSample.uDir[0], bsdfSample.uDir[1], pdf); //这里的主要作用是采样出射方向 if (*pdf == 0) { if (sampledType) *sampledType = BxDFType(0); return 0; } if (sampledType) *sampledType = bxdf->type; *wiWorld = LocalToWorld(wi); //获得世界坐标系下的wi //计算pdf if (!(bxdf->type & BSDF_SPECULAR) && numComp > 1) { for (int i = 0; i < mNumBxdf; ++i) { if (bxdf != mBxdfs[i] && mBxdfs[i]->MatchesFlag(flags)) { *pdf += mBxdfs[i]->Pdf(wo, wi); } } } if (numComp > 1) { *pdf /= numComp; } //开始计算BRDF系数 if (!(bxdf->type & BSDF_SPECULAR)) { f=0;//因为不是镜面反射 所以重新计算BRDF if (Dot(*wiWorld, mNG) * Dot(woWorld, mNG) > 0) //反射 flags = BxDFType(flags & ~BSDF_TRANSMISSION); else//折射 flags = BxDFType(flags & ~BSDF_REFLECTION); for (int i = 0; i < mNumBxdf; ++i) if (mBxdfs[i]->MatchesFlag(flags)) f += mBxdfs[i]->f(wo, wi); } return f; }
void WITVolumeViz::LocalToWorld(double *mat, DTIVoxel &lPos, double *wPos) { double localPos[4]= {lPos[0], lPos[1], lPos[2], 1}; LocalToWorld(mat, localPos, wPos); }
CControl::EHitTestResult CControl::GetHitResult( float x, float y ) { EHitTestResult result = eHTR_HIT_NONE; if( HitTest( x, y )) { CVec3 realPosition = GetPosition(); LocalToWorld( realPosition.x, realPosition.y ); static const float DEVIATION = 7.f; float toLeft = x - m_quadp.tl.x; float toRight = m_quadp.tl.x + m_vecRealSize.x - x; float toTop = y - m_quadp.tl.y; float toBottom = m_vecRealSize.y + m_quadp.tl.y - y; if(toLeft <= DEVIATION) { if(toTop <= DEVIATION) { result = EHitTestResult::eHTR_HIT_TOP_LEFT; } else if(toBottom <= DEVIATION) { result = eHTR_HIT_BOTTOM_LEFT; } else if(abs(toBottom - toTop) <= DEVIATION*2) { result = eHTR_HIT_LEFT_CENTER; } } else if(toRight <= DEVIATION) { if(toTop <= DEVIATION) { result = eHTR_HIT_TOP_RIGHT; } else if(toBottom <= DEVIATION) { result = eHTR_HIT_BOTTOM_RIGHT; } else if(abs(toBottom - toTop) <= DEVIATION*2) { result = eHTR_HIT_RIGHT_CENTER; } } else if(toTop <= DEVIATION) { if(abs(toRight - toLeft) <= DEVIATION*2) { result = eHTR_HIT_TOP_CENTER; } } else if(toBottom <= DEVIATION) { if(abs(toRight - toLeft) <= DEVIATION*2) { result = eHTR_HIT_BOTTOM_CENTER; } } else if(abs(toLeft - realPosition.x) <= DEVIATION*2 && abs(toTop - realPosition.y) <= DEVIATION*2) { result = eHTR_HIT_ANCHOR; } if(result == eHTR_HIT_CONTENT) { if (toLeft <= DEVIATION || toRight <= DEVIATION || toTop <= DEVIATION || toBottom <= DEVIATION) { result = eHTR_HIT_EDGE; } } } return result; }
/// worldspace position of the center of the wheel when the suspension is compressed /// by the displacement_percent where 1.0 is fully compressed MATHVECTOR<Dbl,3> CARDYNAMICS::GetWheelPositionAtDisplacement(WHEEL_POSITION wp, Dbl displacement_percent) const { return LocalToWorld(GetLocalWheelPosition(wp, displacement_percent)); }
void FPaperTileMapRenderSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const { QUICK_SCOPE_CYCLE_COUNTER(STAT_FPaperTileMapRenderSceneProxy_GetDynamicMeshElements); checkSlow(IsInRenderingThread()); // Slight depth bias so that the wireframe grid overlay doesn't z-fight with the tiles themselves const float DepthBias = 0.0001f; for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); // Draw the tile maps //@TODO: RenderThread race condition if (TileMap != nullptr) { FColor WireframeColor = FColor(0, 255, 255, 255); if ((View->Family->EngineShowFlags.Collision /*@TODO: && bIsCollisionEnabled*/) && AllowDebugViewmodes()) { if (UBodySetup2D* BodySetup2D = Cast<UBodySetup2D>(TileMap->BodySetup)) { //@TODO: Draw 2D debugging geometry } else if (UBodySetup* BodySetup = TileMap->BodySetup) { if (FMath::Abs(GetLocalToWorld().Determinant()) < SMALL_NUMBER) { // Catch this here or otherwise GeomTransform below will assert // This spams so commented out //UE_LOG(LogStaticMesh, Log, TEXT("Zero scaling not supported (%s)"), *StaticMesh->GetPathName()); } else { // Make a material for drawing solid collision stuff const UMaterial* LevelColorationMaterial = View->Family->EngineShowFlags.Lighting ? GEngine->ShadedLevelColorationLitMaterial : GEngine->ShadedLevelColorationUnlitMaterial; auto CollisionMaterialInstance = new FColoredMaterialRenderProxy( LevelColorationMaterial->GetRenderProxy(IsSelected(), IsHovered()), WireframeColor ); // Draw the static mesh's body setup. // Get transform without scaling. FTransform GeomTransform(GetLocalToWorld()); // In old wireframe collision mode, always draw the wireframe highlighted (selected or not). bool bDrawWireSelected = IsSelected(); if (View->Family->EngineShowFlags.Collision) { bDrawWireSelected = true; } // Differentiate the color based on bBlockNonZeroExtent. Helps greatly with skimming a level for optimization opportunities. FColor CollisionColor = FColor(157, 149, 223, 255); const bool bPerHullColor = false; const bool bDrawSimpleSolid = false; BodySetup->AggGeom.GetAggGeom(GeomTransform, GetSelectionColor(CollisionColor, bDrawWireSelected, IsHovered()), CollisionMaterialInstance, bPerHullColor, bDrawSimpleSolid, UseEditorDepthTest(), ViewIndex, Collector); } } } // Draw the bounds RenderBounds(PDI, View->Family->EngineShowFlags, GetBounds(), IsSelected()); #if WITH_EDITOR // Draw the debug outline if (View->Family->EngineShowFlags.Grid) { const uint8 DPG = SDPG_Foreground;//GetDepthPriorityGroup(View); // Draw separation wires if selected FLinearColor OverrideColor; bool bUseOverrideColor = false; const bool bShowAsSelected = !(GIsEditor && View->Family->EngineShowFlags.Selection) || IsSelected(); if (bShowAsSelected || IsHovered()) { bUseOverrideColor = true; OverrideColor = GetSelectionColor(FLinearColor::White, bShowAsSelected, IsHovered()); } FTransform LocalToWorld(GetLocalToWorld()); if (bUseOverrideColor) { const int32 SelectedLayerIndex = TileMap->SelectedLayerIndex; // Draw a bound for any invisible layers for (int32 LayerIndex = 0; LayerIndex < TileMap->TileLayers.Num(); ++LayerIndex) { if (LayerIndex != SelectedLayerIndex) { const FVector TL(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(0, 0, LayerIndex))); const FVector TR(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(TileMap->MapWidth, 0, LayerIndex))); const FVector BL(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(0, TileMap->MapHeight, LayerIndex))); const FVector BR(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(TileMap->MapWidth, TileMap->MapHeight, LayerIndex))); PDI->DrawLine(TL, TR, OverrideColor, DPG, 0.0f, DepthBias); PDI->DrawLine(TR, BR, OverrideColor, DPG, 0.0f, DepthBias); PDI->DrawLine(BR, BL, OverrideColor, DPG, 0.0f, DepthBias); PDI->DrawLine(BL, TL, OverrideColor, DPG, 0.0f, DepthBias); } } if (SelectedLayerIndex != INDEX_NONE) { // Draw horizontal lines on the selection for (int32 Y = 0; Y <= TileMap->MapHeight; ++Y) { int32 X = 0; const FVector Start(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex)); X = TileMap->MapWidth; const FVector End(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex)); PDI->DrawLine(LocalToWorld.TransformPosition(Start), LocalToWorld.TransformPosition(End), OverrideColor, DPG, 0.0f, DepthBias); } // Draw vertical lines for (int32 X = 0; X <= TileMap->MapWidth; ++X) { int32 Y = 0; const FVector Start(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex)); Y = TileMap->MapHeight; const FVector End(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex)); PDI->DrawLine(LocalToWorld.TransformPosition(Start), LocalToWorld.TransformPosition(End), OverrideColor, DPG, 0.0f, DepthBias); } } } } #endif } } } // Draw all of the queued up sprites FPaperRenderSceneProxy::GetDynamicMeshElements(Views, ViewFamily, VisibilityMap, Collector); }
//Set the vtk volume for display void WITVolumeViz::SetVolume(DTIScalarVolume *vol, float left, float right) { //Volume is being set for the first time so display the border const DTIScalarVolume* oldVol = _vol; _vol = vol; // use the brightness and contrast by using the left and right variables _lutBW->SetTableRange (left, right); double window = right - left; double level = left + window/2.0; // adjust the range _lutBW->SetWindow(window); // adjust the midpoint _lutBW->SetLevel(level); _lutBW->Modified(); this->updateActors(); uint dim[4]; double voxSize[3]; _vol->getDimension(dim[0], dim[1], dim[2], dim[3]); _vol->getVoxelSize(voxSize[0], voxSize[1], voxSize[2]); if (oldVol == NULL) { // Start in center of volume double localPos[4]= {dim[0]/2, dim[1]/2, dim[2]/2, 1}; LocalToWorld(_vol->getTransformMatrix(), localPos, _vPos); } _img->Modified(); if (dim[3] == 1) // more common case { // copy the background image data to a cache(_img) float *dataPtr = _vol->getDataPointer(); float *destinationPtr = static_cast<float *>(_img->GetScalarPointer()); memcpy (destinationPtr, dataPtr, dim[0]*dim[1]*dim[2]*dim[3]*sizeof(float)); } else { for(uint k=0; k<dim[2]; k++) { for(uint j=0; j<dim[1]; j++) { for(uint i=0; i<dim[0]; i++) { for (uint c = 0; c<dim[3]; c++) { float f = _vol->getScalar(i,j,k,c)*255; _img->SetScalarComponentFromFloat (i,j,k,c,f); } } } } } SetPosition(_vPos); // check to see if this is the very first image that has been loaded. // if so set the camera to a default position and orientation if(_nActiveImage == -1) { DTISceneActorID n = DTI_ACTOR_CORONAL_TOMO; SetActiveImage(n); for(std::map<vtkRenderWindow*, ActorSet*>::iterator it = this->windowToActorSet.begin(); it != this->windowToActorSet.end(); it++) { vtkRenderWindow *win = it->first; vtkRendererCollection *rends = win->GetRenderers(); rends->InitTraversal(); while(vtkRenderer *rend = rends->GetNextItem()) { this->SetCameraToDefault(rend); } } } }
float3 Placeable::WorldPosition() const { return LocalToWorld().TranslatePart(); }