How can I enable shadow effect on *.pod object?
I set up camera and light but my object didn't have shadow.
Can somebody explain how to resolve this?
In order to enable shadows in cocos3d, you must first set
_viewController.viewShouldUseStencilBuffer = NO;
to
_viewController.viewShouldUseStencilBuffer = YES;
in the application delegate.
Next, you must add shadow volumes to the objects of a scene manually.
You can do this by adding this method call to the initialization method of your cc3scene subclass:
[self addShadowVolumesForLight:yourLight];
in order to add shadow volumes to every object in the scene for a specific light, or:
[self addShadowVolumes];
to do the same for all lights in the scene.
alternatively you can do the same for specific objects in the scene, if you want to limit shadowing.
e.g.
[someObject addShadowVolumesForLight:yourLight];
[someObject addShadowVolumes];
Related
I'm using OpenGL ES (2.0) exclusively for my app. I'm trying to get UIMotionEffect to work with one of my OpenGL objects - where all I need are the "tilt" values.
UIInterpolatingMotionEffect can only be applied to a UIView, and a hack would be to apply UIInterpolatingMotionEffect to a UIView and grab the values from there per frame, while not rendering the supposed UIView. But it seems far too hack-ish to be the only solution.
I tried to subclass UIMotionEffect, but couldn't figure out how - (NSDictionary *)keyPathsAndRelativeValuesForViewerOffset:(UIOffset)viewerOffset worked (ie. what calls it and how to retrieve the values I need).
Any ideas on how could I use UIMotionEffect with OpenGL?
I finally tested the method suggested by #rickster: connect UIInterpolatingMotionEffect to my GLKView/GL View pass keys that are custom made and just retrieve them. Unfortunately, that idea royally fails.
First, the keys that are passed to UIInterpolatingMotionEffect must be UIView animatable properties, and can't be custom variables/properties. Considering most people wouldn't want their entire context to parallax in one way direction/intensity, this method will fail.
Second, you can't just retrieve the values. If you pass center.x as a key, UIInterpolatingMotionEffect won't update center.x since the changes are considered "animations". As such, you have you retrieve the animated center.x, for example [[view.layer presentationLayer] center];
Final Notes: Just create a separate UIView on the main thread, add it to your UIViewController and systematically retrieve values from it (also on the main thread). I found that to be the simplest solution by far.
Also, since I needed to retrieve the values on a separate thread, I'm generally 1 value behind, as I dispatch to the main thread to retrieve the current value, while at the same time retrieving the last value set (make sure the variable is thread-safe/atomic).
EDIT
Since its best to access the presentationLayer on the main thread, but my method is called for a thread that isn't main, I dispatch the main thread to retrieve the value and place it in an atomic property. I would then return the atomic property outside the thread. This makes sure my secondary thread doesn't get blocked by the main thread, and I can retrieve the values I need.
Here's the code I used to retrieve values from a thread that isn't the main thread:
#property (atomic) GLKVector2 currentOffset;
#property (atomic, readonly) GLKVector2 offset;
- (GLKVector2)offset
{
dispatch_async(dispatch_get_main_queue(), ^{
CGRect frame = [[self.view.layer presentationLayer] frame];
self.currentOffset = (GLKVector2){-frame.origin.x, -frame.origin.y};
});
return self.currentOffset;
}
UIInterpolatingMotionEffect works by using key-value coding to set a value for any numeric property on a UIView. This can be any property you define, not just those built into the UIView class.
You need some kind of UIView to get your content on screen. If you're using OpenGL ES on iOS, you're (preferably) using GLKView, which is a UIView subclass that manages its own GL framebuffers and gives you a place to write GL drawing code to render into those framebuffers. (If you're not using GLKView, you're probably using some kind of custom UIView subclass that uses a CAEAGLLayer to render its contents.)
Either way, if you've got GL-rendered content on the screen already, you already have a UIView. If that view isn't your own custom subclass (whether a direct UIView subclass or GLKView subclass), you can make it one, and define your own custom properties on it. Then set up your UIInterpolatingMotionEffect to use those properties. In your view subclass, or whatever object is responsible for your GL rendering, read the values of those properties and use them to set up your scene. (For example, you could use them to set up a ModelView matrix, and pass that to a shader uniform.)
So in my project, I call an instance method called "-(void)fire" in the class "Survival.m":
-(void)fire {
NSLog(#"Firing");
CCSprite *sprite = [CCSprite spriteWithFile:#"bullet.png"];
sprite.position = player.position;
NSLog(#"%#",NSStringFromCGPoint(player.position));
[self addChild:sprite z:100];
}
When I do this, the sprite doesn't show on the screen.
The method is being called from another layer but since it logs "Firing" every time I tap the button, it's not the problem.
I am using a TMXTiledMap as well if that could cause any problems.
Please help, thanks!
EDIT---------
I can create sprites in the other layer, HUDLayer but not in the Survival layer which contains the player and the tiled map. If I create a sprite in the "init" method, it works correctly but If i do it in the method "fire" it doesn't work. The method "fire" is being called from the HUDLayer but I still now the method is being called since I see in the log that it says "Firing"
Could it be that:
1. The sprite is being created out of sight?
2. The sprite is not being created?
3. The sprite is not added to the correct parent?
Any suggestions?
to add a sprite in cocos2d do something like this
CCNode *parent = [self getChildByTag:kTagParentNode];
[parent addChild:sprite];
if that doesnt fix it, make sure the point where you are adding it is on the screen and try changing the z value to see if that helps
EDIT
add this under where you import files
enum {
kTagParentNode = 1,
};
Thanks Everybody, Solved it in some mysterious way. Thanks for the help anyway. I think I declared the layer in a wrong way.
Have a nice day!
Newbie to iOS and Cocos2d ( 2.x )
Ok I want to create a Menu Object and call it from each new Scene.
Example:
Scene1, add menu
Scene2, add same menu as on Scene1
I've only seen how to initialize the CCMenu when you init the Layer itself. you build the items and then add them to the CCMenu and so on.
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:lesson_3._menus_and_scenes
How can I initialize the CCMenu once and then just add it to what ever scene I happen to be viewing? So if I'm viewing Scene1 or Scene2 it's still the same menu.
Does this make sense?
You'll need a different instance of the menu for each scene, so technically speaking, you'll need to initialize it once per scene.
But I think you're asking "how can I write the code once and then reuse that code in each scene." You'll want to create some sort of CC Object that you can reuse. This could be a subclass of a CCMenu, CCLayer, or whatever suits the purpose best. So you may try something like:
#interface MyMenuLayer : CCLayer {
CCMenu *myMenu;
}
#end
Then in the .m file, set up your menu however you like. When you want to include this in Scene1:
MyMenuLayer *menu = [MyMenuLayer node];
[self addChild:menu];
You can use the exact same code in Scene2.
(You could just extend CCMenu instead of CCLayer, but I personally prefer to work with Layers instead of Menus. It's a matter of personal choice.)
It's hard to give a very definitive answer with the information in your question, but I hope this gets you set off on the right path.
I want to write a (only one) method or category or something else about an Animation,
so that when I am setting any UIImageView's image property, the animation will be executed automatically.
any idea? Thanks.
You can subclass UIImageview.
Add a animationProperty.
Create a animation block.
Call animation block from the setMethod of the animationProperty.
As image is a property, you can use KVO.
First In the category add image-observer, and write your own animation method.
I am creating a sprite like this in my init method (mySprite is declared in the .h):
mySprite = [CCSprite spriteWithFile:#"Image1.png"];
[mySprite setPosition:ccp(100, 300)];
[self addChild:mySprite z:1 tag:1];
Then in my other method, I try to animate it like so but it doesn't seem to animate at all, I also know that the method that this is in is getting called because I NSLogged it. Anyway here is how I try to animate mySprite:
CCSequence *moveSequence = [CCSequence actions:[CCMoveTo actionWithDuration:5 position:ccp(120, 400)],[CCMoveTo actionWithDuration:4 position:ccp(100, 300)], nil];
[mySprite runAction:[CCRepeatForever actionWithAction:moveSequence]];
Any ideas why this might be happening?
Thanks!
At first glance this part of the code seems right, so perhaps you would need to show more of your overall program so that we can examine what happens between your init function and your other method being called.
A couple things out of the blue:
make sure to call retain on your sprite so that it does not get removed summarily until you are done with it
what is "self" exactly here, is it a cocos layer? Is the layer added to the scene properly (ie, are you seeing the sprite being displayed, even if it does not move)?
I would also look to see if anything in the scene graph might happen between the "init" call and that second method of yours, in which you execute the animation code. Is there a StopAllActions somewhere? A removeFromParent or removeAllChildren, perhaps?
Cheers