OpenGL ES 2.0 several scenes - c++

How to implement transition between several scenes that use opengl?
I have 2 different scenes. each create its frame and render buffers and bind it. But then I try to switch between these scenes - nothing happens... I tried to delete all buffers when swithing but it's doesn't work. The First scene is still visible..

Well, in my experience you may need to dispose of the textures for the first scene's visuals.
A quick idea is using psm studio's approach to OpenGLES.
public TitleScene ()
{
this.Camera.SetViewFromViewport();
_texture = new Texture2D("Application/images/title.png",false);
_ti = new TextureInfo(_texture);
SpriteUV titleScreen = new SpriteUV(_ti);
titleScreen.Scale = _ti.TextureSizef;
titleScreen.Pivot = new Vector2(0.5f,0.5f);
titleScreen.Position = new Vector2(Director.Instance.GL.Context.GetViewport().Width/2,
Director.Instance.GL.Context.GetViewport().Height/2);
this.AddChild(titleScreen);
public override void Update (float dt)
{
base.Update (dt);
var touches = Touch.GetData(0).ToArray();
if((touches.Length >0 && touches[0].Status == TouchStatus.Down) || Input2.GamePad0.Cross.Press)
{
Director.Instance.ReplaceScene(new MenuScene());
}
}
~TitleScene()
{
_texture.Dispose();
_ti.Dispose ();
}
}
I hope this will give you some help on what you are missing.

Related

Override open variable for class in Swift and SpriteKit for use in XCode's ActionEditor

I'm trying to make small platformer game, just in learning purposes. I've tried to animate character with array of SKTextures like this:
let animation: SKAction = SKAction.animate(
with: frames.map {
let texture : SKTexture = SKTexture(imageNamed: $0)
texture.filteringMode = SKTextureFilteringMode.nearest
return texture
},
timePerFrame: 0.15
)
frames variable is array of SKTextures. I've used map to set filtering mode for each texture. This works fine and dandy, but than i've discovered that i can create animations (actions) in ActionEditor in XCode with AnimateWithTextures action. And here lies my problem. This is much more efficient, but i can't change filtering mode for textures in animation in ActionEditor. I've looked into SKTexture class and saw this:
open class SKTexture : NSObject, NSCopying, NSCoding {
...
/**
The filtering mode the texture should use when not drawn at native size. Defaults to SKTextureFilteringLinear.
*/
open var filteringMode: SKTextureFilteringMode
...
}
If i'm not mistaken open means that i can override variable, but i don't know how. I want to set default value of filteringMode to SKTextureFilteringMode.nearest for all SKTextures so ActionEditor will use textures with texture filtering set to nearest neighbor.
Also if you know how to set filtering mode for textures in specific action – i would like to know how to do it too. Thanks
you can create a function to setup the animation for you, and create an extension to SKTexture with your custom init, and when your ready just call it to your node.
extension SKTexture { // Declare this extension outside your class decleration
convenience init(customImageNamed: String) {
self.init(imageNamed: customImageNamed)
self.filteringMode = .nearest
}
}
func setupAnimationWithPrefix(_ prefix: String, start: Int, end: Int, timePerFrame: TimeInterval) -> SKAction{
var textures = [SKTexture]()
for i in start...end{
textures.append(SKTexture(customImageNamed: "\(prefix)\(i)"))
}
return SKAction.animate(with: textures, timePerFrame: timePerFrame)
}
if you have 10 images named image1, image2, image3 ect..then this is how you would use this function
func runAction(){
let action = setupAnimationWithPrefix("image", start: 1, end: 10, timePerFrame: 0.1)
yourNode.run(action)
} // you can change timePerFrame to your liking i find 0.1 sec per frame the best
Unfortunately you can't override a variable without subclassing it, that is to do something like
class MyTexture: SKTexture {
from there, you could override the variable:
override var filteringMode: SKTextureFilteringMode {
get {
return .nearest
}
set {
}
}
That should work, but now you can't change the filtering mode, ever (without going through a bunch of hooplah).
So the more apt way would be to set the default value via the initializer, but SKTexture has no public designated initializers, so that option is out of the window.
So your best bet is going to be the convenience init extension by Arie, or just make a plain function that returns a new texture:
func nearestTexture(imageNamed name: String) -> SKTexture {
let newTex = SKTexture(imageNamed: name)
newTex.filteringMode = .nearest
return newTex
}
let texture: SKTexture = nearestTexture(imageNamed: "lol")
ActionEditor is still very limited in features, you are going to have to write some kind of code behind to allow for texture filtering. If you do not plan on scaling your sprites (Note I said sprite, not scene, these are two different behaviors), then I would not even worry about texture filtering, the time difference would be negligible.

C++ VTK Render Window not working on macOS

I am new to VTK. I was trying to run the code below on my macbook, however the window failed to pop up. Seems like it quit unexpectedly. Could someone tell me whats the reason???
TIA
int main(int argc, const char * argv[]) {
//cylinder
vtkSphereSource *sphere = vtkSphereSource::New();
sphere->SetPhiResolution(16);
sphere->SetThetaResolution(16);
//Shrink
vtkShrinkFilter *shrink = vtkShrinkFilter::New();
shrink->SetInputConnection(sphere->GetOutputPort());
shrink->SetShrinkFactor(0.9);
//Elevation Filter
vtkElevationFilter *colorIt = vtkElevationFilter::New();
colorIt->SetInputConnection(shrink->GetOutputPort());
colorIt->SetLowPoint(0,0,-0.5);
colorIt->SetHighPoint(0,0,0.5);
vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New();
sphereMapper->SetInputConnection(colorIt->GetOutputPort());
vtkActor *sphereActor = vtkActor::New();
sphereActor->SetMapper(sphereMapper);
vtkRenderer *ren1 = vtkRenderer::New();
ren1->AddActor(sphereActor);
ren1->SetBackground(0.1,0.2,0.4);
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren1);
renWin->SetSize(300,300);
renWin->Render();
shrink->SetInputConnection(colorIt->GetOutputPort());
renWin->Render();
return 0;
}
What is the aim of the last two lines?
shrink->SetInputConnection(colorIt->GetOutputPort());
renWin->Render();
This creates a cyclical connection of the filters: sphere->shrink->colorIt->....(mapper, actor)->shrink again. Are you trying to shrink it twice? Then it's simpler to just use higher shrink factor. Or you want two different spheres there? Than you have to create two separate objects for them.
Also, output of vtkShrinkFilter is vtkUnstructuredGrid, not vtkPolyData, so you have to use vtkDataSetMapper instead of vtkPolyDataMapper. Your code works for me when I do this change and also delete the second shrink->SetInputConnection line.

