Context:
I'm creating some Actors (Shields) using C++ in ActorComponent (ShieldComponent) which is attached to Actor (Ship).
When I move my Ship, Actors (Shields) stay in place on world (don't move with Ship).
What can be important: I don't call CreateShieldActor in Constructor, so I can't use ConstructorHelpers::FObjectFinder instead of StaticLoadObject/LoadObject to load Mesh/Material.
My C++ code for creation looks like this:
AShieldPart* UShieldComponent::CreateShieldActor(AActor* Owner, FString MeshName)
{
//Create Shield Actor
FVector Location = Owner->GetActorLocation();
FRotator Rotator(0, 0, 0);
FVector Scale(10, 10, 10);
FActorSpawnParameters SpawnInfo;
SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
SpawnInfo.Owner = Owner;
FTransform Transform(Rotator, Location, Scale);
UClass * MeshClass = AShieldPart::StaticClass();
AShieldPart* ShieldPart = GetWorld()->SpawnActor<AShieldPart>(MeshClass, Transform, SpawnInfo);
//Attach Mesh to Shield Actor
ShieldPart->AttachToActor(Owner, FAttachmentTransformRules(EAttachmentRule::KeepRelative, false));
//Set Mesh for Shield
ShieldPart->SetNewMesh(MeshName);
//Set Material
UMaterial* Material = Cast<UMaterial>(StaticLoadObject(UMaterial::StaticClass(), NULL, TEXT("/some/path")));
ShieldPart->MeshComponent->SetMaterial(0, Material);
return ShieldPart;
}
AShieldPart::AShieldPart()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
SetRootComponent(RootComponent);
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(RootComponent);
}
void AShieldPart::SetNewMesh(FString MeshName)
{
UStaticMesh* Mesh = Cast<UStaticMesh>(StaticLoadObject(UStaticMesh::StaticClass(), NULL, *MeshName));
//UStaticMesh* Mesh = LoadObject<UStaticMesh>(nullptr, *MeshName);
MeshComponent->SetStaticMesh(Mesh);
MeshComponent->SetCollisionProfileName(TEXT("BlockAll"));
MeshComponent->SetNotifyRigidBodyCollision(true);
MeshComponent->SetSimulatePhysics(true);
MeshComponent->SetEnableGravity(false);
MeshComponent->RegisterComponent();
}
That it would be more interesting, when I create that Actors (Shields) using BP all works fine...
The solution turned out to be eliminating the USceneComponent as a RootElement. The main element must be UStaticMeshComponent, then it can attached to the parent element (Ship).
AShieldPart::AShieldPart()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Creating MeshComponent and attach to RootComponent
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
RootComponent = MeshComponent;
MeshComponent->AttachToComponent(RootComponent, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true));
...
Related
I'm doing a simple paddle game with Blueprints at first and C++ after.
I have the current workflow in my blueprint game mode:
And this is my code base on:
void APaddleGameGameMode::SpawnBall()
{
UWorld *world = GetWorld();
if (world)
{
Ref_GameBall = world->SpawnActorDeferred<APaddleGameBall>(APaddleGameBall::StaticClass(), FTransform(FRotator::ZeroRotator, FVector::ZeroVector, FVector::OneVector), NULL, NULL, ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding);
if (Ref_GameBall) world->GetTimerManager().SetTimer(DelayBallMovement, this, &APaddleGameGameMode::SetVelocity, 0.2f);
}
}
void APaddleGameGameMode::SetVelocity()
{
if(Ref_GameBall) Ref_GameBall->ProjectileMovement->Velocity = FVector(Direction * Speed, 0.f, 0.f).RotateAngleAxis(FMath::RandRange(-45.f, 45.f), FVector(0.f, 1.f, 0.f));
Ref_GameBall->ProjectileMovement->Activate();
}
The problem here is, every time the player make a point, the ball is destroyed and a new ball is spawned:
void APaddleGameGameMode::UpdateScore(bool bIsAI)
{
UWorld *world = GetWorld();
if (bIsAI)
{
SPScore++;
Direction = 1.f;
}
else
{
FPScore++;
Direction = -1.f;
}
if (world) world->GetTimerManager().SetTimer(DelaySpawningBall, this, &APaddleGameGameMode::SpawnBall, 1.f);
}
It works fine at the first, the initial, spawnin: ball is spawned and it takes movement; but it does not work at the second spawn, i don't understand why, the ball is spawned but it does not move.
Can anyone to explain me it and help me to solve it?
Thanks.
SpawnActorDeferred function defers the BeginPlay, giving a opportunity to the caller to set parameters beforehand, it means, the spawned actor if in a half-way to being full constructed(is a half actor) until the FinishSpawningActor function is called, wherever it is put; it means, a valid actor instance that didn't receive BeginPlay yet and so it is not fully initialized.
Here, Ref_GameBall ->FinishSpawning( Transform ) can be put before to activate the projectile movement, or replacing SpawnActorDeferred by SpawnActor:
FActorSpawnParameters SpawnParameters;
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
Ref_GameBall = world->SpawnActor<APaddleGameBall>(APaddleGameBall::StaticClass(), FTransform(FRotator::ZeroRotator, FVector::ZeroVector, FVector::OneVector), SpawnParameters);
That's all
Thanks to #KnownBugg, from Discord, to help me with this.
I am up to section 3.2 of the fps tutorial on unreal engine 4. In this section I'm supposed to implement shooting into the code via the fire function so that i can shoot projectiles in-game. However, after typing the code the tutorial provided, I got one error when compiling it. The error is as follows
/Users/apple/Documents/Unreal Projects/FPSProject/Source/FPSProject/FPSCharacter.cpp:120:38: 'Instigator' is a private member of 'AActor'
When I remove this line and compile the code it does so successfully, but when I test it out on unreal, I can't shoot projectiles at all.
Here is the code
FPSCharacter.cpp
include "FPSCharacter.h"
include "FPSProject.h" #include "FPSCharacter.generated.h" #include "FPSProjectile.h" #include "GameFramework/Actor.h"
// Sets default values AFPSCharacter::AFPSCharacter() { // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;
// Create a first person camera component.
FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
// Attach the camera component to our capsule component.
FPSCameraComponent->SetupAttachment(GetCapsuleComponent());
// Position the camera slightly above the eyes.
FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
// Allow the pawn to control camera rotation.
FPSCameraComponent->bUsePawnControlRotation = true;
// Create a first person mesh component for the owning player.
FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh"));
// Only the owning player sees this mesh.
FPSMesh->SetOnlyOwnerSee(true);
// Attach the FPS mesh to the FPS camera.
FPSMesh->SetupAttachment(FPSCameraComponent);
// Disable some environmental shadowing to preserve the illusion of having a single mesh.
FPSMesh->bCastDynamicShadow = false;
FPSMesh->CastShadow = false;
// The owning player doesn't see the regular (third-person) body mesh.
GetMesh()->SetOwnerNoSee(true);
}
// Called when the game starts or when spawned void AFPSCharacter::BeginPlay() { Super::BeginPlay();
if (GEngine)
{
// Put up a debug message for five seconds. The -1 "Key" value (first argument) indicates that we will never need to update or refresh this message.
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
}
}
// Called every frame void AFPSCharacter::Tick( float DeltaTime ) { Super::Tick( DeltaTime );
}
// Called to bind functionality to input void AFPSCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent);
// Set up "movement" bindings.
PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);
// Set up "look" bindings.
PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);
// Set up "action" bindings.
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire);
}
void AFPSCharacter::MoveForward(float Value) { // Find out which way is "forward" and record that the player wants to move that way. FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X); AddMovementInput(Direction, Value); }
void AFPSCharacter::MoveRight(float Value) { // Find out which way is "right" and record that the player wants to move that way. FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y); AddMovementInput(Direction, Value); }
void AFPSCharacter::StartJump() { bPressedJump = true; }
void AFPSCharacter::StopJump() { bPressedJump = false; }
void AFPSCharacter::Fire() { // Attempt to fire a projectile. if (ProjectileClass) { // Get the camera transform. FVector CameraLocation; FRotator CameraRotation; GetActorEyesViewPoint(CameraLocation, CameraRotation);
// Transform MuzzleOffset from camera space to world space.
FVector MuzzleLocation = CameraLocation + FTransform(CameraRotation).TransformVector(MuzzleOffset);
FRotator MuzzleRotation = CameraRotation;
// Skew the aim to be slightly upwards.
MuzzleRotation.Pitch += 10.0f;
UWorld* World = GetWorld();
if (World)
{
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
SpawnParams.Instigator = Instigator;
// Spawn the projectile at the muzzle.
AFPSProjectile* Projectile = World->SpawnActor<AFPSProjectile>(ProjectileClass, MuzzleLocation, MuzzleRotation, SpawnParams);
if (Projectile)
{
// Set the projectile's initial trajectory.
FVector LaunchDirection = MuzzleRotation.Vector();
Projectile->FireInDirection(LaunchDirection);
}
}
}
}
I am a newbie with gameplay3d and went through all tutorials, however I cant manage to display this simple(not much polygons and material) model that I encoded from Fbx. I checked the model with unity3D, and a closed source software that uses gameplay3d and all seems to fine. I guess I am missing some detail loading the scene.
This is the model file including also the original fbx file. I suspect if it has something to do with light
https://www.dropbox.com/sh/ohgpsfnkm3iv24s/AACApRcxwtbmpKu4_5nnp8rZa?dl=0
This is the class that loads the scene.
#include "Demo.h"
// Declare our game instance
Demo game;
Demo::Demo()
: _scene(NULL), _wireframe(false)
{
}
void Demo::initialize()
{
// Load game scene from file
Bundle* bundle = Bundle::create("KGN56AI30N.gpb");
_scene = bundle->loadScene();
SAFE_RELEASE(bundle);
// Get the box model and initialize its material parameter values and bindings
Camera* camera = Camera::createPerspective(45.0f, getAspectRatio(), 1.0f, 20.0f);
Node* cameraNode = _scene->addNode("camera");
// Attach the camera to a node. This determines the position of the camera.
cameraNode->setCamera(camera);
// Make this the active camera of the scene.
_scene->setActiveCamera(camera);
SAFE_RELEASE(camera);
// Move the camera to look at the origin.
cameraNode->translate(0,0, 10);
cameraNode->rotateX(MATH_DEG_TO_RAD(0.25f));
// Update the aspect ratio for our scene's camera to match the current device resolution
_scene->getActiveCamera()->setAspectRatio(getAspectRatio());
// Set the aspect ratio for the scene's camera to match the current resolution
_scene->getActiveCamera()->setAspectRatio(getAspectRatio());
Light* directionalLight = Light::createDirectional(Vector3::one());
_directionalLightNode = Node::create("directionalLight");
_directionalLightNode->setLight(directionalLight);
SAFE_RELEASE(directionalLight);
_scene->addNode(_directionalLightNode);
_scene->setAmbientColor(1.0, 1.0, 1.0);
_scene->visit(this, &Demo::initializeMaterials);
}
bool Demo::initializeMaterials(Node* node)
{
Model* model = dynamic_cast<Model*>(node->getDrawable());
if (model)
{
for(int i=0;i<model->getMeshPartCount();i++)
{
Material* material = model->getMaterial(i);
if(material)
{
// For this sample we will only bind a single light to each object in the scene.
MaterialParameter* colorParam = material->getParameter("u_directionalLightColor[0]");
colorParam->setValue(Vector3(0.75f, 0.75f, 0.75f));
MaterialParameter* directionParam = material->getParameter("u_directionalLightDirection[0]");
directionParam->setValue(Vector3(1, 1, 1));
}
}
}
return true;
}
void Demo::finalize()
{
SAFE_RELEASE(_scene);
}
void Demo::update(float elapsedTime)
{
// Rotate model
//_scene->findNode("box")->rotateY(MATH_DEG_TO_RAD((float)elapsedTime / 1000.0f * 180.0f));
}
void Demo::render(float elapsedTime)
{
// Clear the color and depth buffers
clear(CLEAR_COLOR_DEPTH, Vector4::zero(), 1.0f, 0);
// Visit all the nodes in the scene for drawing
_scene->visit(this, &Demo::drawScene);
}
bool Demo::drawScene(Node* node)
{
// If the node visited contains a drawable object, draw it
Drawable* drawable = node->getDrawable();
if (drawable)
drawable->draw(_wireframe);
return true;
}
void Demo::keyEvent(Keyboard::KeyEvent evt, int key)
{
if (evt == Keyboard::KEY_PRESS)
{
switch (key)
{
case Keyboard::KEY_ESCAPE:
exit();
break;
}
}
}
void Demo::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
{
switch (evt)
{
case Touch::TOUCH_PRESS:
_wireframe = !_wireframe;
break;
case Touch::TOUCH_RELEASE:
break;
case Touch::TOUCH_MOVE:
break;
};
}
I can't download your dropbox .fbx file. How many models do you have in the scene? Here's a simple way of doing what you want to do -- not optimal, but it'll get you started...
So first off, I can't see where in your code you actually assign a Shader to be used with the material. I use something like this:
material = model->setMaterial("Shaders/Animation/ADSVertexViewAnim.vsh", "Shaders/Animation/ADSVertexViewAnim.fsh");
You need to assign a Shader, and the above code will take the vertex and fragment shaders and use that when the object needs to be drawn.
I went about it a slightly different way by not loading the scene file automatically, but creating an empty scene and then extracting my model from the bundle and adding it to the scene manually. That way, I can see exactly what is happening and I'm in control of each step. GamePlay3D has some fancy property files, but use them only once you know how the process works manually..
Initially, I created a simple cube in a scene, and created a scene manually, and added the monkey to the node graph, as follows:
void GameMain::ExtractFromBundle()
{
/// Create a new empty scene.
_scene = Scene::create();
// Create the Model and its Node
Bundle* bundle = Bundle::create("res/monkey.gpb"); // Create the bundle from GPB file
/// Create the Cube
{
Mesh* meshMonkey = bundle->loadMesh("Character_Mesh"); // Load the mesh from the bundle
Model* modelMonkey = Model::create(meshMonkey);
Node* nodeMonkey = _scene->addNode("Monkey");
nodeMonkey->setTranslation(0,0,0);
nodeMonkey->setDrawable(modelMonkey);
}
}
Then I want to search the scene graph and only assign a material to the object that I want to draw (the monkey). Use this if you want to assign different materials to different objects manually...
bool GameMain::initializeScene(Node* node)
{
Material* material;
std::cout << node->getId() << std::endl;
// find the node in the scene
if (strcmp(node->getId(), "Monkey") != 0)
return false;
Model* model = dynamic_cast<Model*>(node->getDrawable());
if( !model )
return false;
material = model->setMaterial("Shaders/Animation/ADSVertexViewAnim.vsh", "Shaders/Animation/ADSVertexViewAnim.fsh");
material->getStateBlock()->setCullFace(true);
material->getStateBlock()->setDepthTest(true);
material->getStateBlock()->setDepthWrite(true);
// The World-View-Projection Matrix is needed to be able to see view the 3D world thru the camera
material->setParameterAutoBinding("u_worldViewProjectionMatrix", "WORLD_VIEW_PROJECTION_MATRIX");
// This matrix is necessary to calculate normals properly, but the WORLD_MATRIX would also work
material->setParameterAutoBinding("u_worldViewMatrix", "WORLD_VIEW_MATRIX");
material->setParameterAutoBinding("u_viewMatrix", "VIEW_MATRIX");
return true;
}
Now the object is ready to be drawn.... so I use these functions:
void GameMain::render(float elapsedTime)
{
// Clear the color and depth buffers
clear(CLEAR_COLOR_DEPTH, Vector4(0.0, 0.0, 0.0, 0.0), 1.0f, 0);
// Visit all the nodes in the scene for drawing
_scene->visit(this, &GameMain::drawScene);
}
bool GameMain::drawScene(Node* node)
{
// If the node visited contains a drawable object, draw it
Drawable* drawable = node->getDrawable();
if (drawable)
drawable->draw(_wireframe);
return true;
}
I use my own shaders, so I don't have to worry about Light and DirectionalLight and all that stuff. Once I can see the object, then I'll add dynamic lights, etc, but for starters, start simple.
Regards.
I am making a cocos 2dx game. But each time the memory increases with every level transition. For debugging purposes I am calling the same scene again and again on touch event. Each level is generated by changing the parameters for the folowing code. Initially I thought that the memory was increasing because there were more objects in the higher levels, but even when calling the same level, memory occupied is increasing.
#include "GameScene.h"
#include "MainMenuScene.h"
#include "GameOverScene.h"
#include "Levels.h"
#define COCOS2D_DEBUG 1
USING_NS_CC;
float theta=0;
int r=0;
int levelNo=0;
int controlable=0; // flag to check if user can controll the ball or not
int rMax=0; // max radius of circle
float objectTime; // stores the inverse of speed
int secondCount=0; // second han value in the timer
int minuteCount=0; //minute hand clock in the timer
float obstacleSpeed=0;
Label *timer;
GameScene::~GameScene()
{
rotationPoint->removeAllChildrenWithCleanup(true);
obstacleRotationPoint->removeAllChildrenWithCleanup(true);
this->removeAllChildrenWithCleanup(true);
}
Scene* GameScene::createScene(int level)
{
// 'scene' is an autorelease object
auto scene = Scene::create();
controlable=0;
r=0;
theta=0;
// 'layer' is an autorelease object
levelNo=level;
rMax=levels[levelNo].ringCount * 15; //setting various parameters
obstacleSpeed =levels[levelNo].obstacleSpeed;
objectTime=1.0/levels[levelNo].speed;
secondCount=0; minuteCount=0;
auto layer = GameScene::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool GameScene::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
controlable=0;
distance=rMax;
visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
#if COMPILE_FOR_MOBILE == 1
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
#endif
goal = DrawNode::create();
goal->drawDot(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y), 5, Color4F(100,0,0,1));
this->addChild(goal,1); // drawing the goal
rotationPoint = Node::create();
rotationPoint->setPosition(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y);
this->addChild(rotationPoint, 2);
//Setting the exit button
auto exitLabel = Label::createWithTTF("Exit","fonts/Marker Felt.ttf",10);
exitButtonWidth=exitLabel->getContentSize().width;
exitButtonHeight=exitLabel->getContentSize().height;
exitLabel->setPosition(Point(visibleSize.width-exitButtonWidth,visibleSize.height-exitButtonHeight));
this->addChild(exitLabel);
//setting the clock
timer = Label::createWithTTF("00:00","fonts/Marker Felt.ttf",10);
timer->setPosition(Point(timer->getContentSize().width,visibleSize.height-timer->getContentSize().height));
this->schedule(schedule_selector(GameScene::updateClock),1.0f); //scedule to call upDateClock function every 1.0 sec
this->addChild(timer);
obstacleRotationPoint = Node::create();
obstacleRotationPoint->setPosition(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y);
this->addChild(obstacleRotationPoint, 3);
float theta=0;
snake[0] = DrawNode::create();
snake[0]->drawDot(Vec2(0,0),3,Color4F(100,110,0,1));
theta+=2*M_PI/150;
//this->addChild(snake[0],2);
rotationPoint->addChild(snake[0]);
// fixedPoint->addChild(snake[0]);
//loop to draw the concentric circles
for(r=15;r<=rMax;r+=15)
{
for(theta=0;theta<=2*M_PI;theta+=2*M_PI/r){
pathNode = DrawNode::create();
pathNode->drawDot(Vec2(r*cos(theta)+origin.x+visibleSize.width/2,r*sin(theta)+origin.y+visibleSize.height/2),1,Color4F(0,0,10,1));
//pathNode->autorelease();
this->addChild(pathNode,1);
//this->removeChild(pathNode);
}
}
controlable=0;
this->scheduleUpdate();
return true;
}
bool GameScene::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event)
{ // check if exit button region was clicked
_eventDispatcher->removeAllEventListeners();
auto scene = GameScene::createScene(levelNo);
Director::getInstance()->replaceScene(scene);
return true;
}
//function updates every frame
void GameScene::update(float dt){
}
The last part in the init function where I need to add pathNode is increasing my memory requirement everytime I transition a scene. I believe I am releasing everything in my destructor.
First of all, I don't recommend using global variables, which you have on top of your file (especially timer label). You should keep everything in class.
Second, you should check whether destructor is called in the first place.
Third, you can also try using some "Loading" screen between two levels and clean all unused textures like this:
setOnExitCallback([&](){
Director::getInstance()->getTextureCache()->removeUnusedTextures();
});
Fourth, I'd recommend to not recreate GameScene at all, but create function like restartLevel() and loadLevel() and just remove unnecessary stuff there and load new one.
I am working with VTK-6.1 and I want to create a single vtkActor using multiple vtkUnstructuredGrid. First I create the actor from a grid...
vtkSmartPointer<vtkActor> create_actor()
{
vtkSmartPointer<vtkUnstructuredGrid> grid = create_grid_a();
auto mapper = vtkSmartPointer<vtkDataSetMapper>::New();
mapper->SetInputData(grid);
auto actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(0.5, 0.5, 0.5);
actor->GetProperty()->SetEdgeVisibility(1);
return actor;
}
and then I (try) to update actor using another grid:
void update_actor(<vtkSmartPointer<vtkActor> actor)
{
// get current grid
vtkAlgorithm* algorithm = actor->GetMapper()->GetInputAlgorithm();
actor_grid = dynamic_cast<vtkUnstructuredGrid>(algorithm);
// create new grid
vtkSmartPointer<vtkUnstructuredGrid> new_grid = create_grid_b();
// combine grids
auto append_filter = vtkSmartPointer<vtkAppendFilter>::New();
append_filter->AddInputData(actor_grid);
append_filter->AddInputData(new_grid);
append_filter->Update();
// update actor
auto mapper = vtkSmartPointer<vtkDataSetMapper>::New();
mapper->SetInputData(append_filter->GetOutput());
actor->SetMapper(mapper);
}
The problem is that the actor does not contain the combination of grids.
Notes:
(create_grid_x() functions are a little too complex to provide but they
certainly work because first actor is created correctly)
SafeDownCast as shown in 1 is not working too.
References:
vtkActor reverse access
Appending data
The problematic section was the retrieval of vtkUnstructuredGrid from vtkActor.
// get current grid
vtkDataSet* actor_data = actor->getMapper()->GetInput();
...instead of using vtkAlgorithm