This page has been translated automatically.
视频教程
界面
要领
高级
实用建议
UnigineEditor
界面概述
资产工作流程
设置和首选项
项目开发
调整节点参数
Setting Up Materials
Setting Up Properties
照明
Landscape Tool
Sandworm
使用编辑器工具执行特定任务
Extending Editor Functionality
嵌入式节点类型
Nodes
Objects
Effects
Decals
Light Sources
Geodetics
World Objects
Sound Objects
Pathfinding Objects
Players
编程
基本原理
搭建开发环境
Usage Examples
UnigineScript
C++
C#
UUSL (Unified UNIGINE Shader Language)
File Formats
Rebuilding the Engine Tools
GUI
双精度坐标
应用程序接口
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
注意! 这个版本的文档是过时的,因为它描述了一个较老的SDK版本!请切换到最新SDK版本的文档。
注意! 这个版本的文档描述了一个不再受支持的旧SDK版本!请升级到最新的SDK版本。

6. Managing Existing Scene Objects

<< RETURN TO THE PREVIOUS SECTION

Not all content in the world is created at runtime, so we should be able to operate with nodes that already exist. How do we get pointers to existing objects in order to manage them? This is where the World class comes into play again. Basically, there are two ways we can get a pointer to a certain node using the methods of the World class:

Notice
In order to be able to use the methods of the World class we must include the UnigineWorld.h library.

These methods return a NodePtr value, which is a pointer to the base class, but in order to perform operations with a certain object (e.g. ObjectMeshDynamicPtr) we need to perform downcasting (i.e. convert from a pointer-to-base to a pointer-to-derived).

Sometimes you may also need to perform upcasting (i.e. convert from a pointer-to-derived to a pointer-to-base), in this case you can use the derived class itself. The code below demonstrates the points described above.

Source code (C++)
#include <UnigineWorld.h>
using namespace Unigine;
/* .. */

// find a pointer to node by a given name
NodePtr baseptr = World::getNodeByName("my_meshdynamic");

// cast a pointer-to-derived from pointer-to-base with automatic type checking
ObjectMeshDynamicPtr derivedptr = checked_ptr_cast<ObjectMeshDynamic>(baseptr);

// static cast (pointer-to-derived from pointer-to-base)
ObjectMeshDynamicPtr derivedptr = static_ptr_cast<ObjectMeshDynamic>(World::getNodeByName("my_meshdynamic"));

// upcast to the pointer to the Object class which is a base class for ObjectMeshDynamic
ObjectPtr object = derivedptr;

// upcast to the pointer to the Node class which is a base class for all scene objects
NodePtr node = derivedptr;

Additional information:

Project Progress#

Now that we've learned how to access existing nodes, let us write a method that removes an object with a given name from the scene and call it removeMeshFromScene. We are also going to write a method called removeObjects to remove all created objects on world shutdown.

In the AppWorldLogic.h file, we add our removeMeshFromScene and removeObjects methods.

Source code (C++)
// AppWorldLogic.h

/* .. */

class AppWorldLogic : public Unigine::WorldLogic {
	
public:

/* .. */

private:

/* .. */

	int removeMeshFromScene(const char *node_name);
	int removeObjects();

/* .. */


};

In the AppWorldLogic.cpp file let us implement our removeMeshFromScene and removeObjects methods and insert the latter to the AppWorldLogic::shutdown() method.

Source code (C++)
// AppWorldLogic.cpp

/* .. */

/// method deleting a Dynamic Mesh Object with a given name from the scene
int AppWorldLogic::removeMeshFromScene(const char *node_name)
{
	// getting a pointer to the node with a given name and downcasting it to ObjectMeshDynamicPtr
	ObjectMeshDynamicPtr object = checked_ptr_cast<ObjectMeshDynamic>(World::getNodeByName(node_name));

	if (object)
	{
		// reporting node deletion to the console
		Log::message("Removing %s node named %s from the scene.\n", object->getTypeName(), node_name);

		// removing the node with a given name from the list of scene objects
		
		for (int i = 0; i < Objects.size();i++)
		{
			if (strcmp(Objects[i]->getName(), node_name) == 0) {
				Objects.remove(i);
				break;
			}
		}
		
		// removing the node from the scene
		object.deleteLater();
		
		return 1;
	}

	return 0;
}