C++ template for classes with static method

I'm currently programming a game using cocos2dx engine and I have a level manager that keeps track of the current level and the scene that needs to be loaded. I want to avoid long if statements, such as this:
Scene* scene;
if (level == 1)
{
scene = Game_Scene1::createScene();
}
else if (level == 2)
{
scene = Game_Scene2::createScene();
}
else if (level == 3)
{
scene = Game_Scene3::createScene();
}
(...)
else if (level == 10)
{
scene = Game_Scene10::createScene();
}
Director::getInstance()->replaceScene(TransitionFade::create(0.5, scene, Color3B(0,0,0)));
The screateScene() method is a static method
static cocos2d::Scene* createScene();
What could I do to "remove" the if statement? So it would look something like this:
Scene* scene = getScene(level, sceneClass::createScene());
and it would take the correct class (that is: Game_Scene1, Game_Scene2 etc.)
Is there a nice solution for such problem? The title says template but I'm not really sure if the solution for this is a template.
One simple solution would be to used a table of pointer functions.
You could declare your table as
typedef cocos2d::Scene *(*PtfCreateScene)();
PtfCreateScene tab[10];
tab[0] = Game_Scene1::create_scene;
tab[1] = Game_Scene2::create_scene; ...
Using this solution you can then call the associated create_scene function using level as an index. Thus avoiding the if branchings .
scene = tab[level - 1]();
You will have to check the correctness of the index to avoid out of memory access.
Hope I answered your question. Don't hesitate to ask if you need more explanation.

How do I make a custom event with VTK?

