I have a 3D sphere model saved as a dae file and loaded to xcode.
Problem is I cannot get it spinning/rotating - it just stays static... I've tried several ways, even tried to get the camera to move around it.
SCNScene *model = [SCNScene sceneNamed:#"model3.dae"];
SK3DNode *node = [[SK3DNode alloc] initWithViewportSize:CGSizeMake(50, 50)];
//workaround
id s1 = [node valueForKey:#"_scnRenderer"];
NSLog(#"%#", s1);
node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:node.frame.size.width/2];
node.physicsBody.affectedByGravity = NO;
node.physicsBody.allowsRotation = YES;
node.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[node setScnScene:model];
//THIS IS THE PART! I cannot get it to spin around
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:#"rotation"];
rotationAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(1, 2, 3, M_PI * 2)];
rotationAnimation.duration = 1;
rotationAnimation.repeatCount = FLT_MAX;
[model.rootNode addAnimation:rotationAnimation forKey:nil];
//camera
SCNCamera *camera = [SCNCamera camera];
camera.xFov = 0;
camera.yFov = 0;
camera.zNear = 0.0;
camera.zFar = 10.0;
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = camera;
cameraNode.position = SCNVector3Make(0, 0, 5);
[model.rootNode addChildNode:cameraNode];
node.pointOfView = cameraNode;
[world addChild:node];
Any ideas? Basically I want to try get the 3D model moving around inside the SK3DNode. Hope this makes sense. Think spinning planet.
Thanks in advance,
Alex
modifying the transform (by adding an animation, for instance) of the root node of a scene has no effect because the camera is held by a child node of that root node. The relative transform between the sphere and the camera stays the same. You should add an animation to the camera node or to the sphere node instead.
Related
I have rectangle shape paddle node, my question is - is it possible to "cut" node in half so when, for example ball, hit right side of node ball will go back with bigger angle, that it came, and same thing on other side. Im bad with words so, here are image of what I want to do :
For paddle node i use this code:
paddle = [[SKSpriteNode alloc] initWithImageNamed: #"board.png"];
paddle.name = paddleCategoryName;
paddle.position = CGPointMake(self.frame.origin.x + 50, CGRectGetMidY(self.frame));
[self addChild:paddle];
paddle.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:paddle.frame.size];
paddle.physicsBody.restitution = 0.1f;
paddle.physicsBody.friction = 0.4f;
paddle.physicsBody.dynamic = NO;
and for ball :
ball = [SKSpriteNode spriteNodeWithImageNamed: #"ball.png"];
[self addChild:ball];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width];
ball.physicsBody.friction = 0.0f;
ball.physicsBody.restitution = 1.0f;
ball.physicsBody.linearDamping = 0.0f;
ball.physicsBody.allowsRotation = NO;
I'm trying to set my camera node's rotation, and the value's are there, but it never changes from 0,0,0,0...
initialize the player node (left out other settings, the node has no geometry, but its physics body does have geometry)
playerNode = [SCNNode node];
and I set it's position and add it to the scene's root node...
- (void)viewDidLoad
{
[super viewDidLoad];
// create a new scene
SCNScene *scene = [SCNScene scene];
scene.physicsWorld.gravity = SCNVector3Make(0, -9, 0);
scene.physicsWorld.timeStep = 1.0/360;
// add world node
worldNode = [SCNNode node];
worldNode.name = #"world";
[scene.rootNode addChildNode:worldNode];
// add terrain
.../* terrain stuff */
// add player node
playerNode = [SCNNode node];
playerNode.name = #"player";
playerNode.position = SCNVector3Make(0, 0, 0);
playerNode.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:[SCNPhysicsShape shapeWithGeometry:[SCNCylinder cylinderWithRadius:0.2 height:1] options:nil]];
playerNode.physicsBody.angularDamping = 0.9999;
playerNode.physicsBody.damping = 0.9999;
playerNode.physicsBody.rollingFriction = 0;
playerNode.physicsBody.friction = 0;
playerNode.physicsBody.restitution = 0;
playerNode.physicsBody.velocityFactor = SCNVector3Make(1, 0, 1);
playerNode.physicsBody.categoryBitMask = playerCategory;
[scene.rootNode addChildNode:playerNode];
// create and add a camera to the scene
SCNNode *cameraNode = [SCNNode node];
[playerNode addChildNode:cameraNode];
cameraNode.camera = [SCNCamera camera];
cameraNode.camera.xFov = 53;
cameraNode.camera.zNear = 0.01;
cameraNode.camera.zFar = 5000;
// place the camera
cameraNode.position = SCNVector3Make(0, 0, 0);
.../* rest of view did load */
}
and then trying to set the rotation:
-(void)lookGestureRecognized:(UIPanGestureRecognizer *)gesture {
SCNView *scnView = (SCNView *)self.view;
CGPoint translation = [gesture translationInView:self.view];
NSLog(#"lookGestureRecognized: translation x %g y %g", translation.x, translation.y);
CGFloat hAngle = acos(((float)translation.x / 200) - (float)M_PI_2);
CGFloat vAngle = acos(((float)translation.y / 200) - (float)M_PI_2);
// rotate hero
[playerNode.physicsBody applyTorque:SCNVector4Make(0, 1, 0, hAngle) impulse:YES];
// tilt camera
[SCNTransaction setAnimationDuration:0.0];
elevation = MAX((float)-M_PI_4, MIN((float)M_PI_4, elevation + vAngle));
NSLog(#"elevation: %g", elevation);
SCNVector4 cameraRotation = SCNVector4Make(1, 0, 0, elevation);
cameraNode.rotation = cameraRotation;
// cameraNode.transform = SCNMatrix4Rotate(cameraNode.transform, 1, 0, 0, elevation); // tried this, didn't work either
NSLog(#"cameraNode.rotation = x %g y %g z %g, w %g", cameraNode.rotation.x, cameraNode.rotation.y, cameraNode.rotation.z, cameraNode.rotation.w);
// reset translation
[gesture setTranslation:CGPointZero inView:self.view];
}
the elevation is being calculated correctly, but trying to set it to the node's rotation fails... the log always says 0,0,0,0...
NSLog sample output:
2015-02-17 14:37:11.732 usingGestureRecognizer.01[96111:289778] lookGestureRecognized: translation x 0 y 0.5
2015-02-17 14:37:11.733 usingGestureRecognizer.01[96111:289778] elevation: -0.785398
2015-02-17 14:37:11.733 usingGestureRecognizer.01[96111:289778] cameraNode.rotation = x 0 y 0 z 0, w 0
Any ideas?
(Side note, mimic'ing the code I found from an example, translated it from swift to obj-c, and the sample code works perfectly)
The simple answer? I'm a newb.
The actual answer? Be very careful when copying code from a tutorial... I had declared a private variable SCCNode cameraNode, and was trying to change this node's rotation, however, the actual camera node doing the camera work was declared as a private method variable in viewDidLoad...
So, again, thank you very much for your help guys, this site is invaluable to me, I have learned so much, but I'm personally 0 for 2 asking questions, both of mine have just been MY oversights. Thanks again, sincerely
I am playing around with scene kit.
I do not know a lot about modeling but i created a very basic Sketchup model with no materials or textures.
I exported the model from ketchup and imported it into the scene.
As i move the camera around towards one end of the model the rear disappears and vice versa. As the camera rotates towards the front the rear gets shadowed in black.
What is the reason for this?
Lighting? Here is the code for the scene. Its a basic Xcode game project
// create a new scene
SCNScene *scene = [SCNScene sceneNamed:#"ship_transport.dae"];
// 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, 100);
// 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 whiteColor];
[scene.rootNode addChildNode:ambientLightNode];
// retrieve the ship node
SCNNode *ship = [scene.rootNode childNodeWithName:#"ship" recursively:YES];
ship.geometry.firstMaterial.diffuse.contents = [UIColor redColor];
ship.geometry.firstMaterial.specular.contents = [UIColor whiteColor];
SCNVector3 vector = SCNVector3Make(.1, .1, .1);
[ship setScale:vector];
//[scene.rootNode addChildNode:lightNode];
// animate the 3d object
[ship runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:0 z:0 duration:1]]];
// retrieve the SCNView
SCNView *scnView = (SCNView *)self.view;
scnView.autoenablesDefaultLighting = true;
// set the scene to the view
scnView.scene = scene;
// allows the user to manipulate the camera
scnView.allowsCameraControl = YES;
// show statistics such as fps and timing information
scnView.showsStatistics = YES;
// configure the view
scnView.backgroundColor = [UIColor darkGrayColor];
Try setting the zFar property on the camera. Other related properties to try changing would be the xFov and yFov.
I'm working with SceneKit. The object SCNNode is rotated relative to the center. How to change anchor point of the SCNNode?
SCNScene *scene = [SCNScene new];
SCNBox *boxGeometry = [SCNBox boxWithWidth:384.f height:512.f length:20.f chamferRadius:0];
SCNMaterial *material = [SCNMaterial new];
material.diffuse.contents = [UIImage imageNamed:#"material"];
SCNNode *boxNode = [SCNNode nodeWithGeometry:boxGeometry];
boxNode.geometry.firstMaterial = material;
boxNode.pivot = SCNMatrix4MakeTranslation(0.5f, 0.5f, 0.5f);
[scene.rootNode addChildNode:boxNode];
self.sceneView.scene = scene;
self.sceneView.allowsCameraControl = YES;
Your pivot transform translation is very small compared to the size of your box. It's not normalized.
If you want to translate around one of the corners you should translate half of the side in all directions.
boxNode.pivot = SCNMatrix4MakeTranslation(384.0/2.0, 512.0/2.0, 20.0/2.0);
As a simple example :
yourSceneNode.pivot = SCNMatrix4MakeTranslation(0.5, 0.5, 0.5),
where you change the node's position, rotation and scale properties.
SCNNode class reference explains this nicely
I'm testing out pin joints with Sprite Kit, and I'm finding something unusual happening.
My desired setup is this: one wide, flat box, and two circles; the circles are connected via SKPhysicsPinJoints to the box, so they can act as wheels.
Here's my code. I've tried to make it as concise as possible:
- (SKNode*) createWheelWithRadius:(float)wheelRadius {
CGRect wheelRect = CGRectMake(-wheelRadius, -wheelRadius, wheelRadius*2, wheelRadius*2);
SKShapeNode* wheelNode = [[SKShapeNode alloc] init];
wheelNode.path = [UIBezierPath bezierPathWithOvalInRect:wheelRect].CGPath;
wheelNode.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:wheelRadius];
return wheelNode;
}
- (void) createCar {
// Create the car
SKSpriteNode* carNode = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(150, 50)];
carNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carNode.size];
carNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild:carNode];
// Create the left wheel
SKNode* leftWheelNode = [self createWheelWithRadius:30];
leftWheelNode.position = CGPointMake(carNode.position.x-80, carNode.position.y);
[self addChild:leftWheelNode];
// Create the right wheel
SKNode* rightWheelNode = [self createWheelWithRadius:30];
rightWheelNode.position = CGPointMake(carNode.position.x+80, carNode.position.y);
[self addChild:rightWheelNode];
// Attach the wheels to the body
CGPoint leftWheelPosition = leftWheelNode.position;
CGPoint rightWheelPosition = rightWheelNode.position;
SKPhysicsJointPin* leftPinJoint = [SKPhysicsJointPin jointWithBodyA:carNode.physicsBody bodyB:leftWheelNode.physicsBody anchor:leftWheelPosition];
SKPhysicsJointPin* rightPinJoint = [SKPhysicsJointPin jointWithBodyA:carNode.physicsBody bodyB:rightWheelNode.physicsBody anchor:rightWheelPosition];
[self.physicsWorld addJoint:leftPinJoint];
[self.physicsWorld addJoint:rightPinJoint];
}
What I'm expecting is that the pin joints are anchored at their centre points; however, when I test this, the anchors for the joints appear to be far off.
Am I missing something really obvious?
I also had this issue and the cause is setting the physics body before setting the sprites position.
carNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carNode.size];
carNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
Change the above to
carNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
carNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carNode.size];
It should work. Thanks Smick.
SpriteKit: How to create Basic Physics Joints
Try this code, I used yours and got weird issues, so started from scratch.
- (SKShapeNode*) makeWheel
{
SKShapeNode *wheel = [[SKShapeNode alloc] init];
CGMutablePathRef myPath = CGPathCreateMutable();
CGPathAddArc(myPath, NULL, 0,0, 16, 0, M_PI*2, YES);
wheel.path = myPath;
return wheel;
}
- (void) createCar
{
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)];
// 1. car body
SKSpriteNode *carBody = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(120, 8)];
carBody.position = CGPointMake(200, 200);
carBody.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carBody.size];
[self addChild:carBody];
// 2. wheels
SKShapeNode *leftWheel = [self makeWheel];
leftWheel.position = CGPointMake(carBody.position.x - carBody.size.width / 2, carBody.position.y);
leftWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:16];
[self addChild:leftWheel];
SKShapeNode *rightWheel = [self makeWheel];
rightWheel.position = CGPointMake(carBody.position.x + carBody.size.width / 2, carBody.position.y);
rightWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:16];
[self addChild:rightWheel];
// 3. Join wheels to car
[self.physicsWorld addJoint:[SKPhysicsJointPin jointWithBodyA:carBody.physicsBody bodyB:leftWheel.physicsBody anchor:leftWheel.position]];
[self.physicsWorld addJoint:[SKPhysicsJointPin jointWithBodyA:carBody.physicsBody bodyB:rightWheel.physicsBody anchor:rightWheel.position]];
// 4. drive car
[carBody.physicsBody applyForce:CGVectorMake(10, 0)];
}