/// method removing all created objects from the scene
int AppWorldLogic::removeObjects()
{

	while (Objects.size() > 0)
	{
		removeMeshFromScene(Objects.begin()->get()->getName());
	}
	
	return 1;
}

/* .. */
int AppWorldLogic::shutdown()
{

	// removing all created objects
	removeObjects();
}
/* .. */

Source Files

You can copy the code below and paste it to the corresponding source files of your project:

AppWorldLogic.h

Source code (C++)
#ifndef __APP_WORLD_LOGIC_H__
#define __APP_WORLD_LOGIC_H__

#include <UnigineLogic.h>
#include <UnigineStreams.h>
#include <UnigineObjects.h>
#include <UnigineGame.h>
#include <UnigineLights.h>
#include <UnigineMaterials.h>
#include <UnigineWorld.h>

using namespace Unigine;

class AppWorldLogic : public WorldLogic {
	
public:
	AppWorldLogic();
	virtual ~AppWorldLogic();
	
	virtual int init();
	
	virtual int update();
	virtual int postUpdate();
	virtual int updatePhysics();
	
	virtual int shutdown();
	
	virtual int save(const StreamPtr &stream);
	virtual int restore(const StreamPtr &stream);
private:
	PlayerSpectatorPtr player;

	// pointers to light sources
	LightWorldPtr thesun;
	LightOmniPtr light_omni;
	LightProjPtr projector;

	// auxiliary functions
	int addMeshToScene(const char *file_name, const char *mesh_name, const char *material_name, Math::Vec3 position);
	int removeMeshFromScene(const char *node_name);

	// initialization functions
	int initObjects();
	int initPlayer();
	int initLights();
	int initMaterials();

	// shutdown functions
	int clearMaterials();
	int removeObjects();

	// scene objects vector
	Vector <ObjectMeshDynamicPtr> Objects;
};

#endif // __APP_WORLD_LOGIC_H__

AppWorldLogic.cpp

Source code (C++)
#include "AppWorldLogic.h"
// World logic, it takes effect only when the world is loaded.
// These methods are called right after corresponding world script's (UnigineScript) methods.
//-----------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------- AUXILIARY FUNCTIONS AND METHODS ----------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------

