Exposed StaticModelGroup to script. Ported HugeObjectCount example group mode switching to script versions.

This commit is contained in:
Lasse Öörni 2013-09-19 22:44:06 +00:00
Родитель 6e58119be9
Коммит 1cd73e46fd
13 изменённых файлов: 246 добавлений и 47 удалений

Просмотреть файл

@ -95,7 +95,7 @@ function CreateInstructions()
-- Position the text relative to the screen center -- Position the text relative to the screen center
instructionText.horizontalAlignment = HA_CENTER instructionText.horizontalAlignment = HA_CENTER
instructionText.verticalAlignment= VA_CENTER instructionText.verticalAlignment = VA_CENTER
instructionText:SetPosition(0, ui.root.height / 4) instructionText:SetPosition(0, ui.root.height / 4)
end end

Просмотреть файл

@ -94,7 +94,7 @@ function CreateInstructions()
-- Position the text relative to the screen center -- Position the text relative to the screen center
instructionText.horizontalAlignment = HA_CENTER instructionText.horizontalAlignment = HA_CENTER
instructionText.verticalAlignment= VA_CENTER instructionText.verticalAlignment = VA_CENTER
instructionText:SetPosition(0, ui.root.height / 4) instructionText:SetPosition(0, ui.root.height / 4)
end end

Просмотреть файл

