/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_SceneBuilder.cpp Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. The content herein is highly confidential and should be handled accordingly. $Revision: $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace nw { namespace gfx { //---------------------------------------- SceneObject* SceneBuilder::CreateObject( os::IAllocator* allocator, os::IAllocator* deviceAllocator ) { NW_NULL_ASSERT(allocator); NW_ASSERT(m_Resource.IsValid()); // 子階層はたどらずに、このリソースのみを生成します。 SceneObject* root = BuildSceneObject(NULL, NULL, 0, m_Resource, allocator, deviceAllocator, false, false); return root; } //---------------------------------------- SceneObject* SceneBuilder::CreateTree( os::IAllocator* allocator, os::IAllocator* deviceAllocator ) { NW_NULL_ASSERT(allocator); NW_ASSERT(m_Resource.IsValid()); // 子階層を辿って生成します。 SceneObject* root = BuildSceneObject(NULL, NULL, 0, m_Resource, allocator, deviceAllocator, true, false); return root; } //---------------------------------------- SceneObject* SceneBuilder::BuildSceneObject( os::MemorySizeCalculator* pSize, os::MemorySizeCalculator* pDeviceSize, SceneNode* parent, ResSceneObject resource, os::IAllocator* allocator, os::IAllocator* deviceAllocator, bool isRecursive, bool isCalculation ) const { NW_ASSERT( allocator != NULL || isCalculation ); if (!resource.IsValid()) { return 0; } SceneObject* object = 0; switch (resource.GetTypeInfo()) { case ResSceneNode::TYPE_INFO: { SceneNode::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { SceneNode::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { SceneNode::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { SceneNode* node = SceneNode::Create( parent, resource, description, allocator); object = node; } } break; case ResTransformNode::TYPE_INFO: { TransformNode::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { TransformNode::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { TransformNode::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { TransformNode* node = TransformNode::Create( parent, resource, description, allocator); object = node; } } break; case ResModel::TYPE_INFO: { Model::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.bufferOption = m_BufferOption; description.sharedMaterialModel = m_SharedMaterialModel; description.isAnimationEnabled = m_IsAnimationEnabled; description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup; if (isCalculation) { if (pSize) { Model::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { Model::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { Model* node = Model::Create( parent, resource, description, allocator); object = node; } } break; case ResSkeletalModel::TYPE_INFO: { SkeletalModel::Builder builder; builder .IsFixedSizeMemory(m_IsFixedSizeMemory) .MaxCallbacks(m_MaxCallbacks) .MaxChildren(m_MaxChildren) .BufferOption(m_BufferOption) .SharedMaterialModel(m_SharedMaterialModel) .MaxAnimObjectsPerGroup(m_MaxAnimObjectsPerGroup) .IsAnimationEnabled(m_IsAnimationEnabled); if (isCalculation) { if (pSize) { builder.GetMemorySizeInternal(pSize, ResStaticCast(resource)); } if (pDeviceSize) { builder.GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource)); } } else { SkeletalModel* node = builder.Create(parent, resource, allocator); object = node; } } break; case ResParticleModel::TYPE_INFO: { ResParticleModel resNode = ResDynamicCast(resource); NW_ASSERT(resNode.IsValid()); ParticleModel::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.bufferOption = m_BufferOption; description.sharedMaterialModel = m_SharedMaterialModel; description.maxChildren = resNode.GetChildrenCount() + resNode.GetParticleSetsCount() + m_ParticleSetMarginCount; description.particleSetCount = resNode.GetParticleSetsCount() + m_ParticleSetMarginCount; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { ParticleModel::GetMemorySizeInternal(pSize, resNode, description); } if (pDeviceSize) { ParticleModel::GetDeviceMemorySizeInternal(pDeviceSize, resNode, description); } } else { ParticleModel* node = ParticleModel::Create( parent, resource, description, allocator, deviceAllocator); object = node; } } break; case ResParticleEmitter::TYPE_INFO: { ParticleEmitter::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { ParticleEmitter::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { ParticleEmitter::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { ParticleEmitter* node = ParticleEmitter::Create( parent, resource, description, allocator); object = node; } } break; case ResFragmentLight::TYPE_INFO: { FragmentLight::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { FragmentLight::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { FragmentLight::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { FragmentLight* node = FragmentLight::Create( parent, resource, description, allocator); object = node; } } break; #if defined(NW_GFX_VERTEX_LIGHT_ENABLED) case ResVertexLight::TYPE_INFO: { VertexLight::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { VertexLight::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { VertexLight::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { VertexLight* node = VertexLight::Create( parent, resource, description, allocator); object = node; } } break; #endif case ResAmbientLight::TYPE_INFO: { AmbientLight::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { AmbientLight::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { AmbientLight::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { AmbientLight* node = AmbientLight::Create( parent, resource, description, allocator); object = node; } } break; case ResHemiSphereLight::TYPE_INFO: { HemiSphereLight::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { HemiSphereLight::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { HemiSphereLight::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { HemiSphereLight* node = HemiSphereLight::Create( parent, resource, description, allocator); object = node; } } break; case ResFog::TYPE_INFO: { Fog::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { Fog::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { Fog::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { Fog* node = Fog::Create( parent, resource, description, allocator); object = node; } } break; case ResCamera::TYPE_INFO: { Camera::Description description; description.isFixedSizeMemory = m_IsFixedSizeMemory; description.maxCallbacks = m_MaxCallbacks; description.maxChildren = m_MaxChildren; description.maxAnimObjectsPerGroup = m_MaxAnimObjectsPerGroup; description.isAnimationEnabled = m_IsAnimationEnabled; if (isCalculation) { if (pSize) { Camera::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { Camera::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { Camera* node = Camera::Create( parent, resource, description, allocator); object = node; } } break; case ResSceneEnvironmentSetting::TYPE_INFO: { SceneEnvironmentSetting::Description description; if (isCalculation) { if (pSize) { SceneEnvironmentSetting::GetMemorySizeInternal(pSize, ResStaticCast(resource), description); } if (pDeviceSize) { //SceneEnvironmentSetting::GetDeviceMemorySizeInternal(pDeviceSize, ResStaticCast(resource), description); } } else { SceneEnvironmentSetting* node = SceneEnvironmentSetting::Create( resource, description, allocator); object = node; } } break; default: NW_FATAL_ERROR("Unknown resource type."); break; } if (isCalculation) { // 子階層のメモリサイズを求める if (isRecursive) { BuildChildren(pSize, pDeviceSize, NULL, resource, NULL, NULL, true); } } else { SceneNode* sceneNode = ut::DynamicCast(object); // 子階層を初期化するなら、子をたどる if (sceneNode != NULL && isRecursive) { BuildChildren(NULL, NULL, sceneNode, resource, allocator, deviceAllocator, false); } } return object; } //---------------------------------------- void SceneBuilder::BuildChildren( os::MemorySizeCalculator* pSize, os::MemorySizeCalculator* pDeviceSize, SceneNode* parent, ResSceneObject resource, os::IAllocator* allocator, os::IAllocator* deviceAllocator, bool isCalculation ) const { NW_NULL_ASSERT(allocator); ResSceneNode resNode = ResSceneNode(resource.ptr()); if (!resource.IsValid()) { return; } typedef nw::ut::ResArrayClass::type ResSceneObjectArray; for (ResSceneObjectArray::iterator i = resNode.GetChildren().begin(); i != resNode.GetChildren().end(); ++i) { if (isCalculation) { BuildSceneObject(pSize, pDeviceSize, NULL, resource, NULL, NULL, true, true); } else { // 子階層をたどるときは、デフォルトで再帰的に生成を行う SceneObject* child = BuildSceneObject(NULL, NULL, parent, *i, allocator, deviceAllocator, true, false); } } } } // namespace gfx } // namespace nw