I am still working on a “global” example architecture for a blog post; Trying to help people who are new to the engine get their feet wet with some boilerplate. I have run into a strange issue.
When I do:
this->GetContext()->RegisterSubsystem< Level >();
this->GetSubsystem< Level >()->Start();
everything works great. I get my level and my camera to zoom around with. It even prints “Level” like it should.
When I change it to:
this->GetContext()->RegisterSubsystem< Level >();
this->GetSubsystem< Level >()->Start();
this->GetContext()->RegisterSubsystem< Balls >();
this->GetSubsystem< Balls >()->Start();
I get:
u3da: /home/nick/Urho3D/build.linux/include/Urho3D/Audio/../Core/../Core/../Container/Ptr.h:133: T* Urho3D::SharedPtr<T>::operator->() const [with T = Urho3D::Scene]: Assertion `ptr_' failed.*
*Aborted (core dumped)
Level is defined as:
#pragma once
#include <iostream>
#include <Urho3D/Urho3DAll.h>
#include "constants.hpp"
class Level : public Urho3D::Component {
private:
#ifdef __DEBUG__
bool drawDebug_;
void HandlePostRenderUpdate( Urho3D::StringHash, Urho3D::VariantMap& );
#endif
Urho3D::SharedPtr< Urho3D::Scene > scene_;
Urho3D::SharedPtr< Urho3D::Node > cameraNode_;
Urho3D::SharedPtr< Urho3D::Node > terrainNode_;
public:
explicit Level( Urho3D::Context* context ) : Urho3D::Component( context ) {
#ifdef __DEBUG__
this->drawDebug_ = false;
#endif
};
virtual void Start( void );
virtual void Stop( void );
virtual void Update( Urho3D::StringHash, Urho3D::VariantMap& );
#ifdef __DEBUG__
void setDebug( const bool );
bool getDebug( void );
#endif
Urho3D::SharedPtr< Urho3D::Scene > getScene( void );
Urho3D::SharedPtr< Urho3D::Node > getCamera( void );
Urho3D::SharedPtr< Urho3D::Node > getTerrain( void );
void rotateCamera( const float, const float );
void moveCamera( const Urho3D::Vector3& );
};
#include <level.hpp>
#ifdef __DEBUG__
void Level::HandlePostRenderUpdate( Urho3D::StringHash eventType, Urho3D::VariantMap& eventData ) {
if ( this->drawDebug_ )
this->scene_->GetComponent< Urho3D::PhysicsWorld >()->DrawDebugGeometry( true );
};
#endif
void Level::Start( void ) {
std::cout << "Level" << std::endl;
this->scene_ = new Urho3D::Scene( this->GetContext() );
#ifdef __DEBUG__
this->scene_->CreateComponent< Urho3D::DebugRenderer >();
#endif
this->scene_->CreateComponent< Urho3D::Octree >();
auto* cache = this->GetSubsystem< Urho3D::ResourceCache >();
auto* physicsWorld = this->scene_->CreateComponent< Urho3D::PhysicsWorld >();
physicsWorld->SetGravity( Urho3D::Vector3( 0, WORLD_GRAVITY, 0 ) );
this->cameraNode_ = new Urho3D::Node( this->GetContext() );
this->cameraNode_->SetTransform( Urho3D::Vector3( 0.0f, 250.0f, 0.0f ), Urho3D::Quaternion( 90.0f, 0.0f, 0.0f ) );
auto* camera = this->cameraNode_->CreateComponent< Urho3D::Camera >();
camera->SetFarClip( 500.0f );
auto* zoneNode = this->scene_->CreateChild( "Zone" );
auto* zone = zoneNode->CreateComponent< Urho3D::Zone >();
zone->SetBoundingBox( Urho3D::BoundingBox( Urho3D::Sphere( Urho3D::Vector3::ZERO, 200 ) ) );
zone->SetAmbientColor( Urho3D::Color( 0.15f, 0.15f, 0.15f ) );
zone->SetFogColor( Urho3D::Color( 0.0f, 0.0f, 0.0f ) );
zone->SetFogStart( 400.0f );
zone->SetFogEnd( 500.0f );
auto* lightNode = this->scene_->CreateChild( "Light" );
lightNode->SetDirection( Urho3D::Vector3( 0.8f, -1.0f, 0.8f ) );
auto* light = lightNode->CreateComponent< Urho3D::Light >();
light->SetLightType( Urho3D::LIGHT_DIRECTIONAL );
light->SetCastShadows( true );
light->SetSpecularIntensity( 1.0f );
light->SetColor( Urho3D::Color( 1.0f, 1.0f, 1.0f ) );
auto* skyNode = this->scene_->CreateChild( "Sky" );
auto* skybox = skyNode->CreateComponent< Urho3D::Skybox >();
skybox->SetModel( cache->GetResource< Urho3D::Model >( "Models/Box.mdl" ) );
skybox->SetMaterial( cache->GetResource< Urho3D::Material >( "Materials/Skybox.xml" ) );
this->terrainNode_ = this->scene_->CreateChild( "Terrain" );
this->terrainNode_->SetPosition( Urho3D::Vector3::ZERO );
auto* terrain = this->terrainNode_->CreateComponent< Urho3D::Terrain >();
terrain->SetPatchSize( 32 );
terrain->SetSpacing( Urho3D::Vector3( 1.0f, 0.25f, 1.0f ) );
terrain->SetSmoothing( true );
terrain->SetHeightMap( cache->GetResource< Urho3D::Image >( "Textures/HeightMap.png" ) );
terrain->SetMaterial( cache->GetResource< Urho3D::Material >( "Materials/Terrain.xml" ) );
terrain->SetOccluder( true );
auto* rigidBody = this->terrainNode_->CreateComponent< Urho3D::RigidBody >();
rigidBody->SetFriction( 0.1f );
rigidBody->SetCollisionLayerAndMask( LayerFlagsTerrain, LayerFlagsPlayer );
auto* collisionShape = this->terrainNode_->CreateComponent< Urho3D::CollisionShape >();
collisionShape->SetTerrain();
auto* renderer = this->GetSubsystem< Urho3D::Renderer >();
Urho3D::SharedPtr< Urho3D::Viewport > viewport( new Urho3D::Viewport( this->GetContext(), this->scene_, this->cameraNode_->GetComponent< Urho3D::Camera >() ) );
renderer->SetViewport( 0, viewport );
#ifdef __DEBUG__
SubscribeToEvent( Urho3D::E_POSTRENDERUPDATE, URHO3D_HANDLER( Level, HandlePostRenderUpdate ) );
#endif
};
void Level::Stop( void ) {
#ifdef __DEBUG__
UnsubscribeFromEvent( Urho3D::E_POSTRENDERUPDATE );
#endif
};
void Level::Update( Urho3D::StringHash eventType, Urho3D::VariantMap& eventData ) {};
#ifdef __DEBUG__
void Level::setDebug( bool enable ) {
this->drawDebug_ = enable;
};
bool Level::getDebug( void ) {
return this->drawDebug_;
};
#endif
Urho3D::SharedPtr< Urho3D::Scene > Level::getScene( void ) {
return this->scene_;
};
Urho3D::SharedPtr< Urho3D::Node > Level::getCamera( void ) {
return this->cameraNode_;
};
Urho3D::SharedPtr< Urho3D::Node > Level::getTerrain( void ) {
return this->terrainNode_;
};
void Level::rotateCamera( const float pitch, const float yaw ) {
this->cameraNode_->SetRotation( Urho3D::Quaternion( pitch, yaw, 0.0f ) );
};
void Level::moveCamera( const Urho3D::Vector3& vector3 ) {
this->cameraNode_->Translate( vector3 );
};
Balls is define as:
#pragma once
#include <iostream>
#include <Urho3D/Urho3DAll.h>
#include "constants.hpp"
#include "level.hpp"
class Balls : public Urho3D::Component {
private:
Urho3D::SharedPtr< Urho3D::Node > balls_[ BALLS_COUNT ];
void HandleObjectCollisionStart( Urho3D::StringHash eventType, Urho3D::VariantMap& eventData );
public:
explicit Balls( Urho3D::Context* context ) : Urho3D::Component( context ) {};
virtual void Start( void );
};
#include <balls.hpp>
void Balls::HandleObjectCollisionStart( Urho3D::StringHash eventType, Urho3D::VariantMap& eventData ) {
auto* rigidBody1 = static_cast< Urho3D::RigidBody* >( eventData[ Urho3D::NodeCollisionStart::P_BODY ].GetPtr() );
auto* node1 = rigidBody1->GetNode();
const auto name1 = node1->GetName();
auto* rigidBody2 = static_cast< Urho3D::RigidBody* >( eventData[ Urho3D::NodeCollisionStart::P_OTHERBODY ].GetPtr() );
auto* node2 = rigidBody2->GetNode();
const auto name2 = node2->GetName();
if ( name2 == "Player" ) {
UnsubscribeFromEvent( node1, Urho3D::E_NODECOLLISIONSTART );
node1->Remove();
}
};
void Balls::Start( void ) {
std::cout << "Balls" << std::endl;
for ( short int i = 0 ; i < BALLS_COUNT ; i++ ) {
auto* cache = this->GetSubsystem< Urho3D::ResourceCache >();
auto* level = this->GetSubsystem< Level >();
this->balls_[ i ] = level->getScene()->CreateChild( "Ball" );
const auto& ball = this->balls_[ i ];
Urho3D::Vector3 position( Urho3D::Random( -50, 50 + 1 ), 0.0f, Urho3D::Random( -50, 50 + 1 ) );
position.y_ = level->getTerrain()->GetComponent< Urho3D::Terrain >()->GetHeight( position ) + 10.0f;
ball->SetPosition( position );
ball->SetScale( Urho3D::Vector3( 10.0f, 10.0f, 10.0f ) );
auto* object = ball->CreateComponent< Urho3D::StaticModel >();
object->SetModel( cache->GetResource< Urho3D::Model >( "Models/Sphere.mdl" ) );
object->SetMaterial( cache->GetResource< Urho3D::Material >( "Materials/Stone.xml" ) );
object->SetCastShadows( true );
auto* rigidBody = ball->CreateComponent< Urho3D::RigidBody >();
rigidBody->SetMass( 1.0f );
rigidBody->SetFriction( 0.1f );
rigidBody->SetCollisionLayerAndMask( LayerFlagsBall, LayerFlagsTerrain | LayerFlagsPlayer );
auto* collisionShape = ball->CreateComponent< Urho3D::CollisionShape >();
collisionShape->SetSphere( 1, Urho3D::Vector3( 0, .5, 0 ) );
SubscribeToEvent( ball, Urho3D::E_NODECOLLISIONSTART, URHO3D_HANDLER( Balls, HandleObjectCollisionStart ) );
}
};
I can not find where this issue is. It prints “Level” and “Balls” but then crashes. Even if I comment out the function bodies (except the cout
) in Balls it still crashes but now with
u3da: /home/nick/Urho3D/build.linux/include/Urho3D/Audio/../Core/../Core/../Container/Ptr.h:133: T* Urho3D::SharedPtr<T>::operator->() const [with T = Urho3D::Node]: Assertion `ptr_' failed.*
*Aborted (core dumped)
What am I missing?
Maybe there is the possibility of turning this into a Sample one day in the future (after a lot of work and some convention changes.)