ADTF_DISPLAY_TOOLBOX  3.8.0 (ADTF 3.14.3)
Source Code for Demo 3D Object Mixin
Location
./src/examples/src/objectmixin
This example shows:
  • how to create multiple 3D objects
  • how to update these objects periodically
  • how to create a separate control to show properties of objects
  • how to offer a possibility to select (pick) an object
Header
#pragma once
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::disptb::mixinlib;
class cObjectMixin : public cBaseObjectSelectionMixin
{ public:
ADTF_CLASS_ID_NAME(cObjectMixin, "demo_adtf_object.3d_mixin.disptb.cid", "Demo 3D Object Mixin");
/*
* Following methods provide extended function, which is characteristic for this mixin.
* They overwrite the base class behaviour.
*/
cObjectMixin();
tResult RequestDynamicInputPin(const tChar* strName,
const iobject_ptr<const IStreamType>& pType) override;
tResult InitScene() override;
tResult UpdateScene(cBaseObjectScene* pScene, const iobject_ptr<const ISample>& pSample) override;
protected:
property_variable<tBool> m_bHistoryShow = tTrue;
property_variable<tUInt32> m_nHistorySize = 0;
property_variable<tBool> m_bMotionVectorShow = tTrue;
std::vector<ISampleReader*> m_oReader;
};
Copyright © Audi Electronics Venture GmbH.
Namespace for functionality provided by the Mixin Library.
Definition: baseobject.h:23
#pragma once
#include <adtffiltersdk/adtf_filtersdk.h>
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::filter;
class cDemoObjectFilter : public cFilter
{
public:
ADTF_CLASS_ID_NAME(cDemoObjectFilter, "demo_object.filter.disptb.cid", "Demo Object Generator Filter");
public:
cDemoObjectFilter();
tResult Process(tNanoSeconds tmTrigger, IRunner* pRunner) override;
private:
property_variable<tUInt> m_nUpdateRate = 20000;
property_variable<tUInt32> m_nObjectCount = 3;
property_variable<tFloat64> m_fObjectAreaWidth = 10.0;
property_variable<tFloat64> m_fObjectSpeed = 3.0;
property_variable<tFloat64> m_fWaveLength = 5.0;
tUInt32 m_nIdBase = 0;
tFloat m_fPosX = 30.0;
tFloat m_fBeta = 0.0;
ISampleWriter* m_pWriter = nullptr;
tNanoSeconds m_tmLastTrigger{-1};
private:
tResult CreateObjects();
};
#pragma once
#include <a_utils/base/types.h>
#pragma pack(push, 1)
struct tADTFObjectListItem
{
tUInt32 nId;
tUInt8 nRed;
tUInt8 nGreen;
tUInt8 nBlue;
tUInt8 nAlpha;
tFloat64 fPosX;
tFloat64 fPosY;
tFloat64 fPosZ;
tFloat64 fRotX;
tFloat64 fRotY;
tFloat64 fRotZ;
tFloat64 fSizeX;
tFloat64 fSizeY;
tFloat64 fSizeZ;
tFloat64 fMotionX;
tFloat64 fMotionY;
tFloat64 fMotionZ;
tBool bNew;
};
struct stream_meta_type_adtf_object_list
{
static constexpr const tChar *const MetaTypeName = "adtf/object_list";
};
#pragma pack(pop)
Implementation
#include "objectmixin.h"
#include "adtfobjectlist.h"
#include <osg/Switch>
#include <osg/Group>
#include <osgViewer/Viewer>
#include <osg/PositionAttitudeTransform>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osgText/Text>
using namespace adtf::disptb::mixinlib;
#ifdef WIN32
#pragma warning(push)
#pragma warning(disable : 4200)
#endif
struct tADTFObjectList
{
tADTFObjectListItem aItems[0];
};
#ifdef WIN32
#pragma warning(pop)
#endif
cObjectMixin::cObjectMixin()
{
m_bHistoryShow.SetDescription("If enabled, the history will be shown.");
RegisterPropertyVariable("history_show", m_bHistoryShow);
m_nHistorySize.SetDescription("Size of history trail.");
RegisterPropertyVariable("history_size", m_nHistorySize);
m_bMotionVectorShow.SetDescription("If enabled, the motion vector will be visible.");
RegisterPropertyVariable("motion_vector_show", m_bMotionVectorShow);
SetDescription("Use this Mixin to create movable 3D objects in the scene.");
adtf::streaming::set_help_link(*this, "$(ADTF_DISPLAY_TOOLBOX_DIR)/doc/displaytoolbox_html/page_3d_object_mixin_example_readme.html");
}
tResult cObjectMixin::RequestDynamicInputPin(const tChar* strName, const iobject_ptr<const IStreamType>& /*pType*/)
{
m_oReader.push_back(CreateInputPin(strName, stream_meta_type_adtf_object_list()));
RETURN_NOERROR;
}
tResult cObjectMixin::InitScene()
{
for (auto pReader: m_oReader)
{
std::string strName;
pReader->GetName(adtf_string_intf(strName));
RETURN_IF_FAILED(AddScene(pReader, new cBaseObjectScene(strName.c_str())));
}
RETURN_NOERROR;
}
tResult cObjectMixin::UpdateScene(cBaseObjectScene* pScene, const iobject_ptr<const ISample>& pSample)
{
sample_data<tADTFObjectList> oData(pSample);
auto nCount = oData.GetDataSize() / sizeof(tADTFObjectListItem);
for (tUInt nObject = 0; nObject < nCount; ++nObject)
{
const auto& oObject = oData->aItems[nObject];
// check if we already have this object
if (IS_FAILED(pScene->GetObject(oObject.nId, &pBaseObj)) ||
oObject.bNew)
{
// check if we are forced to create a new object
if (oObject.bNew && pBaseObj != nullptr)
{
pScene->RemoveObject(oObject.nId);
}
// we don't, so create a new one
pBaseObj = new adtf::disptb::mixinlib::cBaseObject(oObject.nId);
// add it to the scene, the object will be managed by the scene
// so you don't have to perform cleanup
pScene->AddObject(pBaseObj);
pBaseObj->SetHistory(m_bHistoryShow, m_nHistorySize);
pBaseObj->SetMotionVector(m_bMotionVectorShow);
}
// now set the object information
pBaseObj->SetPosition(oObject.fPosX,
oObject.fPosY,
oObject.fPosZ);
pBaseObj->SetRotation(oObject.fRotX,
oObject.fRotY,
oObject.fRotZ);
pBaseObj->SetSize(oObject.fSizeX,
oObject.fSizeY,
oObject.fSizeZ);
pBaseObj->SetColor(oObject.nRed / 255.0,
oObject.nGreen / 255.0,
oObject.nBlue / 255.0,
oObject.nAlpha == 255 ? 1.0 : oObject.nAlpha / 255.0);
pBaseObj->SetMotion(oObject.fMotionX,
oObject.fMotionY,
oObject.fMotionZ);
// and every time we modified an object we have to call its Update() method
pBaseObj->Update();
}
// remove all objects that have not been in this sample.
pScene->RemoveInvalid();
RETURN_NOERROR;
}
Base class for objects that can be managed with cBaseObjectScene.
Definition: baseobject.h:40
virtual tResult SetHistory(tBool bEnabled, tUInt32 nCount=0)
Enables or disable the history trail of this object.
virtual tResult SetRotation(tFloat64 fRotX, tFloat64 fRotY, tFloat64 fRotZ)
Sets the rotation (attitude) of the object.
virtual tResult SetMotionVector(tBool bEnabled)
Enables or disables the motion vector.
virtual tResult SetMotion(tFloat64 fMotionX, tFloat64 fMotionY, tFloat64 fMotionZ)
Sets the motion vector of the object.
tResult Update()
Base Implementation sets the updated property to true.
virtual tResult SetSize(tFloat64 fSizeX, tFloat64 fSizeY, tFloat64 fSizeZ)
Sets the dimensions of the object.
virtual tResult SetColor(tFloat64 fRed, tFloat64 fGreen, tFloat64 fBlue, tFloat64 fAlpha)
Sets the color of the object.
virtual tResult SetPosition(tFloat64 fPosX, tFloat64 fPosY, tFloat64 fPosZ)
Sets the position of the object.
tResult InitScene() override
Init the scene of this mixin.
#include "demoobjectfilter.h"
#include "adtfobjectlist.h"
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif
#include <cmath>
#ifndef M_PI
namespace
{
const double M_PI = std::acos(-1.0);
const double M_PI_2 = M_PI/2.0;
}
#endif
cDemoObjectFilter::cDemoObjectFilter()
{
m_nObjectCount.SetDescription("Amount of objects.");
RegisterPropertyVariable("object_count", m_nObjectCount);
m_fObjectAreaWidth.SetDescription("Width of object area.");
RegisterPropertyVariable("object_area_width", m_fObjectAreaWidth);
m_fObjectSpeed.SetDescription("Speed for objects.");
RegisterPropertyVariable("object_speed", m_fObjectSpeed);
m_fWaveLength.SetDescription("Length for wave.");
RegisterPropertyVariable("wave_length", m_fWaveLength);
m_pWriter = CreateOutputPin("object_list", stream_meta_type_adtf_object_list());
SetDescription("object_list", "Output pin to provide data containing object list.");
CreateRunner("generate_objects", cTimerTriggerHint(std::chrono::seconds(1)));
SetDescription("generate_objects", "Runner to periodically trigger the function which generates the object list.");
SetDescription("Use this Filter to create a object list for scene.");
SetHelpLink("$(ADTF_DISPLAY_TOOLBOX_DIR)/doc/displaytoolbox_html/page_3d_object_mixin_example_readme.html");
}
tResult cDemoObjectFilter::Process(tNanoSeconds tmTrigger, IRunner* /*pRunner*/)
{
tFloat64 fXDiff = 0.0;
tFloat64 fBetaDiff = 0.0;
if (m_tmLastTrigger.nCount > 0)
{
fXDiff = m_fObjectSpeed / (tNanoSeconds(std::chrono::seconds(1)) / (tmTrigger - m_tmLastTrigger));
fBetaDiff = 2 * M_PI / (m_fWaveLength / fXDiff);
}
m_tmLastTrigger = tmTrigger;
tFloat fMotionScale = m_fObjectSpeed / fXDiff;
// we set the amplitude to half of the wave length
tFloat fAmplitude = m_fWaveLength / 2.0;
// this is our new y position
tFloat fJiggle = sin(m_fBeta) * fAmplitude;
// calculate difference to last
tFloat fMotionY = fJiggle - (sin(m_fBeta - fBetaDiff) * fAmplitude);
// scale it to m/s
fMotionY *= fMotionScale;
// scale in x direction
tFloat fMotionX = -fXDiff * fMotionScale; // just to be explicit
tFloat fRot = atan2(fMotionY, fMotionX);
auto nBufferSize = sizeof(tADTFObjectListItem) * m_nObjectCount;
object_ptr<ISample> pSample;
RETURN_IF_FAILED(alloc_sample(pSample, tmTrigger));
{
object_ptr_locked<ISampleBuffer> pBuffer;
RETURN_IF_FAILED(pSample->WriteLock(pBuffer, nBufferSize));
// initialize to zero so we only have to set the attributes we want to explicitly
adtf::util::cMemoryBlock::MemZero(pBuffer->GetPtr(), nBufferSize);
// we directly access the sample buffer
auto pObj = static_cast<tADTFObjectListItem*>(pBuffer->GetPtr());
// and create our objects
for (tUInt nObj = 0; nObj < m_nObjectCount; ++nObj, ++pObj)
{
// each object needs an id, we switch the id each time the objects reach 5 meters before 0.
pObj->nId = m_nIdBase + nObj;
// calculate and set its position.
pObj->fPosX = m_fPosX;
pObj->fPosZ = 1.0;
pObj->fPosY = -(m_fObjectAreaWidth / 2.0) + ((m_fObjectAreaWidth / (m_nObjectCount + 1)) * (nObj + 1)) + fJiggle;
// set its attitude
pObj->fRotZ = fRot;
// set the motion vector (calculation at the beginning if this method)
pObj->fMotionX = fMotionX;
pObj->fMotionY = fMotionY;
// we use fixed size objects, all the same
pObj->fSizeX = pObj->fSizeY = pObj->fSizeZ = 1.0;
// bright red
pObj->nRed = 255;
pObj->nAlpha = nObj % 2 ? 127 : 255;
}
}
m_pWriter->Write(pSample);
// update our angles and positions
m_fBeta += fBetaDiff;
m_fPosX -= fXDiff;
// reset them when coming to close
if (m_fPosX < 5.0)
{
m_nIdBase += m_nObjectCount;
m_fPosX = 30.0;
}
RETURN_NOERROR;
}
#include "demoobjectfilter.h"
#include "objectmixin.h"
ADTF_PLUGIN_VERSION("Demo 3D Object Mixin Plugin",
disptb,
DISPTB_VERSION_MAJOR,
DISPTB_VERSION_MINOR,
DISPTB_VERSION_PATCH,
cObjectMixin,
cDemoObjectFilter)