Upload
others
View
14
Download
0
Embed Size (px)
Citation preview
Creating Component using C++
Version 1.0 - 2/6/2013
Written by: Sonia Bourdache
Validated by: Anne Marie Miller
3D
S.C
OM
© D
assault S
ystè
me
s
| C
onfid
entia
l In
form
atio
n | 0
1/0
2/2
012
ref.:
Docum
ent R
efe
rence |
2
Executive Summary
3DVIA Studio Pro provides several components that you can easily use to create your experience.
In some case, you will need to customize them to create your own behaviors, functions and components.
This white paper explains how to create and manipulate your own C++ components in 3DVIA Studio Pro
with SDK.
3
TABLE OF CONTENT
1. INTRODUCTION ..................................................................................................................................... 4
2. LET’S STARTING WITH A KIND REMINDER OF WHAT IS AN ACTOR, A COMPONENT AND AN
ACTOR TEMPLATE ........................................................................................................................................ 6
3. DOWNLOAD AND BUILD YOUR COMPONENT ................................................................................... 8
4. BINDING MEMBER AND FUNCTION OF A COMPONENT ................................................................ 13
5. MANAGE SEVERAL COMPONENTS .................................................................................................. 18
6. EXAMPLE OF GEOMETRY CREATION IN SDK ................................................................................. 21
7. CREATION OF DYNAMIC ACTOR ...................................................................................................... 27
8. SAMPLE CODE TO SHOW HOW TO BROWSE A 3DVIA STUDIO PRO PROJECT ......................... 29
9. CONCLUSION ...................................................................................................................................... 34
4
1. Introduction
In this document, you will find some definitions of 3DVIA Studio Pro features but the goal is to give you
some source code examples of some scenarios to help you when you start with the SDK of 3DVIA Studio
Pro.
To begin, I invite you to read all the articles related to the topic “SDK Concepts” available in the 3DVIA
Studio documentation in the “Contents” tab (see the screenshot below): Studio Internal Architecture and
APIs, the Taskloop, Components, Projects and Stages, Templates and Actors, Assets and Resources,
Behavioral Engine and Render Engine. It is important to understand all these notions before starting to
create your own component.
With the content of this white paper, you will be able to create a component, create and manipulate
members of the component, manipulate components of an actor, create a 3D component with an
associated geometry, manipulate dynamic actors and browse a Studio Pro project.
5
6
2. Let’s starting with a kind reminder of what is an actor, a
component and an actor template
An actor of a stage is a runtime element in a stage: what will be visible and/or running when the
stage is loaded: geometry, behaviors, physics … An actor is an aggregation of what we call
components. There are 2 kind of actor: static actor and dynamic actor. For example, static actors
are resources imported into a stage: when you import a resource, an actor is created and added to
the Project Editor. Dynamic actors are actors created dynamically at runtime, we will see later how
to create them.
A component is a feature that you can simply drag and drop to an actor. Thus, we said you add
this component to the actor’s component ring. The component ring is the group of all the
components describing the actor.
An actor template is used when you need to instantiate several times an object: for example a
character, a car etc…
The screenshot below is an example of a actor’s component ring: the actor is “Capsule_-node”, its
component ring is composed of 4 components: a 3D component (vkEntity3D), a constraint component
(vkObjectSliderConstraint), a clickable component (vkClickable) and the behavior component “Rotate
Behavior” I have created. To create a new behavior component, you just need to right click on the actor
and select “Add New Behavior…” An important notion to understand is that all the components can
communicate with each other. Studio engine provides mechanisms that allows to retrieve the components
by their unique types (it is not possible to have two components of the same type in the component ring).
You can use these mechanisms using SDK or VSL.
In this example, from “RotateBehavior” component, if I need to retrieve the 3D component (vkEntity3D)
from the component ring of this actor, I have 2 solutions in VSL: the first solution consists to declare a
vkEntity3DPtr in Target of the VSL task, this allows casting the unique vkEntity3D present in the
component ring.
The second solution is to retrieve the actor (by its ID for example) and cast it to retrieve the 3D component
(vkEntity3D).
We will see later how to retrieve a 3D component from the component ring using SDK (C++).
7
This screenshot shows the result testing both solutions in VSL:
8
3. Download and build your Component
In the 3DVIA Studio Pro documentation, you can download an example of basic component in the white
paper “Creating a Component”. This example presents how to declare and make visible in 3DVIA Studio
Pro the members of your component (binding).
We will see in the next topic what binding operation means. In the documentation, it is also interesting to
read the white paper “Understanding Binding by Example” to understand how to manipulate in 3DVIA
Studio Pro a global function, enum and flag type, a class, methods that are defined in C++ (binding).
The Visual C++ Project downloaded is composed of the component “TestComponent” and the module
“AdditionalContentModule” that you need to register your component.
9
All the components listed in 3DVIA Studio Pro are available in the Libraries tab and are listed by category
as you can see in the screenshot below. You can add your component in one of these categories or you
can also create your own component’s category.
Note that you can create a component using 3DVIA Studio Pro 32 bits or 3DVIA Studio Pro 64 bits. In this
white paper I choose to work with 3DVIA Studio Pro 32 bits. Therefore, the Solution Configuration and
Platform mode is Debug/ Win 32. Note also, you can add breakpoints in the Visual C++ project to execute
it in debug mode.
10
Now, I would like to create the new category “SDK” in Libraries\Presets and add inside the component
“TestComponent”. To do this, I should follow the following steps:
1) Create the folder C:\Program Files (x86)\3DVIA\3DVIA Studio
Pro\bin\Win32_Dynamic\release_licensed\plugins\SDK, that means when you will build your
component, the output file “TestComponent.vkmodule” will be generated in this folder.
2) You should modify the Visual C++ project properties to add Include and Lib directories.
Include folder is the following C:\Program Files (x86)\3DVIA\3DVIA Studio Pro\SDK\win32\include.
Lib folder is this one C:\Program Files (x86)\3DVIA\3DVIA Studio Pro\SDK\win32\lib.
Remark: if you use 3DVIA Studio Pro 64 bits, both folders are C:\Program Files\3DVIA\3DVIA
Studio Pro 64-bit\SDK\win64\include and C:\Program Files\3DVIA\3DVIA Studio Pro 64-
bit\SDK\win64\lib.
Be sure also to add the module path in Linker\General\Output File as it is displayed here:
11
3) Last step is to create the Library Item Description file (.mpli) of your component. This file allows
exposing your component in the Libraries tab in Studio Pro.
Each resource must be identified by a Library Item. Library items are XML files, identifiable by their
.mpli extension.
In my component example, I should create TestComponent.mpli file and it will be located in the
folder C:\Program Files (x86)\3DVIA\3DVIA Studio
Pro\data\Applications\3dviamp\Libraries\TemplateLibrary\SDK.
Below is the content of this XML file:
<?xml version="1.0" encoding="UTF-8"?>
<asset>
<infos>
<version>2.10.74.0</version>
<name>TestComponent</name>
<properties count="1">
<item>
<id>resourceURI</id>
<value
type="vkString">$(ExeURI)plugins/SDK/TestComponent/TestComponent.vkModule?cat=
Template#New TestComponent</value>
</item>
</properties>
</infos>
<resources/>
</asset>
For more information about mpli files, see the White Paper “Managing Library Item Description Files
(.mpli)”.
Once your project compiled, you can execute it (using debug mode if you need).Then, running 3DVIA
Studio Pro you will find the component “TestComponent” in the category Libraries\Presets\SDK, so now
you are able to select and drag and drop it in the Project Editor.
12
In the Project Editor, you can see the actor “New TestComponent”.
13
4. Binding member and function of a component
My component is ready to be used in 3DVIA Studio Pro, now we are going to see how to add members
and functions to the component using binding operation.
The binding concept is important because it allows to the member or the function to be visible and
manipulable in 3DVIA Studio Pro.
A member is a property of the component and once declared and bound, it is usable in 3DVIA Studio Pro
i.e. it is displayed in the Property View of the component and can be modified in authoring or dynamically.
You can find below some examples of how to declare and bind different types:
To declare and bind a float type member, you should use this line:
iTm.DeclareMember(VK_AS("Value"),
vkFloat::s_Type[ch],GET_MEMBER_OFFSET(TestComponent, value));
To declare and bind a uint32 type member:
iTm.DeclareMember(VK_AS("Offset"), vkUint32::s_Type[ch],
GET_MEMBER_OFFSET(TestComponent, offset));
To declare and bind a vkMaterial type member:
DECLARE_MEMBER2(Material, vkMaterial::s_TypePtr);
You should add the VRE namespace in the file TestComponent.cpp file to build correctly your
project.(using namespace VRE;)
To declare and bind an event member of type vkEventType :
DECLARE_MEMBER2(Event, vkEventType::s_TypePtr);
To declare and bind a vkArray<uint32> type member:
DECLARE_MEMBER2(MyUint32Array, vkInt32::s_Type[ch]->GetDynArrayType());
Binding operations
VK_DECLARE_RTTI_COMPO
NENT
DeclareMember(…)
DeclareCMethod
…
Usable component in
3DVIA Studio Pro
Component class in C++
class MyComponent
Members
Functions
14
To declare and bind a vkArray<MyStruct> type member where MyStruct is a C++ structure with
two elements.
MyStruct {
uint32 val;
vkString name;
}
The solution is first to bind the struct “MyStruct” as following:
vkType* TypeStruct=iTm.BeginClass(VK_AS("MyStruct"),0,sizeof(MyStruct))
{
iTm.DeclareMember(VK_AS("Val"), vkUint32::s_Type,
GET_MEMBER_OFFSET(TestComponent::MyStruct, val));
iTm.DeclareMember(VK_AS("Name"), vkString::s_Type,
GET_MEMBER_OFFSET(TestComponent::MyStruct, name));}
and add the binding of the member:
DECLARE_MEMBER2(MyStructArray, TypeStruct->GetDynArrayType());
I declare all these members in the function
TestComponent::RegisterMembers(vkTypeManager& iTm) in the file “TestComponent.cpp”.
I build the C++ project and I run 3DVIA Studio Pro and I drag and drop the component from
Libraries/Presets/SDK to the DefaultStage in the Project Editor.
You can see in the Property View of the component, the different bound properties.
15
You can modify the member’s values directly in 3DVIA Studio Pro authoring or modify them dynamically:
a. I edit directly the members from the Property View. For example, I edit “My Uint 32 Array” and “My
Struct Array” members and fill the values in authoring:
16
I can also select a material among those present in the scene and select an event among those proposed
by 3DVIA Studio Pro:
b. The second way is to modify those dynamically defining Getter/Setter functions in the component.
For example, if you want to change dynamically the “Offset” value used in this component, you
should define and bind the both simple functions as following:
17
iTm.DeclareCMethod("uint32 GetOffset()const",
vkFunctionPtr(&TestComponent::Getoffset), vkFunctionPtr::eSTD);
iTm.DeclareCMethod("void SetOffset(uint32 iVal)",
vkFunctionPtr(&TestComponent::Setoffset), vkFunctionPtr::eSTD);
Then in 3DVIA Studio Pro, you can create a VSL Task in a new behavior component added to the “Test
Component” actor:
task NewBehavior::Task
{
Target {
NewBehaviorPtr be;
TestComponentPtr MyComponent; /* add this line as Target allows
to retrieve
“TestComponent” from the Component Ring. */
};
bool Execute(const vkTaskContext& iCtx)
{
MyComponent.SetOffset(10);
uint32 res= MyComponent.GetOffset();
return true;
}
};
By this way, at runtime, the Offset value will be correctly modified (displayed in red in the Property View):
18
5. Manage several components
Now, we are going to see how to manage two components in the same module. In the previous
component example, a module has been created in your project as you can see in the following
screenshot. In this example, I have created two components “MyClass” and “TestComponent”.
A module can be considered as an object that supports all the Studio Pro features that you can create in
C++ (BuildingBlocks, 3D Readers, Readers etc…). Have a look to the white paper “Creating a Module” if
you need more information about module.
This module is important in the case of you want to create several components because each time you
create a new component, you need to register it in this module.
In the method AdditionalContentModule::_CreateContextedSingletons(), I put in bold the information to add
for your second component to be recognized by Studio Pro:
AdditionalContentModule::_CreateContextedSingletons()
{
vkCtx ch = GetCtx();
vkTypeManager& tm = vkTypeManager::Instance(ch);
vkResourceManager& rm = vkResourceManager::Instance(ch);
// Component Registration
TestComponent::RegisterType(tm);
MyClass::RegisterType(tm);
// TestComponent Template Creation (optional)
vkComponentFactory* factoryTestComponent = new
vkComponentFactory(TestComponent::s_Type[ch]);
factoryTestComponent ->SetResourceID(VK_AS_HARDCODED("New TestComponent"));
rm.AddResource(factoryTestComponent, this);
vkComponentFactory* factoryMyClass = new
vkComponentFactory(MyClass::s_Type[ch]);
factoryMyClass ->SetResourceID(VK_AS_HARDCODED("New MyClass"));
rm.AddResource(factoryMyClass, this);
19
return errOk;
}
Then, you should also create a mpli file for “MyClass” component in C:\Program Files (x86)\3DVIA\3DVIA
Studio Pro\data\Applications\3dviamp\Libraries\TemplateLibrary\SDK
<?xmlversion="1.0" encoding="UTF-8"?>
<asset>
<infos>
<version>2.10.74.0</version>
<name>MyClass</name>
<propertiescount="1">
<item>
<id>resourceURI</id>
<value
type="vkString">$(ExeURI)plugins/SDK/TestComponent/TestComponent.vkModule?cat=
Template#New MyClass</value>
</item>
</properties>
</infos>
<resources/>
</asset>
20
Now you are able to use the both components in 3DVIA Studio Pro:
21
6. Example of geometry creation in SDK
Now, I would like to share a sample of creation of geometry that I am going to integrate to my component.
This sample works also using VSL.
To do this, I create the function TestComponent::CreateGeometry() and I should bind it to be usable in
3DVIA Studio Pro:
void TestComponent::CreateGeometry(void)
{
vkCtx ch = GetCtx();
vkEntity3D* entity=vkEntity3D::CreateInstance(ch);
if(entity)
{
entity->SetObjectID("newEntity");
vkEntity3D* root = vkRenderManager::Instance(ch).GetWorld();
if(root)
entity->SetParent(root, false);
}
vkGeometry* geom = vkGeometry::CreateInstance(ch);
if(geom)
{
geom->SetObjectID("newGeom");
// Allocate primitive materials
geom->SetMaterialCount(1);
//Material is a member of TestComponent (as seen above)
geom->SetMaterial(0,Material);
// Allocate primitives (here just one)
geom->SetPrimitiveCount(0, 1);
}
// Lock allocated primitive
vkPrimitive& prim = geom->LockPrimitive(0, 0);
// Allocate primitive's vertices
uint32 vertexCount = 4;
vkVertexDeclaration* vDecl = vkVertexDeclaration::PositionColorNormal(ch);
prim.CreateVertices(vertexCount, vDecl, false);
22
// Lock allocated vertices, get the first one
float r=128.0; float g= 128.0; float b= 128.0;
vertexStruct* vert = (vertexStruct*)prim.LockVertices(0, vertexCount, 0);
{
vert->position = vkVec3(-1.0,0.0,1.0);
vert->color = vkIColor::vkIColor(r, g, b);
vert->normal= vkVec3(0.0,1.0,0.0);
vert++;
vert->position = vkVec3(1.0,0.0,1.0);
vert->color = vkIColor::vkIColor(r, g, b);
vert->normal= vkVec3(0.0,1.0,0.0);
vert++;
vert->position = vkVec3(1.0,0.0,-1.0);
vert->color = vkIColor::vkIColor(r, g, b);
vert->normal= vkVec3(0.0,1.0,0.0);
vert++;
vert->position = vkVec3(-1.0,0.0,-1.0);
vert->color = vkIColor::vkIColor(r, g, b);
vert->normal= vkVec3(0.0,1.0,0.0);
}
prim.UnlockVertices();
uint16 indiceCount = vertexCount;
prim.CreateIndices(ch,indiceCount, eTriFan);
uint16* indice = (uint16*)prim.LockIndices(0, indiceCount, 0);
{
*indice = 0;
indice++;
*indice = 1;
indice++;
*indice = 2;
indice++;
*indice = 3;
}
prim.UnlockIndices();
// Unlock geometry
geom->UnlockPrimitive(0, 0);
// Set geometry
entity->SetRenderable(geom);
}
23
And the type “vertexStruct” is the following C++ Structure:
struct vertexStruct {
vkVec3 position;
vkIColor color;
vkVec3 normal;
};
Remark: I put in bold the lines in the above sample code corresponding to the normal vector, it is important
to define the vector normal to allow to the geometry to react to the light (like Spot Light for example).
I declare the function as following and I run the project:
iTm.DeclareCMethod(VK_AS("void CreateGeometry(void)"),
vkFunctionPtr(&TestComponent::CreateGeometry),vkFunctionPtr::eSTD );
In 3DVIA Studio Pro, I select a material in the corresponding member of TestComponent and I create a
new behavior to test the function TestComponent::CreateGeometry():
24
25
In the task NewBehavior::Task, I call the function TestComponent::CreateGeometry():
26
As you can see, the geometry is correctly created and displayed in the 3D View. In the Scene Graph
Browser, I can see my vkEntity3D “newEntity” with its geometry “newGeom” and its material associated.
Note: There is no new node created in the Project Editor and it’s normal because no actor has been
created. So the question now is how to create dynamically an actor with this 3D component? I need to
create a dynamic actor.
27
7. Creation of Dynamic Actor
Taking the previous example, I am going to create a dynamic actor. I need to create an actor template and
a 3D template and add this template to the actor. The following code is an example:
vkActorTemplate* actorTpl= vkActorTemplate::CreateInstance(ch);
vkStage* CurrentStage= GetStage();
vkNode3DTemplate* template3D= vkNode3DTemplate::CreateInstance(ch);
if(template3D)
template3D->SetPrototype(entity);
if(actorTpl)
{
actorTpl->AddTemplate(vkUCI::kSelfActor, template3D);
vkActor * myact= CurrentStage->CreateDynamicActor("MyActor", actorTpl);
}
I add the above code to the function TestComponent::CreateGeometry(). The following screenshot shows
the result in 3DVIA Studio Pro: the actor “My Actor” and its geometry “newGeom” have been created in the
Project Editor.
Remark: an actor has always its own template actor associated so when an actor is modified, in the Studio
engine, its template is also modified then the actor is recreated with this modified template.
Another sample code that could be interesting to use is how to load an extern asset like 3DXML file or
.DAE file in 3DVIA Studio Pro? A solution is to take this example:
28
void TestComponent::Load3DXML(void)
{
vkCtx ch = GetCtx();
vkAssetPtr asset;
vkArray<vkResourcePtr> resources;
vkURI uri;
uri.Create (ch,"file:///C:/test/Sample.3dxml");
vkStage* stage=GetStage();
stage->LoadAsset(uri, resources, &asset);
vkArray<vkTemplatePtr> templates;
vkTemplate::ExtractTemplates(asset, templates);
for(int noTpl=0; noTpl<templates.Size(); noTpl++)
{
vkActorTemplatePtr actorTpl =
vkActorTemplate::CreateInstance(ch,templates[noTpl]->GetObjectID(),
templates[noTpl]);
vkActorPtr newActor = stage->CreateDynamicActor(templates[noTpl]-
>GetObjectID(), actorTpl);
vkString str;
vkNode3DPtr ent = newActor; // Access to the 3D component of the
actor’s component ring.
}
}
Remark: to create a vkURI object type, you have noted that the vkString has to be defined like this:
“file:///z:/directory/file.ext”.
I declare the function as following:
iTm.DeclareCMethod(VK_AS("void Load3DXML(void)"),
vkFunctionPtr(&TestComponent:: Load3DXML),vkFunctionPtr::eSTD );
And I run the project, I create a new VSL task to call the function TestComponent::Load3DXML(). Here is
the result in 3DVIA Studio Pro:
29
8. Sample code to show how to browse a 3DVIA Studio Pro project
A frequent question is how to browse the project to retrieve all the stages, the viewport, the actors, the
lights etc…
Below is an example of code that can help you to start. The scenario in 3DVIA Studio Pro is the following: I
dragged and dropped “TestComponent” from Libraries/Presets/SDK to the DefaultStage in the Project
Editor: I dragged and dropped also a primitive (vkEntity3D) from Libraries/Samples/Models/Primitives to
the actor “New TestComponent”. Then I add the new component behavior “NewBeh” to the component ring
of the actor.
The goal here is to modify the opacity of the vkEntity3D using the value member previously defined. By this
way, the user can edit directly the field “Value” in the property view of the actor “New TestComponent”:
30
With this example, we are going to see also how to retrieve from the component “NewBeh” the 3D
component (vkEntity3D). I add also the code to show how to retrieve the Viewport:
void TestComponent::BrowseProject(void)
{
//Viewport
vkCtx ch = GetCtx();
vkRenderManager& rm = vkRenderManager ::Instance(ch) ;
vkViewportPtr viewport = rm.GetDevice(0)->GetCurrentViewport();
vkCameraPtr cam = viewport->GetCamera();
//Browse Stages
vkArray<vkStagePtr> allstages;
vkProjectPtr project=GetStage()->GetProject();
project->GetAllStages(allstages);
int size= allstages.Size(); /* The function GetAllStages returns also the
folder “Template” considered as a stage, if you want to exclude it, you can
use the function IsProjectTemplatesFolder. */
for (int i=0;i<size;i++)
{
vkStagePtr stage= allstages[i];
vkString StageName= stage->GetObjectID(); //Return the name of the stage
VKLOGW(StageName);
if(str=="DefaultStage")
{
vkActorPtr MyComponent = stage->GetActor("New TestComponent"); //Returns New
TestComponent
vkEntity3DPtr Obj3D= vkEntity3D::ComponentCast(MyComponent); //this cast
allows to return the component vkEntity3D of the component ring.
if(Obj3D)
{
vkString Component3DName= Obj3D->GetObjectID();
Obj3D->SetOpacity(value);
VKLOGW(Component3DName);
}
}
}
}
I declare the function as following:
iTm.DeclareCMethod(VK_AS("void BrowseProject (void)"),
vkFunctionPtr(&TestComponent:: BrowseProject),vkFunctionPtr::eSTD );
And I run the project, I create a new VSL task to call the function TestComponent::BrowseProject(). Here
are the results with different values of the member “Value”:
31
With Value=0.2
32
With Value= 0.6:
33
With Value= 1:
34
9. Conclusion
I hope now you know more about notion of actor, component ring, stage, component, template and I hope
you are ready to create your own component.
If you have questions, don’t hesitate to create a service request via the support platform
http://www.3ds.com/support. You can find also a lot of information consulting the Knowledge Base.
Finally, you can find also many posts related to SDK and VSL in the 3DVIA Studio forum:
http://www.3dvia.com/forums/forum/3dvia-studio .
35