Position of SCNode Object infront of Camera With ARKit - ios

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.

Related

How to zoom-out object in SceneKit?

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.

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 didBeginContact function not called

I am trying to get collision working in my SpriteKit game using the didBeginContact function.
My problem is that the function is just not getting called at all when the ball bounces off of the bricks. This is how I have set them both up:
static const uint32_t blockCollisionCheck = 0x1 << 0;
static const uint32_t ballCollisionCheck = 0x1 << 1;
Ball:
SKShapeNode *ball = [[SKShapeNode alloc] init];
CGMutablePathRef drawPath = CGPathCreateMutable();
CGPathAddArc(drawPath, NULL, 0, 0, _ballRadius, 0, M_PI * 2, YES);
ball.path = drawPath;
CGPathRelease(drawPath);
ball.fillColor = [SKColor greenColor];
ball.position = CGPointMake(CGRectGetMidX(self.frame), 150);
ball.name = #"ball";
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_ballRadius];
ball.physicsBody.friction = 0.0;
ball.physicsBody.restitution = 1.0;
ball.physicsBody.linearDamping = 0.0f;
ball.physicsBody.allowsRotation = NO;
ball.physicsBody.dynamic = YES;
ball.physicsBody.categoryBitMask = ballCollisionCheck;
ball.physicsBody.contactTestBitMask = blockCollisionCheck;
[self addChild:ball];
Bricks:
SKSpriteNode *block = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(_blockWidth, _blockHeight)];
block.name = #"block";
block.position = CGPointMake(x, y);
block.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:block.size];
block.physicsBody.allowsRotation = NO;
block.physicsBody.friction = 0.0;
block.physicsBody.dynamic = YES;
block.physicsBody.categoryBitMask = blockCollisionCheck;
block.physicsBody.contactTestBitMask = ballCollisionCheck;
[self addChild:block];
I can't for the life of me see what is wrong with this, as I have the category bit masks correct I think? Also both of the sprites are Dynamic, which is another problem I read it could have been.
It's not that the contents of my didBeginContact function is not working, it's just never getting there as evidenced from a lack of NSLog message and breakpoints not being reached.
Any help would be greatly appreciated.
Thank you.
If, as you say, the didBeginContact method is not being called at all, I suspect you did not add the self.physicsWorld.contactDelegate = self; into your GameScene init method.

Sprite Kit didBeginContact not called between body and edgeRect

I have a game where I'm flicking bodies off the screen. I want to detect when these bodies are coming into contact with the edges (still letting the bodies pass through to off the screen) of the screen and I've implemented everything but still it is not working..here's my code:
GameScene.h
typedef NS_OPTIONS(uint32_t, FAPhysicsCategory) {
FAWallCategory = 1 << 0,
FABottomWallCategory = 1 << 1,
FAAnimalCategory = 1 << 2,
};
GameScene : SKScene <SKPhsyicsContactDelegate>
GameScene.m
-(void)setupWorldPhysics
{
// Set world gravity
self.physicsWorld.gravity = CGVectorMake(0.0, -5.0);
float bottomOffset = 400.0;
CGRect newFrame = CGRectMake(0, -bottomOffset, self.frame.size.width, self.frame.size.height + bottomOffset);
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:newFrame];
self.physicsBody.categoryBitMask = FAWallCategory;
self.physicsBody.contactTestBitMask = FAAnimalCategory;
self.physicsBody.collisionBitMask = 0;
}
-(void)launchBody {
SKSpriteNode* animalSprite = [SKSpriteNode spriteNodeWithImageNamed:[animalImagesArray objectAtIndex:animalChoice]];
animalSprite.position = CGPointMake(self.size.width/2, -animalSprite.size.height);
animalSprite.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:25];
animalSprite.physicsBody.dynamic = YES;
animalSprite.physicsBody.allowsRotation = YES;
animalSprite.name = #"animalSprite";
animalSprite.physicsBody.categoryBitMask = FAAnimalCategory;
animalSprite.physicsBody.contactTestBitMask = FAWallCategory;
animalSprite.physicsBody.collisionBitMask = 0;
animalSprite.physicsBody.usesPreciseCollisionDetection = YES;
[self addChild:animalSprite];
}
Alright so it's late and I'm exhausted and I feel like an idiot..i was missing:
self.physicsWorld.contactDelegate = self;
tool

Accelerometer and Sprite Face Direction

I am making a simple game where my sprite is moved through the use of accelerometer. My sprite is a circle with eyes on it. I want to rotate the sprite in a way that it is always facing towards the direction it is moving. The below code successfully moves the sprite using the accelerometer but I am having trouble rotating the sprite to face the direction of the movement.
-(void) moveHeroFromAccelaration
{
GLKVector3 raw = GLKVector3Make(_motionManager.accelerometerData.acceleration.x,_motionManager.accelerometerData.acceleration.y,_motionManager.accelerometerData.acceleration.z);
if(GLKVector3AllEqualToScalar(raw, 0))
return;
static GLKVector3 ax, ay, az;
ay = GLKVector3Make(0.63f, 0.0f, -0.92f);
az = GLKVector3Make(0.0f, 1.0f, 0.0f);
ax = GLKVector3Normalize(GLKVector3CrossProduct(az, ay));
CGPoint accel2D = CGPointZero;
accel2D.x = GLKVector3DotProduct(raw, az); accel2D.y = GLKVector3DotProduct(raw, ax);
accel2D = CGPointNormalize(accel2D);
static const float steerDeadZone = 0.18;
if (fabsf(accel2D.x) < steerDeadZone) accel2D.x = 0; if (fabsf(accel2D.y) < steerDeadZone) accel2D.y = 0;
float maxAccelerationPerSecond = 160.0f;
_hero.physicsBody.velocity =
CGVectorMake(accel2D.x * maxAccelerationPerSecond, accel2D.y * maxAccelerationPerSecond);
//1
if (accel2D.x!=0 || accel2D.y!=0) {
//2
float orientationFromVelocity = CGPointToAngle(CGPointMake(_hero.physicsBody.velocity.dx,
_hero.physicsBody.velocity.dy));
float angleDelta = 0.0f;
//3
if (fabsf(orientationFromVelocity-_hero.zRotation)>1) { //prevent wild rotation
angleDelta = (orientationFromVelocity-_hero.zRotation);
} else {
//blend rotation
const float blendFactor = 0.25f; angleDelta =
(orientationFromVelocity - _hero.zRotation) * blendFactor; angleDelta =
ScalarShortestAngleBetween(_hero.zRotation, _hero.zRotation + angleDelta);
}
_hero.zRotation += angleDelta;
// face the hero in the moving direction
[_hero runAction:[SKAction rotateToAngle:orientationFromVelocity duration:0.25 shortestUnitArc:YES]]; <---- THIS IS WHERE I NEED HELP!
}
}

Resources