-(void)renderFrameQCAR{[selfsetFramebuffer];// Clear colour and depth buffers
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);// Render video background and retrieve tracking state
QCAR::Statestate=QCAR::Renderer::getInstance().begin();QCAR::Renderer::getInstance().drawVideoBackground();// ...
for(inti=0;i<state.getNumTrackableResults();++i){// Get the trackable
constQCAR::TrackableResult*result=state.getTrackableResult(i);constQCAR::Trackable&trackable=result->getTrackable();// Choose the index based on the ImageTarget name
inttargetIndex=0;// "stones"
if(!strcmp(trackable.getName(),"chips"))targetIndex=1;elseif(!strcmp(trackable.getName(),"tarmac"))targetIndex=2;elseif(!strcmp(trackable.getName(),"ARCODE1"))targetIndex=3;if(targetIndex==3){[selfperformSelectorOnMainThread:@selector(showMyView)withObject:nilwaitUntilDone:NO];}SampleApplicationUtils::checkGlError("EAGLView renderFrameQCAR");}// ...
[selfpresentFramebuffer];}
// size: 200x200, opaque: true, scale: 1(0:screen scale)
UIGraphicsBeginImageContextWithOptions(CGSize(width:200,height:200),true,1)// drawing commands
CGContextSetRGBFillColor(context,1,1,0,1);// ...
// getting an image from it
letimage=UIGraphicsGetImageFromCurrentImageContext()UIGraphicsEndImageContext()
Core image with filter
// create a UIImage
letimage=UIImage(named:"c0415")// create Core Image context
letciContext=CIContext(options:nil)// create a CIImage(image data for processing)
letcoreImage=CIImage(image:image)// picking the filter
//let filter = CIFilter(name: "CIPhotoEffectTransfer")
letfilter=CIFilter(name:"CIVignetteEffect")// passing image
filter.setValue(coreImage,forKey:kCIInputImageKey)// set a custom value for the inputCenter
filter.setValue(CIVector(x:xpos,y:ypos),forKey:kCIInputCenterKey)// retrieve the processed image
letfilteredImageData=filter.valueForKey(kCIOutputImageKey)asCIImage// returns a Quartz image from the Core Image context
letfilteredImageRef=ciContext.createCGImage(filteredImageData,fromRect:filteredImageData.extent())// this is our final UIImage ready to be displayed
letfilteredImage=UIImage(CGImage:filteredImageRef);
drawing text
// select a font
letfont=UIFont.boldSystemFontOfSize(44)letshowText:NSString="hello world"// setting attr: font name, color...etc.
letattr=[NSFontAttributeName:font,NSForegroundColorAttributeName:UIColor.whiteColor()]// getting size
letsizeOfText=showText.sizeWithAttributes(attr)letimage=UIImage(named:"c0415")letrect=CGRectMake(0,0,image!.size.width,image!.size.height)UIGraphicsBeginImageContextWithOptions(CGSize(width:rect.size.width,height:rect.size.height),true,0)// drawing our image to the graphics context
image?.drawInRect(rect)// drawing text
showText.drawInRect(CGRectMake(rect.size.width-sizeOfText.width-10,rect.size.height-sizeOfText.height-10,rect.size.width,rect.size.height),withAttributes:attr)// getting an image from it
letnewImage=UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext()
// Load two scenes
SCNScene*mainScene=[SCNScenesceneNmaed:@"level.dae"];SCNScene*characterScene=[SCNScenesceneNamed:@"monkey.dae"];// Get the monkey
SCNNode*monkey=[characterScene.rootNodechildNodeWithName:@"monkey"recursively:YES];// Add a monkey to the level
[mainScene.rootNodeaddChildNode:monkey];// Add another monkey to the level
[mainScene.rootNodeaddChildeNode:[monkeyclone]];
Behaviors
Animating characters
skinned-character.da
run.dae
jump.dae
idle.dae
// Load an animation
CAAnimation*anim=[sceneSourceentryWithIdentifier:animationNamewithClass:[CAAnimationclass]];// Play it
[characteraddAnimation:animforKey:@"run"];
Moving characters
Collision Detection
// Be notified through delegation
-(void)physicsWorld:(SCNPhysicsWorld*)worlddidBeginContact:(SCNPhysicsContact*)contact;// Or explicitly perform ray tests
-(NSArray*)rayTestWithSegmentFromPoint:(SCNVector3)origintoPoint:(SCNVector3)destoptions:(NSDictionary*)options;// Animating items
[aBananarunAction:[SCNActionrepeatActionForever:[SCNActionrotateByX:0.0y:2.0*M_PIz:0.0duration:2.0]]];
Particles
// Load a particle system
SCNParticleSystem*particleSystem=[SCNParticleSystemparticleSystemNamed:@"dust.scnp"inDirectory:@"art.scnassets/particles"];// Attach to a node
[characteraddparticleSystem:particleSystem];// Control emission
particleSystem.birthRate=shouldEmit?aBirthRate:0;
// Assign the scene
aSCNView.scene=aScene;// modifiy a node
aNode.position=SCNVector3Make(0,0,0);aNode.scale=SCNVector3Make(2,2,2);aNode.rotation=SCNVector4Make(x,y,z,angle);aNode.opacity=0.5;
Animating a Scene
Per-frame updates
Animations
Actions *new*
Physics
Constraints
Animations
// Begin a transaction
[SCNTransactionbegin];[SCNTransationsetAnimationDuration:2.0];// Change properties
aNode.opacity=1.0;aNode.rotation=SCNVector4(0,1,0,M_PI*4);// Commit
[SCNTransactioncommit];
or
// Create a animation
animation=[CABasicAnimationanimationWithKeyPath:@"rotation"];// Configure
animation.duration=2.0;animation.toValue=[NSValuevalueWithSCNVector4:SCNVector4Make(0,1,0,M_PI*2)];animation.repeatCount=MAXFLOAT;// Play the animation
[aNodeaddAnimation:animationforKey:@"myAnimation"];
Animation Events
Smooth transitions
// 音效 Playing a sound at 60 percent
SCNAnimationEvent*anEvent=[SCNAnimationEventanimationEventWithKeyTime:0.6block:aSoundBlock];anAnimation.animationEvents=@[anEvent,anotherEvent];
// Dynamic body: Make a node dynamic
aNode.physicsBody=[SCNPhysicsBodydynamicBody];// Manipulate with forces
// Apply an impulse
[aNode.phsicsBodyappleyForce:aVector3atPosition:aVector3impulse:YES];// Staic bodies: Make a node static
aNode.physicsBody=[SCNPhysicsBodystaticBody];// Kinematic body: Make a node kinematic(不受碰撞/重力影響,但是可以用程式的方式加入速度)
aNode.physicsBody=[SCNPhysicsBodykinematicBody];// Physics shape: SceneKit 會自動建立,也可以用手動的方式指定,如下:
aNode.physicsBody.physicsShape=[SCNPhysicsShapeshapeWithGeometry:aGeometryoptions:options];// Physics behavior
SCNPhysicsHingeJoint*joint=[SCNPhysicsHingeJointjointWithBodyA:nodeA.physicsBodyaxisA:[...]anchorA:[...]jointWithBodyB:nodeB.physicsBodyaxisB:[...]anchorB:[...]];[scene.physicsWorldaddBehavior:joint];// Remove behavior
[scene.physicsWorldremoveBehavior:joint];
Constraints
Applied sequentially at render time
Only affect presentation values
aNode.constraints=@[aConstraints,anotherConstraints,...];// Custom constraint on a node's transform
aConstrains=[SCNTransformConstraintransformConstrainInWorldSpace:YeswithBlock:^SCNMatrix4(SCNNode*node,SCNMatrix4transform){transform.m43=0.0;returntransform;}];// Makes a node to look at another node: 頭部/眼睛/攝影機都適用
nodeA.constraints=@[SCNLookAtConstraintlookAtConstrainWithTarget:nodeB];//SCNIKConstraint:拳頭朝目標物體揮動,連帶會牽動手臂及全身
// Color
material.diffuse.contents=[UIColorredColor];// Image
material.diffuse.contents=@"slate.jpg";// SKTexture
material.normal.content=[SKTexturetextureByGeneratingNormalMap];// Dynamic content:Video using SKVideo node
// Cube map
/*
Top
Left Back Right Front
Bottom
*/material.reflective.contents=@[@"right.png",@"left.png",...@"front"];// Custom material: Shader Modifier
// 常用在液體流動材質的呈現或是光暈的表現
material.shaderModifiers=@{<EntryPoint>:<GLSLCode>};// SpriteKit Overlays
sceneView.overlaySKScene=aSKScene;
// Load a technique
SCNTechnique*technique=[SCNTechniquetechniqueWithDictionary:aDictionary];// Chain techniques
technique=[SCNTechniquetechniqueBySequencingTechniques:@[t1,t2...]];// Set a technique
aSCNView.technique=technique;