@ -3,6 +3,7 @@
-- - Creating a scene with 250 x 250 simple objects; -- - Creating a scene with 250 x 250 simple objects;
-- - Competing with http://yosoygames.com.ar/wp/2013/07/ogre-2-0-is-up-to-3x-faster/ :); -- - Competing with http://yosoygames.com.ar/wp/2013/07/ogre-2-0-is-up-to-3x-faster/ :);
-- - Allowing examination of performance hotspots in the rendering code; -- - Allowing examination of performance hotspots in the rendering code;
-- - Optionally speeding up rendering by grouping the objects using StaticModelGroup component;
require "LuaScripts/Utilities/Sample" require "LuaScripts/Utilities/Sample"
@ -12,6 +13,7 @@ local boxNodes = {}
local yaw = 0.0 local yaw = 0.0
local pitch = 0.0 local pitch = 0.0
local animate = false local animate = false
local useGroups = false
local context = GetContext() local context = GetContext()
@ -38,7 +40,12 @@ function Start()
end end
function CreateScene() function CreateScene()
scene_ = Scene(context) if scene_ == nil then
scene_ = Scene(context)
else
scene_:Clear()
boxNodes = {}
end
-- Create the Octree component to the scene so that drawable objects can be rendered. Use default volume -- Create the Octree component to the scene so that drawable objects can be rendered. Use default volume
-- (-1000, -1000, -1000) to (1000, 1000, 1000) -- (-1000, -1000, -1000) to (1000, 1000, 1000)
@ -54,42 +61,74 @@ function CreateScene()
-- Create a directional light -- Create a directional light
local lightNode = scene_:CreateChild("DirectionalLight") local lightNode = scene_:CreateChild("DirectionalLight")
lightNode.direction = Vector3(0.5, -1.0, 0.5) -- The direction vector does not need to be normalized lightNode.direction = Vector3(-0.6, -1.0, -0.8) -- The direction vector does not need to be normalized
local light = lightNode:CreateComponent("Light") local light = lightNode:CreateComponent("Light")
light.lightType = LIGHT_DIRECTIONAL light.lightType = LIGHT_DIRECTIONAL
light.color = Color(0.7, 0.35, 0.0)
-- Create box StaticModels in the scene
for y = -125, 125 do if not useGroups then
for x = -125, 125 do light.color = Color(0.7, 0.35, 0.0)
local boxNode = scene_:CreateChild("Box")
boxNode.position = Vector3(x * 0.3, 0.0, y * 0.3) -- Create individual box StaticModels in the scene
boxNode:SetScale(0.25) for y = -125, 125 do
local boxObject = boxNode:CreateComponent("StaticModel") for x = -125, 125 do
boxObject.model = cache:GetResource("Model", "Models/Box.mdl") local boxNode = scene_:CreateChild("Box")
table.insert(boxNodes, boxNode) boxNode.position = Vector3(x * 0.3, 0.0, y * 0.3)
boxNode:SetScale(0.25)
local boxObject = boxNode:CreateComponent("StaticModel")
boxObject.model = cache:GetResource("Model", "Models/Box.mdl")
table.insert(boxNodes, boxNode)
end
end
else
light.color = Color(0.6, 0.6, 0.6);
light.specularIntensity = 1.5;
-- Create StaticModelGroups in the scene
local lastGroup = nil
for y = -125, 125 do
for x = -125, 125 do
-- Create new group if no group yet, or the group has already "enough" objects. The tradeoff is between culling
-- accuracy and the amount of CPU processing needed for all the objects. Note that the group's own transform
-- does not matter, and it does not render anything if instance nodes are not added to it
if lastGroup == nil or lastGroup.numInstanceNodes >= 25 * 25 then
local boxGroupNode = scene_:CreateChild("BoxGroup")
lastGroup = boxGroupNode:CreateComponent("StaticModelGroup")
lastGroup.model = cache:GetResource("Model", "Models/Box.mdl")
end
local boxNode = scene_:CreateChild("Box");
boxNode.position = Vector3(x * 0.3, 0.0, y * 0.3)
boxNode:SetScale(0.25)
table.insert(boxNodes, boxNode)
lastGroup:AddInstanceNode(boxNode);
end
end end
end end
-- Create the camera -- Create the camera. Create it outside the scene so that we can clear the whole scene without affecting it
cameraNode = scene_:CreateChild("Camera") if cameraNode == nil then
cameraNode.position = Vector3(0.0, 10.0, -100.0) cameraNode = Node(context)
local camera = cameraNode:CreateComponent("Camera") cameraNode.position = Vector3(0.0, 10.0, -100.0)
camera.farClip = 300.0 local camera = cameraNode:CreateComponent("Camera")
camera.farClip = 300.0
end
end end
function CreateInstructions() function CreateInstructions()
-- Construct new Text object, set string to display and font to use -- Construct new Text object, set string to display and font to use
local instructionText = ui.root:CreateChild("Text") local instructionText = ui.root:CreateChild("Text")
instructionText:SetText("Use WASD keys and mouse to move\n".. instructionText:SetText("Use WASD keys and mouse to move\n"..
"Space to toggle animation") "Space to toggle animation\n"..
"G to toggle object group optimization")
instructionText:SetFont(cache:GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15) instructionText:SetFont(cache:GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15)
-- The text has multiple rows. Center them in relation to each other -- The text has multiple rows. Center them in relation to each other
instructionText.textAlignment = HA_CENTER instructionText.textAlignment = HA_CENTER
-- Position the text relative to the screen center -- Position the text relative to the screen center
instructionText.horizontalAlignment = HA_CENTER instructionText.horizontalAlignment = HA_CENTER
instructionText.verticalAlignment= VA_CENTER instructionText.verticalAlignment = VA_CENTER
instructionText:SetPosition(0, ui.root.height / 4) instructionText:SetPosition(0, ui.root.height / 4)
end end
@ -157,6 +196,12 @@ function HandleUpdate(eventType, eventData)
animate = not animate animate = not animate
end end
-- Toggle grouped / ungrouped mode
if input:GetKeyPress(KEY_G) then
useGroups = not useGroups
CreateScene()
end
-- Move the camera, scale movement with time step -- Move the camera, scale movement with time step
MoveCamera(timeStep) MoveCamera(timeStep)

Просмотреть файл

@ -92,7 +92,7 @@ void CreateInstructions()
// Position the text relative to the screen center // Position the text relative to the screen center
instructionText.horizontalAlignment = HA_CENTER; instructionText.horizontalAlignment = HA_CENTER;
instructionText.verticalAlignment= VA_CENTER; instructionText.verticalAlignment = VA_CENTER;
instructionText.SetPosition(0, ui.root.height / 4); instructionText.SetPosition(0, ui.root.height / 4);
} }

Просмотреть файл

@ -94,7 +94,7 @@ void CreateInstructions()
// Position the text relative to the screen center // Position the text relative to the screen center
instructionText.horizontalAlignment = HA_CENTER; instructionText.horizontalAlignment = HA_CENTER;
instructionText.verticalAlignment= VA_CENTER; instructionText.verticalAlignment = VA_CENTER;
instructionText.SetPosition(0, ui.root.height / 4); instructionText.SetPosition(0, ui.root.height / 4);
} }

