How to zoom-out object in SceneKit? - ios

I am creating cube in scene kit. this is output.
You can see images are not size to fit in SceneView.
Here is my code :
SCNScene *scene = [[SCNScene alloc]init];
float X = 0.0;
float Radius = 1.0;
for (int i = 0; i<3; i++) {
SCNBox *Box = [SCNBox boxWithWidth:3.0 height:3.0 length:3.0 chamferRadius:Radius];
self.cubeNode = [SCNNode nodeWithGeometry:Box];
[ArrBoxNode addObject:self.cubeNode];
self.sceneView.backgroundColor = [UIColor grayColor];
self.view.backgroundColor = [UIColor grayColor];
self.cubeNode.position = SCNVector3Make(X,.00,0.0);
[scene.rootNode addChildNode:self.cubeNode];
self.sceneView.scene = scene;
[self.sceneView sizeToFit];
self.sceneView.contentScaleFactor = 0.0;
}
Can you please help me?i am stuck in this issue.

Related

Can SKEmitterNode particles be rotated around their X and Y axes? [duplicate]

I'm trying to reproduce pieces of small paper falling from top effect, using CAEmitterLayer & CAEmitterCell.
So far, I got the 2D animation of it, But I'm having difficulty to make each cell to rotate when falling.
How to I apply random rotation on each particle? I tried with 3D Transform with no success so far.
This is what I got:
-(void) configureEmitterLayer {
self.emitterLayer = [CAEmitterLayer layer];
self.emitterLayer.emitterPosition = CGPointMake(self.backgroundContainer.bounds.size.width /2, 0);
self.emitterLayer.emitterZPosition = 10;
self.emitterLayer.emitterSize = self.backgroundContainer.bounds.size;
self.emitterLayer.emitterShape = kCAEmitterLayerLine;
CAEmitterCell *emitterCell = [CAEmitterCell emitterCell];
emitterCell.contents = (__bridge id)([UIImage imageWithColor:[UIColor whiteColor]].CGImage);
emitterCell.lifetime = CGFLOAT_MAX;
emitterCell.lifetimeRange = 4.0;
emitterCell.birthRate = 2.5;
emitterCell.color = [[UIColor colorWithRed:1.0f green:1.0 blue:1.0 alpha:1.0] CGColor];
emitterCell.redRange = 1.0;
emitterCell.blueRange = 1.0;
emitterCell.greenRange = 1.0;
emitterCell.alphaRange = 0.3;
emitterCell.velocity = 10;
emitterCell.velocityRange = 3;
emitterCell.emissionRange = (CGFloat) M_PI_2;
emitterCell.emissionLongitude = (CGFloat) M_PI;
emitterCell.yAcceleration = 1;
emitterCell.zAcceleration = 4;
emitterCell.spinRange = 2.0;
emitterCell.scale = 7.0;
emitterCell.scaleRange = 4.0;
self.emitterLayer.emitterCells = [NSArray arrayWithObject:emitterCell];
[self.backgroundContainer.layer addSublayer:self.emitterLayer];
}
This library doesn't use the emitter framework but is worth looking at for inspiration. UIDynamics is attached to individual objects to achieve the desired effect.
iOS confetti example

Position of SCNode Object infront of Camera With ARKit

