SceneKit transparent node, transparent material - ios

I try to create two node, one with transparent and one is nomal. There're same position nodes.
Code like following
//UIBezierPath *aPath = ....
// add transparent node
SCNMaterial *transparentMaterial = [SCNMaterial material];
UIImage *checkImage = [UIImage imageNamed:#"tree.png"];
transparentMaterial.diffuse.contents = checkImage;
SCNShape *transparentGeometry = [SCNShape shapeWithPath:aPath extrusionDepth:0.000001];
transparentMaterial.transparency = 0.000001;
transparentGeometry.materials = #[transparentMaterial];
SCNNode *transparentNode = [SCNNode new];
transparentNode.geometry = transparentGeometry;
transparentNode.transform = SCNMatrix4MakeRotation(M_PI_2, 1, 0, 0);
[root addChildNode:transparentNode];
// addd node
SCNMaterial *materal = [SCNMaterial material];
UIImage *checkImage1 = [UIImage imageNamed:#"tree.png"];
materal.diffuse.contents = checkImage1;
SCNShape *geometry = [SCNShape shapeWithPath:aPath extrusionDepth:0.00001];
geometry.materials = #[materal];
SCNNode *node = [SCNNode new];
node.geometry = geometry;
node.transform = SCNMatrix4Rotate(SCNMatrix4MakeRotation(M_PI_2, 1, 0, 0), M_PI_2 , 0, 0, 1);
[root addChildNode:node];
the problem is I can look through visible node via transparent node. Problem only occurred when visible node has material with image that has alpha channel inside (like my example image, it's has clear background).
it's bug of SceneKit? any help would be appreciated!
here is resource of image "tree.png"

Related

How to Move a Node towards camera by certain amount - SceneKit

I'm rendering a 3d model(car) using SceneKit.
Whenever user taps on a car, using SCNHitTestResult i'm trying to add annotation(a simple plane node).
//hit results are obtained using [sceneView hitTest:location options:nil]
SCNHitTestResult * result = hitResults[0];
if([result.node.name isEqualToString:#"Annotation"]){
[result.node removeFromParentNode];
return;
}
SCNMaterial *material = [SCNMaterial material];
material.diffuse.contents = [UIImage imageNamed:#"bug"];
SCNPlane *plane = [[SCNPlane alloc] init];
plane.width = 1.0;
plane.height = 1.0;
plane.cornerRadius = 0.5;
plane.firstMaterial = material;
SCNNode *planeNode = [[SCNNode alloc] init];
planeNode.position = result.worldCoordinates;
// planeNode.transform = cameraNode.transform;
planeNode.geometry = plane;
SCNBillboardConstraint *bbc = [[SCNBillboardConstraint alloc] init];
planeNode.constraints = #[bbc];
planeNode.name = #"Annotation";
[scene.rootNode addChildNode:planeNode];
Now the problem is, half of the plane(plane node added as annotation) gets hidden in the intersected node itself.
How can i prevent that... i dont want plane to be hidden. Ideally it should be circular plane. But half of it is missing. I'm thinking of moving it little bit towards the camera. Any help or suggestions will be helpful.

ARKit add snap Picture but it causes rotation

I create a project of AR app, then add on one tap gesture in view. But the picture is rotation. I found the self.sceneView.session.currentFrame.camera.transform causes the rotation, how to solve this?
- (void)handleTapGesture:(UITapGestureRecognizer *)tap {
SCNPlane * plane = [SCNPlane planeWithWidth:self.sceneView.bounds.size.width / 6000 height:self.sceneView.bounds.size.height / 6000];
UIImage * image = self.sceneView.snapshot;
plane.firstMaterial.diffuse.contents = image;
SCNNode * node = [SCNNode nodeWithGeometry:plane];
[self.sceneView.scene.rootNode addChildNode:node];
simd_float4x4 translation = matrix_identity_float4x4;
translation.columns[3][2] = -0.3;
translation = matrix_multiply(self.sceneView.session.currentFrame.camera.transform,translation);
node.simdTransform = translation;
}
I has not fond why camera transform has rotaion,but I multiply one tranform to fix it ,and it work well.
SCNMatrix4 stranslation = SCNMatrix4Translate(SCNMatrix4Identity, 0, 0, -0.3);
stranslation = SCNMatrix4Rotate(stranslation, M_PI_2, 0, 0, 1);
simd_float4x4 translation = SCNMatrix4ToMat4(stranslation);
translation = matrix_multiply(scameraTranstion,translation);

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.

How to change anchor point?

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

applying masks to SKEmitterNodes

May be some one can give me a hand… I’m trying to add a couple of SKEmitterNodes in their own SKCropNodes.
My code:
// left emitter node
NSString *path = [[NSBundle mainBundle] pathForResource:#"LeftParticle" ofType:#"sks"];
SKEmitterNode *lEmitterNode = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
// left crop node
SKSpriteNode *lMask = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:CGSizeMake(self.size.width/2, self.size.height)];
[lMask setAnchorPoint:CGPointZero];
SKCropNode *lCropNode = [SKCropNode node];
lCropNode.maskNode = lMask;
// move the left emitter under the mask
lEmitterNode.position = CGPointMake(CGRectGetMinX(lMask.frame) + lMask.size.width / 2, self.size.height);
[lCropNode addChild:lEmitterNode];
[self addChild:lCropNode];
// right emitter node
path = [[NSBundle mainBundle] pathForResource:#"RightParticle" ofType:#"sks"];
SKEmitterNode *rEmitterNode = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
// right crop node
SKSpriteNode *rMask = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(self.size.width/2, self.size.height)];
[rMask setAnchorPoint:CGPointZero];
rMask.position = CGPointMake(rMask.size.width, 0);
SKCropNode *rCropNode = [SKCropNode node];
rCropNode.maskNode = rMask;
// move the right emitter under the mask
rEmitterNode.position = CGPointMake(CGRectGetMinX(rMask.frame) + rMask.size.width / 2, self.size.height);
[rCropNode addChild:rEmitterNode];
[self addChild:rCropNode];
And this is the result:
As you can see, my red particles render under the left mask... Why?
I’ve tried to reduce the size of mask with:
lMask.xScale = lMask.yScale = 0.9;
rMask.xScale = rMask.yScale = 0.9;
And this is the result:
I presume it’s a problem with render buffer, or may be it’s something about zPosition, or a bug, or may be I’m really lost.
Thnx

Resources