Просмотреть файл

@ -3,6 +3,7 @@
// - Creating a scene with 250 x 250 simple objects; // - Creating a scene with 250 x 250 simple objects;
// - Competing with http://yosoygames.com.ar/wp/2013/07/ogre-2-0-is-up-to-3x-faster/ :) // - Competing with http://yosoygames.com.ar/wp/2013/07/ogre-2-0-is-up-to-3x-faster/ :)
// - Allowing examination of performance hotspots in the rendering code; // - Allowing examination of performance hotspots in the rendering code;
// - Optionally speeding up rendering by grouping the objects using StaticModelGroup component;
#include "Scripts/Utilities/Sample.as" #include "Scripts/Utilities/Sample.as"
@ -12,6 +13,7 @@ Array<Node@> boxNodes;
float yaw = 0.0f; float yaw = 0.0f;
float pitch = 0.0f; float pitch = 0.0f;
bool animate = false; bool animate = false;
bool useGroups = false;
void Start() void Start()
{ {
@ -33,7 +35,13 @@ void Start()
void CreateScene() void CreateScene()
{ {
scene_ = Scene(); if (scene_ is null)
scene_ = Scene();
else
{
scene_.Clear();
boxNodes.Clear();
}
// Create the Octree component to the scene so that drawable objects can be rendered. Use default volume // Create the Octree component to the scene so that drawable objects can be rendered. Use default volume
// (-1000, -1000, -1000) to (1000, 1000, 1000) // (-1000, -1000, -1000) to (1000, 1000, 1000)
@ -46,49 +54,87 @@ void CreateScene()
zone.fogColor = Color(0.2f, 0.2f, 0.2f); zone.fogColor = Color(0.2f, 0.2f, 0.2f);
zone.fogStart = 200.0f; zone.fogStart = 200.0f;
zone.fogEnd = 300.0f; zone.fogEnd = 300.0f;
// Create a directional light // Create a directional light
Node@ lightNode = scene_.CreateChild("DirectionalLight"); Node@ lightNode = scene_.CreateChild("DirectionalLight");
lightNode.direction = Vector3(0.5f, -1.0f, 0.5f); // The direction vector does not need to be normalized lightNode.direction = Vector3(-0.6f, -1.0f, -0.8f); // The direction vector does not need to be normalized
Light@ light = lightNode.CreateComponent("Light"); Light@ light = lightNode.CreateComponent("Light");
light.lightType = LIGHT_DIRECTIONAL; light.lightType = LIGHT_DIRECTIONAL;
light.color = Color(0.7f, 0.35f, 0.0f);
// Create box StaticModels in the scene if (!useGroups)
for (int y = -125; y < 125; ++y)
{ {
for (int x = -125; x < 125; ++x) light.color = Color(0.7f, 0.35f, 0.0f);
// Create individual box StaticModels in the scene
for (int y = -125; y < 125; ++y)
{ {
Node@ boxNode = scene_.CreateChild("Box"); for (int x = -125; x < 125; ++x)
boxNode.position = Vector3(x * 0.3f, 0.0f, y * 0.3f); {
boxNode.SetScale(0.25f); Node@ boxNode = scene_.CreateChild("Box");
StaticModel@ boxObject = boxNode.CreateComponent("StaticModel"); boxNode.position = Vector3(x * 0.3f, 0.0f, y * 0.3f);
boxObject.model = cache.GetResource("Model", "Models/Box.mdl"); boxNode.SetScale(0.25f);
boxNodes.Push(boxNode); StaticModel@ boxObject = boxNode.CreateComponent("StaticModel");
boxObject.model = cache.GetResource("Model", "Models/Box.mdl");
boxNodes.Push(boxNode);
}
}
}
else
{
light.color = Color(0.6f, 0.6f, 0.6f);
light.specularIntensity = 1.5f;
// Create StaticModelGroups in the scene
StaticModelGroup@ lastGroup;
for (int y = -125; y < 125; ++y)
{
for (int x = -125; x < 125; ++x)
{
// Create new group if no group yet, or the group has already "enough" objects. The tradeoff is between culling
// accuracy and the amount of CPU processing needed for all the objects. Note that the group's own transform
// does not matter, and it does not render anything if instance nodes are not added to it
if (lastGroup is null || lastGroup.numInstanceNodes >= 25 * 25)
{
Node@ boxGroupNode = scene_.CreateChild("BoxGroup");
lastGroup = boxGroupNode.CreateComponent("StaticModelGroup");
lastGroup.model = cache.GetResource("Model", "Models/Box.mdl");
}
Node@ boxNode = scene_.CreateChild("Box");
boxNode.position = Vector3(x * 0.3f, 0.0f, y * 0.3f);
boxNode.SetScale(0.25f);
boxNodes.Push(boxNode);
lastGroup.AddInstanceNode(boxNode);
}
} }
} }
// Create the camera // Create the camera. Create it outside the scene so that we can clear the whole scene without affecting it
cameraNode = scene_.CreateChild("Camera"); if (cameraNode is null)
cameraNode.position = Vector3(0.0f, 10.0f, -100.0f); {
Camera@ camera = cameraNode.CreateComponent("Camera"); cameraNode = Node("Camera");
camera.farClip = 300.0f; cameraNode.position = Vector3(0.0f, 10.0f, -100.0f);
Camera@ camera = cameraNode.CreateComponent("Camera");
camera.farClip = 300.0f;
}
} }
void CreateInstructions() void CreateInstructions()
{ {
// Construct new Text object, set string to display and font to use // Construct new Text object, set string to display and font to use
Text@ instructionText = ui.root.CreateChild("Text"); Text@ instructionText = ui.root.CreateChild("Text");
instructionText.text = instructionText.text =
"Use WASD keys and mouse to move\n" "Use WASD keys and mouse to move\n"
"Space to toggle animation"; "Space to toggle animation\n"
"G to toggle object group optimization";
instructionText.SetFont(cache.GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15); instructionText.SetFont(cache.GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15);
// The text has multiple rows. Center them in relation to each other // The text has multiple rows. Center them in relation to each other
instructionText.textAlignment = HA_CENTER; instructionText.textAlignment = HA_CENTER;
// Position the text relative to the screen center // Position the text relative to the screen center
instructionText.horizontalAlignment = HA_CENTER; instructionText.horizontalAlignment = HA_CENTER;
instructionText.verticalAlignment= VA_CENTER; instructionText.verticalAlignment = VA_CENTER;
instructionText.SetPosition(0, ui.root.height / 4); instructionText.SetPosition(0, ui.root.height / 4);
} }
@ -155,6 +201,13 @@ void HandleUpdate(StringHash eventType, VariantMap& eventData)
if (input.keyPress[KEY_SPACE]) if (input.keyPress[KEY_SPACE])
animate = !animate; animate = !animate;
// Toggle grouped / ungrouped mode
if (input.keyPress['G'])
{
useGroups = !useGroups;
CreateScene();
}
// Move the camera, scale movement with time step // Move the camera, scale movement with time step
MoveCamera(timeStep); MoveCamera(timeStep);

Просмотреть файл

@ -1982,6 +1982,18 @@ Properties:<br>
- unsigned numGeometries (readonly) - unsigned numGeometries (readonly)
- unsigned occlusionLodLevel - unsigned occlusionLodLevel
StaticModelGroup : StaticModel
Methods:<br>
- void AddInstanceNode(Node* node)
- void RemoveInstanceNode(Node* node);
- void RemoveAllInstanceNodes()
- unsigned GetNumInstanceNodes() const
- Node* GetInstanceNode(unsigned index) const
Properties:<br>
- unsigned numInstanceNodes (readonly)
Pass : RefCounted Pass : RefCounted
Methods:<br> Methods:<br>

Просмотреть файл

@ -2436,6 +2436,66 @@ Properties:<br>
- uint occlusionLodLevel - uint occlusionLodLevel
StaticModelGroup
Methods:<br>
- void SendEvent(const String&, VariantMap& arg1 = VariantMap ( ))
- bool Load(File@, bool arg1 = false)
- bool Save(File@) const
- bool LoadXML(const XMLElement&, bool arg1 = false)
- bool SaveXML(XMLElement&) const
- void ApplyAttributes()
- bool SetAttribute(const String&, const Variant&)
- void ResetToDefault()
- void RemoveInstanceDefault()
- Variant GetAttribute(const String&) const
- Variant GetAttributeDefault(const String&) const
- void Remove()
- void MarkNetworkUpdate() const
- void DrawDebugGeometry(DebugRenderer@, bool)
- void AddInstanceNode(Node@)
- void RemoveInstanceNode(Node@)
- void RemoveAllInstanceNodes()
Properties:<br>
- int refs (readonly)
- int weakRefs (readonly)
- ShortStringHash type (readonly)
- String typeName (readonly)
- String category (readonly)
- uint numAttributes (readonly)
- Variant[] attributes
- Variant[] attributeDefaults (readonly)
- AttributeInfo[] attributeInfos (readonly)
- bool temporary
- bool enabled
- bool enabledEffective (readonly)
- uint id (readonly)
- Node@ node (readonly)
- bool inView (readonly)
- bool castShadows
- bool occluder
- bool occludee
- float drawDistance
- float shadowDistance
- float lodBias
- uint viewMask
- uint lightMask
- uint shadowMask
- uint zoneMask
- uint maxLights
- BoundingBox boundingBox (readonly)
- BoundingBox worldBoundingBox (readonly)
- Model@ model
- Material@ material (writeonly)
- Material@[] materials
- uint numGeometries (readonly)
- Zone@ zone (readonly)
- uint occlusionLodLevel
- uint numInstanceNodes (readonly)
- Node@[] instanceNodes (readonly)
Skybox Skybox
Methods:<br> Methods:<br>

Просмотреть файл

@ -38,6 +38,7 @@
#include "RenderPath.h" #include "RenderPath.h"
#include "Scene.h" #include "Scene.h"
#include "SmoothedTransform.h" #include "SmoothedTransform.h"
#include "StaticModelGroup.h"
#include "Technique.h" #include "Technique.h"
#include "Terrain.h" #include "Terrain.h"
#include "TerrainPatch.h" #include "TerrainPatch.h"
@ -817,6 +818,18 @@ static void RegisterStaticModel(asIScriptEngine* engine)
engine->RegisterObjectMethod("StaticModel", "uint get_occlusionLodLevel() const", asMETHOD(StaticModel, GetOcclusionLodLevel), asCALL_THISCALL); engine->RegisterObjectMethod("StaticModel", "uint get_occlusionLodLevel() const", asMETHOD(StaticModel, GetOcclusionLodLevel), asCALL_THISCALL);
} }
static void RegisterStaticModelGroup(asIScriptEngine* engine)
{
RegisterStaticModel<StaticModelGroup>(engine, "StaticModelGroup", true);
engine->RegisterObjectMethod("StaticModelGroup", "void set_occlusionLodLevel(uint) const", asMETHOD(StaticModelGroup, SetOcclusionLodLevel), asCALL_THISCALL);
engine->RegisterObjectMethod("StaticModelGroup", "uint get_occlusionLodLevel() const", asMETHOD(StaticModelGroup, GetOcclusionLodLevel), asCALL_THISCALL);
engine->RegisterObjectMethod("StaticModelGroup", "void AddInstanceNode(Node@+)", asMETHOD(StaticModelGroup, AddInstanceNode), asCALL_THISCALL);
engine->RegisterObjectMethod("StaticModelGroup", "void RemoveInstanceNode(Node@+)", asMETHOD(StaticModelGroup, RemoveInstanceNode), asCALL_THISCALL);
engine->RegisterObjectMethod("StaticModelGroup", "void RemoveAllInstanceNodes()", asMETHOD(StaticModelGroup, RemoveAllInstanceNodes), asCALL_THISCALL);
engine->RegisterObjectMethod("StaticModelGroup", "uint get_numInstanceNodes() const", asMETHOD(StaticModelGroup, GetNumInstanceNodes), asCALL_THISCALL);
engine->RegisterObjectMethod("StaticModelGroup", "Node@+ get_instanceNodes(uint) const", asMETHOD(StaticModelGroup, GetInstanceNode), asCALL_THISCALL);
}
static void RegisterSkybox(asIScriptEngine* engine) static void RegisterSkybox(asIScriptEngine* engine)
{ {
RegisterStaticModel<Skybox>(engine, "Skybox", true); RegisterStaticModel<Skybox>(engine, "Skybox", true);
@ -1438,6 +1451,7 @@ void RegisterGraphicsAPI(asIScriptEngine* engine)
RegisterLight(engine); RegisterLight(engine);
RegisterZone(engine); RegisterZone(engine);
RegisterStaticModel(engine); RegisterStaticModel(engine);
RegisterStaticModelGroup(engine);
RegisterSkybox(engine); RegisterSkybox(engine);
RegisterAnimatedModel(engine); RegisterAnimatedModel(engine);
RegisterAnimationController(engine); RegisterAnimationController(engine);

Просмотреть файл

@ -0,0 +1,13 @@
$#include "StaticModelGroup.h"
class StaticModelGroup : public StaticModel
{
void AddInstanceNode(Node* node);
void RemoveInstanceNode(Node* node);
void RemoveAllInstanceNodes();
unsigned GetNumInstanceNodes() const;
Node* GetInstanceNode(unsigned index) const;
tolua_readonly tolua_property__get_set unsigned numInstanceNodes;
};

Просмотреть файл

@ -21,6 +21,7 @@ $pfile "Graphics/RenderSurface.pkg"
$pfile "Graphics/Skeleton.pkg" $pfile "Graphics/Skeleton.pkg"
$pfile "Graphics/Skybox.pkg" $pfile "Graphics/Skybox.pkg"
$pfile "Graphics/StaticModel.pkg" $pfile "Graphics/StaticModel.pkg"
$pfile "Graphics/StaticModelGroup.pkg"
$pfile "Graphics/Technique.pkg" $pfile "Graphics/Technique.pkg"
$pfile "Graphics/Terrain.pkg" $pfile "Graphics/Terrain.pkg"
$pfile "Graphics/TerrainPatch.pkg" $pfile "Graphics/TerrainPatch.pkg"

Просмотреть файл

@ -134,7 +134,7 @@ void HugeObjectCount::CreateScene()
// Create new group if no group yet, or the group has already "enough" objects. The tradeoff is between culling // Create new group if no group yet, or the group has already "enough" objects. The tradeoff is between culling
// accuracy and the amount of CPU processing needed for all the objects. Note that the group's own transform // accuracy and the amount of CPU processing needed for all the objects. Note that the group's own transform
// does not matter, and it does not render anything if instance nodes are not added to it // does not matter, and it does not render anything if instance nodes are not added to it
if (!lastGroup || lastGroup->GetNumInstanceNodes() >= 25* 25) if (!lastGroup || lastGroup->GetNumInstanceNodes() >= 25 * 25)
{ {
Node* boxGroupNode = scene_->CreateChild("BoxGroup"); Node* boxGroupNode = scene_->CreateChild("BoxGroup");
lastGroup = boxGroupNode->CreateComponent<StaticModelGroup>(); lastGroup = boxGroupNode->CreateComponent<StaticModelGroup>();
@ -170,7 +170,7 @@ void HugeObjectCount::CreateInstructions()
instructionText->SetText( instructionText->SetText(
"Use WASD keys and mouse to move\n" "Use WASD keys and mouse to move\n"
"Space to toggle animation\n" "Space to toggle animation\n"
"G to toggle object group optimization\n" "G to toggle object group optimization"
); );
instructionText->SetFont(cache->GetResource<Font>("Fonts/Anonymous Pro.ttf"), 15); instructionText->SetFont(cache->GetResource<Font>("Fonts/Anonymous Pro.ttf"), 15);
// The text has multiple rows. Center them in relation to each other // The text has multiple rows. Center them in relation to each other

Просмотреть файл

@ -38,6 +38,7 @@ class Scene;
/// - Competing with http://yosoygames.com.ar/wp/2013/07/ogre-2-0-is-up-to-3x-faster/ :) /// - Competing with http://yosoygames.com.ar/wp/2013/07/ogre-2-0-is-up-to-3x-faster/ :)
/// - Allowing examination of performance hotspots in the rendering code; /// - Allowing examination of performance hotspots in the rendering code;
/// - Using the profiler to measure the time taken to animate the scene; /// - Using the profiler to measure the time taken to animate the scene;
/// - Optionally speeding up rendering by grouping the objects using StaticModelGroup component;
class HugeObjectCount : public Sample class HugeObjectCount : public Sample
{ {
OBJECT(HugeObjectCount); OBJECT(HugeObjectCount);