I am trying to add Bullet in my Scene with ARKit.
Here is what i have done to add bullet in my Scene
{
SCNNode* systemNode = [SCNNode new];
SCNSphere *sphere = [SCNSphere sphereWithRadius:0.01];
systemNode.geometry = sphere;
systemNode.renderingOrder = 1;
SCNPhysicsShape *shape = [SCNPhysicsShape shapeWithGeometry:sphere options:nil];
systemNode.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:shape];
systemNode.physicsBody.mass = 0.05;
systemNode.physicsBody.friction = 0.01;
systemNode.physicsBody.affectedByGravity = NO;
SCNScene *modelScene = [SCNScene sceneNamed:#"Cartridge45.scn" inDirectory:#"art.scnassets/models" options:nil];
Bullet *bulletNode = [Bullet new];
bulletNode = (Bullet *) [modelScene.rootNode childNodeWithName:#"cartridge" recursively:YES];
bulletNode.scale = SCNVector3Make(1.0, 1.0, 1.0);
bulletNode.renderingOrder = 1;
Bullet *bulletNode1 = [Bullet new];
bulletNode1 = (Bullet *) [modelScene.rootNode childNodeWithName:#"cartridge_1" recursively:YES];
bulletNode1.scale = SCNVector3Make(1.0, 1.0, 1.0);
bulletNode1.renderingOrder = 1;
SCNVector3 min, max;
[bulletNode getBoundingBoxMin:&min max:&max];
CGFloat collisionCapsuleRadius = 0.01;
CGFloat collisionCapsuleHeight = 0.1;
NSLog(#"El Bouncing Box. El min es collisionCapsuleRadius:%f collisionCapsuleHeight:%f", collisionCapsuleRadius, collisionCapsuleHeight);
SCNNode *bColNode = [SCNNode node];
NSString *nameCube = [NSString stringWithFormat:#"BulletB%d", rand()];
bColNode.name =nameCube;
bColNode.position = SCNVector3Make(0.0, 0.0, 1.2);// a bit too high to not hit the floor
bColNode.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeKinematic shape:[SCNPhysicsShape shapeWithGeometry:[SCNCapsule capsuleWithCapRadius:collisionCapsuleRadius height:collisionCapsuleHeight] options:nil]];
bColNode.physicsBody.categoryBitMask = CollisionCategoryBullet;
bColNode.physicsBody.contactTestBitMask = CollisionCategoryInvader;
[systemNode addChildNode:bColNode];
ARFrame *frame = self.sceneView.session.currentFrame;
SCNVector3 direction;
SCNVector3 position;
if (frame != nil) {
SCNMatrix4 mat = SCNMatrix4FromMat4(frame.camera.transform);
direction = SCNVector3Make(mat.m41, mat.m42, mat.m43);
position = SCNVector3Make(mat.m31*-1, mat.m32*-1, mat.m33*-1);
}
else {
direction = SCNVector3Make(0,0,-0.11);
position = SCNVector3Make(0,0,-0.1);
}
systemNode.position = SCNVector3Make(0,0,0);
bulletNode.position = position;
bulletNode1.position = position;
systemNode.name=#"bullet";
[systemNode addChildNode:bulletNode];
[systemNode addChildNode:bulletNode1];
SCNMatrix4 transform = SCNMatrix4FromMat4(frame.camera.transform);
SCNVector4 force = SCNVector4Make(0, 0,-5, 0);
SCNVector3 rotatedForce = [self to3:[self multiplyVector:transform :force]];
[systemNode.physicsBody applyForce:rotatedForce impulse:YES];
[self.sceneView.scene.rootNode addChildNode:systemNode];
}
The bullet is getting added at same direction disregards of view of camera in real world.

iOS+SceneKit: How to apply toon shader on texture?

I want to use a toon-shader with SceneKit on iOS8+ to render a sphere with an Earth texture on it. I also want to add a toon shader for rendering the Earth. So far the shader works on the lighting, but the texture isn't shaded by the toon-shader (cp. to the image below, the texture should also be "tooned").
Someone any ideas?
Here's my view controller code (self.sceneKitView is an instance of SCNView):
#implementation ToonViewController
- (void)viewDidLoad {
[super viewDidLoad];
SCNScene *scene = [SCNScene scene];
// create and add a camera to the scene
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
[scene.rootNode addChildNode:cameraNode];
// place the camera
cameraNode.position = SCNVector3Make(0, 0, 15);
// create and add a light to the scene
SCNNode *lightNode = [SCNNode node];
lightNode.light = [SCNLight light];
lightNode.light.type = SCNLightTypeOmni;
lightNode.position = SCNVector3Make(0, 10, 10);
[scene.rootNode addChildNode:lightNode];
// create and add an ambient light to the scene
SCNNode *ambientLightNode = [SCNNode node];
ambientLightNode.light = [SCNLight light];
ambientLightNode.light.type = SCNLightTypeAmbient;
ambientLightNode.light.color = [UIColor darkGrayColor];
[scene.rootNode addChildNode:ambientLightNode];
// set up the scene
self.sceneKitView.scene = scene;
self.sceneKitView.allowsCameraControl = YES;
self.sceneKitView.showsStatistics = NO;
self.sceneKitView.backgroundColor = [UIColor clearColor];
NSMutableDictionary* shaders = [[NSMutableDictionary alloc] init];
shaders[SCNShaderModifierEntryPointLightingModel] = [[NSString alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:#"fixed_toon" withExtension:#"shader"]
encoding:NSUTF8StringEncoding
error:nil];
SCNNode* earth = [SCNNode nodeWithGeometry:[SCNSphere sphereWithRadius:5.0]];
earth.position = SCNVector3Make(0.0, 0.0, 0.0);
[scene.rootNode addChildNode:earth];
[earth runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0.0 y:0.25 z:0.0 duration:1.0]]];
SCNMaterial* earthMaterial = [SCNMaterial material];
earthMaterial.diffuse.contents = [UIImage imageNamed:#"Earth.png"];
earthMaterial.specular.contents = [UIColor whiteColor];
earthMaterial.specular.intensity = 0.2;
earthMaterial.locksAmbientWithDiffuse = NO;
earthMaterial.shaderModifiers = shaders;
earth.geometry.firstMaterial = earthMaterial;
}
#end
And this is the fixed_toon.shader file:
vec3 lDir = normalize(vec3(0.1, 1.0, 1.0));
float dotProduct = dot(_surface.normal, lDir);
_lightingContribution.diffuse += (dotProduct*dotProduct*_light.intensity.rgb);
_lightingContribution.diffuse = floor(_lightingContribution.diffuse*4.0)/3.0;
vec3 halfVector = normalize(lDir + _surface.view);
dotProduct = max(0.0, pow(max(0.0, dot(_surface.normal, halfVector)), _surface.shininess));
dotProduct = floor(dotProduct*3.0)/3.0;
//_lightingContribution.specular += (dotProduct*_light.intensity.rgb);
_lightingContribution.specular = vec3(0,0,0);
The shader you have is only a lighting shader. If you want the earth to be tooned, you need a fragment shader.
Look at the shader file all of the math is related to light. You need something that will adjust the pixel color of the texture. Then connect it using the SCNShaderModifierEntryPointFragment entry point.

SpriteKit Generate Random Curl Line

I am working on a project and what I need to accomplish is to generate random curl line. At this point I have already have a line which is randomly generated but it is not curl. I am spawning points at different x positions on every 0.5 seconds and connect this points with bezier. Everything works perfectly except that it is not curl. On the picture below is shown on 1) How I have it now and on 2) How I suppose to make it. Any ideas how I can do that ? I am using SpriteKit - Objective C
Basically what you need to make and randomize a A Bézier (parametric) curve are control points.
After you read that great answer and get familiar with terms, you can try this example (I assume that your scene and view size are set correctly):
GameScene.m
#import "GameScene.h"
#implementation GameScene
-(void)didMoveToView:(SKView *)view {
}
-(NSInteger)randomNumberBetween:(NSInteger)from to:(NSInteger)to {
return (int)from + arc4random() % (to-from+1);
}
- (CGMutablePathRef)generatePath
{
CGMutablePathRef path = CGPathCreateMutable();
CGPoint p0 = CGPointMake(CGRectGetMidX(self.frame),self.scene.size.height-20.0f); //starting point just little below the upper edge of the screen
CGPathMoveToPoint(path, nil, p0.x, p0.y);
CGPoint p1 =
CGPointMake([self randomNumberBetween:150 to:300], self.scene.size.height- [self randomNumberBetween:150 to:300]);
CGPoint p2 = CGPointMake([self randomNumberBetween:150 to:300],[self randomNumberBetween:150 to:300]);
CGPoint p3 = CGPointMake(CGRectGetMidX(self.frame),0 + 20.0f); //ending point, just little above the bottom edge of the screen
CGFloat v = 0.3;
CGFloat cp1x = p1.x+v * (p1.x-p0.x);
CGFloat cp1y = p1.y+v * (p1.y-p0.y);
CGFloat cp2x = p2.x-v * (p3.x-p2.x);
CGFloat cp2y = p2.y-v * (p3.y-p2.y);
CGPathAddCurveToPoint(path,nil,cp1x,cp1y,cp2x,cp2y,p3.x,p3.y);
/*Debug - not needed*/
SKSpriteNode *sp0 = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(5.0f,5.0f)];
sp0.zPosition = 5;
sp0.position = p0;
SKLabelNode *lp0 = [SKLabelNode labelNodeWithFontNamed:#"ArialMT"];
lp0.fontColor = [SKColor whiteColor];
lp0.fontSize = 20.0f;
lp0.text = #"p0";
lp0.position = CGPointMake(0.0f,-20.0f);
[sp0 addChild:lp0];
[self addChild:sp0];
SKSpriteNode *sp1 = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(5.0f,5.0f)];
sp1.zPosition = 5;
sp1.position = p1;
SKLabelNode *lp1 = [SKLabelNode labelNodeWithFontNamed:#"ArialMT"];
lp1.fontColor = [SKColor whiteColor];
lp1.fontSize = 20.0f;
lp1.position = CGPointMake(0.0f,15.0f);
lp1.text = #"p1";
[sp1 addChild:lp1];
[self addChild:sp1];
SKSpriteNode *sp2 = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(5.0f,5.0f)];
sp2.zPosition = 5;
sp2.position = p2;
SKLabelNode *lp2 = [SKLabelNode labelNodeWithFontNamed:#"ArialMT"];
lp2.fontColor = [SKColor whiteColor];
lp2.fontSize = 20.0f;
lp2.position = CGPointMake(0.0f,15.0f);
lp2.text = #"p2";
[sp2 addChild:lp2];
[self addChild:sp2];
SKSpriteNode *sp3 = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(5.0f,5.0f)];
sp3.zPosition = 5;
sp3.position = p3;
SKLabelNode *lp3 = [SKLabelNode labelNodeWithFontNamed:#"ArialMT"];
lp3.fontColor = [SKColor whiteColor];
lp3.fontSize = 20.0f;
lp3.position = CGPointMake(0.0f,15.0f);
lp3.text = #"p3";
[sp3 addChild:lp3];
[self addChild:sp3];
SKShapeNode *p0p1 = [SKShapeNode node];
p0p1.zPosition = 2;
CGMutablePathRef path1 = CGPathCreateMutable();
CGPathMoveToPoint(path1, NULL, p0.x, p0.y);
CGPathAddLineToPoint(path1, NULL, p1.x, p1.y);
p0p1.path = path1;
[p0p1 setStrokeColor:[UIColor greenColor]];
[self addChild:p0p1];
SKShapeNode *p2p3 = [SKShapeNode node];
p2p3.zPosition = 2;
CGMutablePathRef path2 = CGPathCreateMutable();
CGPathMoveToPoint(path2, NULL, p2.x, p2.y);
CGPathAddLineToPoint(path2, NULL, p3.x, p3.y);
p2p3.path = path2;
[p2p3 setStrokeColor:[UIColor greenColor]];
[self addChild:p2p3];
return path;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self removeAllChildren];
SKShapeNode *yourline = [SKShapeNode node];
yourline.zPosition = 1;
yourline.path = [self generatePath];
[yourline setLineWidth:5];
[yourline setStrokeColor:[SKColor redColor]];
[self addChild:yourline];
}
Most of this code is used for visual debugging and its not needed in order to randomize the curve. The important part is the first part of the method generatePath. Here is the result:

