ADTF Display Toolbox
Loading...
Searching...
No Matches
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
{
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 adtf::ucom::iobject_ptr<const adtf::streaming::IStreamType>& pType) override;
tResult InitScene() override;
tResult UpdateScene(adtf::disptb::mixinlib::cBaseObjectScene* pScene,
const adtf::ucom::iobject_ptr<const adtf::streaming::ISample>& pSample) override;
protected:
adtf::base::property_variable<tBool> m_bHistoryShow = tTrue;
adtf::base::property_variable<tUInt32> m_nHistorySize = 0;
adtf::base::property_variable<tBool> m_bMotionVectorShow = tTrue;
std::vector<adtf::streaming::ISampleReader*> m_oReader;
};
Copyright © Audi Electronics Venture GmbH.
Base class for managing a scene of objects.
tResult InitScene() override
Init the scene of this mixin.
#pragma once
#include <adtffiltersdk/adtf_filtersdk.h>
class cDemoObjectFilter : public adtf::filter::cFilter
{
public:
ADTF_CLASS_ID_NAME(cDemoObjectFilter, "demo_object.filter.disptb.cid", "Demo Object Generator Filter");
public:
cDemoObjectFilter();
tResult Process(adtf::base::tNanoSeconds tmTrigger, adtf::streaming::IRunner* pRunner) override;
private:
adtf::base::property_variable<tUInt> m_nUpdateRate = 20000;
adtf::base::property_variable<tUInt32> m_nObjectCount = 3;
adtf::base::property_variable<tFloat64> m_fObjectAreaWidth = 10.0;
adtf::base::property_variable<tFloat64> m_fObjectSpeed = 3.0;
adtf::base::property_variable<tFloat64> m_fWaveLength = 5.0;
tUInt32 m_nIdBase = 0;
tFloat m_fPosX = 30.0;
tFloat m_fBeta = 0.0;
adtf::streaming::ISampleWriter* m_pWriter = nullptr;
adtf::base::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
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
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/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;
}
tResult InitScene() override
Init the scene of this mixin.
Base class for objects that can be managed with cBaseObjectScene.
Definition baseobject.h:42
virtual tResult SetHistory(tBool bEnabled, tUInt32 nCount=0)
Enables or disable the history trail of this object.
Definition baseobject.h:245
virtual tResult SetRotation(tFloat64 fRotX, tFloat64 fRotY, tFloat64 fRotZ)
Sets the rotation (attitude) of the object.
Definition baseobject.h:322
virtual tResult SetMotionVector(tBool bEnabled)
Enables or disables the motion vector.
Definition baseobject.h:267
virtual tResult SetMotion(tFloat64 fMotionX, tFloat64 fMotionY, tFloat64 fMotionZ)
Sets the motion vector of the object.
Definition baseobject.h:410
tResult Update()
Base Implementation sets the updated property to true.
Definition baseobject.h:209
virtual tResult SetSize(tFloat64 fSizeX, tFloat64 fSizeY, tFloat64 fSizeZ)
Sets the dimensions of the object.
Definition baseobject.h:343
virtual tResult SetColor(tFloat64 fRed, tFloat64 fGreen, tFloat64 fBlue, tFloat64 fAlpha)
Sets the color of the object.
Definition baseobject.h:378
virtual tResult SetPosition(tFloat64 fPosX, tFloat64 fPosY, tFloat64 fPosZ)
Sets the position of the object.
Definition baseobject.h:279
virtual tResult RemoveObject(tUInt32 nId)
Removes an object from the scene.
virtual tResult AddObject(cBaseObject *pObj)
Use this to add a new object to the scene.
virtual tResult RemoveInvalid()
Removes all objects that have not been updated since the last call.
virtual tResult GetObject(tUInt32 nId, cBaseObject **ppObj)
Retrieves an object.
Namespace for functionality provided by the Mixin Library.
Definition baseobject.h:26
#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;
} // namespace
#endif
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
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/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_VERSION_MAJOR,
DISPTB_VERSION_MINOR,
DISPTB_VERSION_PATCH,
cObjectMixin,
cDemoObjectFilter)
Namespace for functionality provided by the Display Toolbox.