/// method adding a Dynamic Mesh Object to the scene. If an empty filename is passed the method creates a default box; otherwise, loads a mesh-file with a given name.
int AppWorldLogic::addMeshToScene(const char *file_name, const char *mesh_name, const char *material_name, Math::Vec3 position)
{
	MeshPtr mesh = Mesh::create();
	ObjectMeshDynamicPtr omd;
	if (file_name) {				// loading a mesh from a specified file
		if (!mesh->load(file_name))
		{
			Log::error("\nError opening .mesh file!\n");
			mesh.clear();

			return 0;
		}
		else omd = ObjectMeshDynamic::create(mesh);
	}
	else						// creating a default box
	{
		mesh->addBoxSurface("box_surface", Math::vec3(0.5f));

		omd = ObjectMeshDynamic::create(mesh);
	}

	// setting node material, name and position
	omd->setMaterial(material_name, "*");
	omd->setName(mesh_name);
	omd->setWorldPosition(position);

	// updating the list of scene objects
	Objects.append(omd);

	// reporting progress to the console
	Log::message("-> Object %s added to the scene.\n", mesh_name);

	// clearing the mesh
	mesh.clear();

	return 1;

}
//-----------------------------------------------------------------------------------------------------------------------------
/// method deleting a Dynamic Mesh Object with a given name from the scene
int AppWorldLogic::removeMeshFromScene(const char *node_name)
{
	// getting a pointer to the node with a given name and downcasting it to ObjectMeshDynamicPtr
	ObjectMeshDynamicPtr object = checked_ptr_cast<ObjectMeshDynamic>(World::getNodeByName(node_name));

	if (object)
	{
		// reporting node deletion to the console
		Log::message("Removing %s node named %s from the scene.\n", object->getTypeName(), node_name);

		// removing the node with a given name from the list of scene objects

		for (int i = 0; i < Objects.size(); i++)
		{
			if (strcmp(Objects[i]->getName(), node_name) == 0) {
				Objects.remove(i);
				break;
			}
		}

		// removing the node from the scene
		object->deleteLater();

		return 1;
	}

	return 0;
}
//-----------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------- INITIALIZATION METHODS -------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------
/// method performing initialization of the set of 4 boxes
int AppWorldLogic::initObjects()
{
	int index = 0;

	for (int x = 0; x < 2; x++)
	{
		for (int y = 0; y < 2; y++)
		{
			addMeshToScene(NULL, String::format("my_meshdynamic_%d", index), String::format("my_mesh_base%d", index), Math::Vec3(x, y, 1.0f));
			index++;
		}
	}

	// reporting progress to the console
	Log::warning("Objects generation OK!\n\n");

	return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
/// method performing initialization of the player
int AppWorldLogic::initPlayer()
{
	// creating a new PlayerSpectator instance
	player = PlayerSpectator::create();

	// setting player's FOV, ZNear, ZFar
	player->setFov(90.0f);
	player->setZNear(0.1f);
	player->setZFar(10000.0f);

	// setting player's view direction vector and position
	player->setPosition(Math::Vec3(3.0f));
	player->setDirection(Math::vec3(-1.0f), Math::vec3(0.0f, 0.0f, -1.0f));

	// setting the player as a default one via the Game singleton instance
	Game::setPlayer(player);

	//reporting progress to the console
	Log::warning("\nPlayer initialization OK!\n\n");

	return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
/// method performing initialization of lights
int AppWorldLogic::initLights()
{
	// creating an omni light and setting up its parameters
	light_omni = LightOmni::create(Math::vec4(1.0f, 1.0f, 1.0f, 1.0f), 10.0f, "");
	light_omni->setWorldPosition(Math::Vec3(0.0f, 0.0f, 5.0f));
	light_omni->setIntensity(0.1f);

	// reporting progress to the console
	Log::message("-> Created a %s light source.\n", light_omni->getName());

	// creating a world light and setting up its parameters
	thesun = LightWorld::create(Math::vec4(1.0f, 1.0f, 1.0f, 1.0f));
	thesun->setName("Sun");
	thesun->setDisableAngle(90.0f);
	thesun->setIntensity(1.0f);
	thesun->setScattering(LightWorld::SCATTERING_SUN);
	thesun->setWorldRotation(Math::quat(86.0f, 30.0f, 300.0f));

	// reporting progress to the console
	Log::message("-> Created a %s light source.\n", thesun->getName());

	// creating a proj light and setting up its parameters
	projector = LightProj::create(Math::vec4(1.0f, 1.0f, 0.5f, 1.0f), 10.0f, 60.0f, "");
	projector->setWorldPosition(Math::Vec3(2.5f, 2.5f, 3.0f));
	projector->setName("projector");
	projector->setRotation(Math::quat(-45.0f, 45.0f, 0.0f));
	projector->setPenumbra(0.425f);
	projector->setIntensity(1.0f);

	// reporting progress to the console
	Log::message("-> Created a %s light source.\n", projector->getName());
	Log::warning("Lights initialization OK!\n");

	return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
/// method performing initialization of materials
int AppWorldLogic::initMaterials()
{
	// creating a new child material of the mesh_base and setting its color
	MaterialPtr mesh_base = Materials::findMaterial("mesh_base");
	MaterialPtr my_mesh_base = mesh_base->inherit("my_mesh_base0");
	my_mesh_base->setParameterFloat4("albedo_color", Math::vec4(255, 0, 0, 255));

	// reporting progress to the console
	Log::message("\n-> Generated %s material.\n", my_mesh_base->getName());

	// creating a new child material of the mesh_base and setting its color
	my_mesh_base = mesh_base->inherit("my_mesh_base1");
	my_mesh_base->setParameterFloat4("albedo_color", Math::vec4(0, 255, 0, 255));

	// reporting progress to the console
	Log::message("-> Generated %s material.\n", my_mesh_base->getName());

	//creating a new child material of the mesh_base and setting its color
	my_mesh_base = mesh_base->inherit("my_mesh_base2");
	my_mesh_base->setParameterFloat4("albedo_color", Math::vec4(0, 0, 255, 255));

	// reporting progress to the console
	Log::message("-> Generated %s material.\n", my_mesh_base->getName());

	//creating a new child material of the mesh_base and setting its color
	my_mesh_base = mesh_base->inherit("my_mesh_base3");
	my_mesh_base->setParameterFloat4("albedo_color", Math::vec4(255, 255, 0, 255));

	// reporting progress to the console
	Log::message("-> Generated %s material.\n", my_mesh_base->getName());
	Log::warning("Material generation OK!\n\n");


	my_mesh_base.clear();

	return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------- SHUTDOWN METHODS -------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------
/// method removing all created materials
int AppWorldLogic::clearMaterials()
{
	Materials::removeMaterial(Materials::findMaterial("my_mesh_base0")->getGUID());
	Materials::removeMaterial(Materials::findMaterial("my_mesh_base1")->getGUID());
	Materials::removeMaterial(Materials::findMaterial("my_mesh_base2")->getGUID());
	Materials::removeMaterial(Materials::findMaterial("my_mesh_base3")->getGUID());

	return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
/// method removing all  created objects
int AppWorldLogic::removeObjects()
{
	while (Objects.size() > 0)
	{
		removeMeshFromScene(Objects.begin()->get()->getName());
	}

	return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
AppWorldLogic::AppWorldLogic() {

}

AppWorldLogic::~AppWorldLogic() {

}

int AppWorldLogic::init() {
	// Write here code to be called on world initialization: initialize resources for your world scene during the world start.

	// creating materials
	initMaterials();

	// creating objects
	initObjects();

	// creating a player
	initPlayer();

	// creating lights
	initLights();

	return 1;
}

// start of the main loop
int AppWorldLogic::update() {
	// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.

	return 1;
}

int AppWorldLogic::postUpdate() {
	// The engine calls this function before rendering each render frame: correct behavior after the state of the node has been updated.

	return 1;
}

int AppWorldLogic::updatePhysics() {
	// Write here code to be called before updating each physics frame: control physics in your application and put non-rendering calculations.
	// The engine calls updatePhysics() with the fixed rate (60 times per second by default) regardless of the FPS value.
	// WARNING: do not create, delete or change transformations of nodes here, because rendering is already in progress.

	return 1;
}
// end of the main loop

int AppWorldLogic::shutdown() {
	// Write here code to be called on world shutdown: delete resources that were created during world script execution to avoid memory leaks.

		// deleting all created nodes
	removeObjects();

	// clearing the player pointer
	player->deleteLater();

	// clearing light sources
	thesun->deleteLater();
	light_omni->deleteLater();
	projector->deleteLater();

	// clearing all created materials
	clearMaterials();

	return 1;
}

int AppWorldLogic::save(const StreamPtr &stream) {
	// Write here code to be called when the world is saving its state (i.e. state_save is called): save custom user data to a file.

	UNIGINE_UNUSED(stream);
	return 1;
}

int AppWorldLogic::restore(const StreamPtr &stream) {
	// Write here code to be called when the world is restoring its state (i.e. state_restore is called): restore custom user data to a file here.

	UNIGINE_UNUSED(stream);
	return 1;
}


PROCEED TO THE NEXT SECTION >>

Last update: 2021-04-09
Build: ()