CAEmitterCell - slow stars or light effect

I'm playing around with CAEmitterCell, but most effects are very fast effects like the firework.
But I want to have a slow "stars" effect like you see here on www.findyourwaytooz.com
How can I do that with CAEmitterCell?
Thank you :)
I have a project that uses the following setup for the emitter, and it pretty accurately mimics what I think you mean:
//set ref to the layer
starsEmitter = (CAEmitterLayer*)self.layer; //2
//configure the emitter layer
starsEmitter.emitterPosition = CGPointMake(160, 240);
starsEmitter.emitterSize = CGSizeMake(self.superview.bounds.size.width,self.superview.bounds.size.height);
NSLog(#"width = %f, height = %f", starsEmitter.emitterSize.width, starsEmitter.emitterSize.height);
starsEmitter.renderMode = kCAEmitterLayerPoints;
starsEmitter.emitterShape = kCAEmitterLayerRectangle;
starsEmitter.emitterMode = kCAEmitterLayerUnordered;
CAEmitterCell* stars = [CAEmitterCell emitterCell];
stars.birthRate = 0;
stars.lifetime = 10;
stars.lifetimeRange = 0.5;
stars.color = [[UIColor colorWithRed:255 green:255 blue:255 alpha:0] CGColor];
stars.contents = (id)[[UIImage imageNamed:#"particle.png"] CGImage];
stars.velocityRange = 500;
stars.emissionRange = 360;
stars.scale = 0.2;
stars.scaleRange = 0.1;
stars.alphaRange = 0.3;
stars.alphaSpeed = 0.5;
[stars setName:#"stars"];
//add the cell to the layer and we're done
starsEmitter.emitterCells = [NSArray arrayWithObject:stars];
I uploaded the sample project to GitHub: SimpleCAEmitterLayer

Resources