I'm making a thread software with VTK, where I need to change the model itself in real time, while I need to change his method of rendering. Everything is working fine, but, the problem start with the interactor->start(); , the model data gets updated just fine, but it's only showed on screen when I move The camera. Also I have selected some methods for generating a 3D data from a imagedata file, for that I need to close the vtk window (interactor window) and then the code will reopen it and send the new data generated to it...
I would need something like these:
int force close_window = false; int refresh_interactor = false;
I managed to make the Window close, but only with vtkcommand::Keypressed command, but idk how do I do with a new command :S, I tried the vtkcommand::UserEvent but I didn't found a good information about how to deal with that data (like some way to call it)
the way I'm dealing with VTK is with two threads, the first one, is just about the vtk iren loop, and the second one would manage the models and check if iren requires to be updated.
In my dream code it should be something like this:
=======================================================
bool VTKWindow()
{
...
vtkSmartPointer ator = vtkSmartPointer::New();
iren = vtkSmartPointer::New();
RenWindow = vtkSmartPointer::New();
render->SetBackground(.1, .2, .3);
RenWindow->AddRenderer(renderer);
iren->SetRenderWindow(RenWindow);
if(data_type == voxel_type)
{
Render->AddViewProp(VoxelData);
}
else
{
actor->SetMapper(PolyData);
Render->AddActor(Actor);
}
RenWindow->Render();
iren->Start();
}
void ManageVTK()
{
while true loop...
if(force close_window == true)
do some command to exit the iren loop
if(refresh_interactor == true)
do some command to refresh iren
}
Sorry for the english, it's not my native language, and also sorry about the question format, it's the first time I'm using stackoverflow
It may sounds stupid, but, I found a kind of solution for the problem.
I saw on related links this guy vtkRenderWindowInteractor event loop and threading and, it's almost the same problem...
class VTKNewEvent : public vtkCommand{
public:
vtkTypeMacro(VTKNewEvent , vtkCommand);
static VTKNewEvent * New(){
return new VTKNewEvent ;
}
void Execute(vtkObject * caller, unsigned long vtkNotUsed(eventId), void * vtkNotUsed(callData)){
vtkRenderWindowInteractor *iren = static_cast<vtkRenderWindowInteractor*>(caller);
if (iren_close == true){
iren->GetRenderWindow()->Finalize // Stop the interactor
iren->TerminateApp();
iren_close = false;
}
if (iren_update== true){
renderJanela->Render();
iren_update= false;
}
}
};
bool VTKWindow(){
vtkSmartPointer<VTKNewEvent > IrenRefresh= vtkSmartPointer<VTKNewEvent>::New();
...
iren->CreateRepeatingTimer(1);//this makes that IrenRefresh will be called at every 1ms
iren->AddObserver(vtkCommand::TimerEvent, IrenRefresh);
iren->Start();
...
}
it's simple, but, maybe not the best, but it did Th job, I hope this link will help people that are starting into the VTK world, since threads + rendering loop wasn't a simple job to understand what was going on

How can I get other layer in the same scene in cocos2d-x?

I have several layers in the scene, like TLayer,HLayer,TouchLayer. How can I get HLayer in HLayer? The solution I take is that I pass Layer to other Layer. However I met some problems recently. I push the Scene and pop Scene while TouchLayer still exists. So my problem is that is it right to pass HLayer to TouchLayer. Or is there a better way to do it in Cocos2d-x?
In the init() function in Scene:
this->setbackgroundLayer(BackgroundLayer::create());
CC_BREAK_IF(!backgroundLayer);
this->addChild(backgroundLayer);
this->setTLayer(TcharacterLayer::create(backgroundLayer->tianzige));
CC_BREAK_IF(!TLayer);
this->addChild(TLayer);
this->setHLayer(HcharacterLayer::create(testCharacter,backgroundLayer->tianzige_draw));
CC_BREAK_IF(!HLayer);
this->addChild(HLayer);
this->settouchLayer(TouchLayer::create(TLayer,HLayer));
CC_BREAK_IF(!touchLayer);
this->addChild(touchLayer);
I made my own create function:
TouchLayer* TouchLayer::create(TcharacterLayer* t,HcharacterLayer* h){
TouchLayer* pRet = new TouchLayer();
if (pRet && pRet->init(t,h))
{
pRet->autorelease();
return pRet;
}else
{
delete pRet;
pRet = NULL;
return NULL;
}
}
Here's how we've done this in the past. Define a set of tags for our layers.
typedef enum {
kBgLayerTag,
kHLayerTag,
kTLayerTag,
kTouchLayerTag
} MyLayerTags
Then while creating the layers set layer specific tags:
this->setTLayer(TcharacterLayer::create(backgroundLayer->tianzige));
CC_BREAK_IF(!TLayer);
TLayer->setTag(kTLayerTag);
this->addChild(TLayer);
And in TouchLayer access the TLayer and others like:
TcharacterLayer* myTLayer = this->getParent()->getChildByTag(kTLayerTag);
Sure, there is nothing wrong in adding a layer as a child. I would do that this way :
BackgroundLayer has all the necessary layers as children (remember to add TouchLayer as the last one and then pass Touch to others) and then you only add BackgroundLayer to your scene. There is even more simple way (probably better): to make BackgroundLayer inherit all the previous ones - but that depends on how much scenes you are going to make.
Edit:
1)
BackgroundLayer * bglayer = BackgroundLayer::create();
TcharacterLayer * tcharlayer = TcharacterLayer::create();
HcharacterLayer * hcharlayer = HcharacterLayer::create();
TouchLayer * tlayer = TouchLayer::create();
bglayer->addChild(tcharlayer);
bglayer->addChild(hcharlayer);
bglayer->addChild(tlayer);
this->addChild(bglayer);
(assuming this as a CCScene)
2)
class BackgroundLayer : public TcharacterLayer, HcharacterLayer, TouchLayer
{
...
}
In the first case you can give each layer a specific tag and then get the layer by getChildByTag(int tag) or just create fields in the BackgroundLayer class for each layer.