StackUnderflow
StackUnderflow

Reputation: 2463

How to do flat shaded polygons/geometry in SceneKit i.e. not smooth

I'm trying to make my geometry look flat and not smooth in SceneKit. As you can see in the images, the green sphere has smooth shading by default in SceneKit. What I want is the flat "look" in the other image where it says "flat".

SCNSphere SmoothVSFlat I don't see any options in SceneKit on how to disable this feature? This is the code from my playground:

import Cocoa
import SceneKit
import QuartzCore
import XCPlayground

var sceneView = SCNView(frame:CGRect(x:0, y:0, width:300, height:300))
var scene = SCNScene()
sceneView.backgroundColor = NSColor.darkGrayColor()
sceneView.scene = scene
sceneView.autoenablesDefaultLighting = true
XCPlaygroundPage.currentPage.liveView = sceneView

let g = SCNSphere(radius:1)
g.firstMaterial?.diffuse.contents = NSColor.greenColor()
g.firstMaterial?.litPerPixel = false
g.segmentCount = 5
let node = SCNNode(geometry:g)
node.position = SCNVector3(x:0, y:0, z:0)
scene.rootNode.addChildNode(node)

var spin = CABasicAnimation(keyPath:"rotation")
spin.toValue = NSValue(SCNVector4:SCNVector4(x:1, y:1, z:0, w:CGFloat(2.0*M_PI)))
spin.duration = 3
spin.repeatCount = HUGE
node.addAnimation(spin, forKey:"spin")

Upvotes: 4

Views: 2313

Answers (1)

ooOlly
ooOlly

Reputation: 2127

It seems Apple will apply normal smoothing for you. This is more observe when SceneKit encounter a flat mesh. Remove the smoothed normals from mesh will make it looks low polygon.

If you use ModelI/O to load 3D asset. (For test I create MDLMesh form SCNGeometry)

SCNGeometry* flatGeoUsingModelIO(SCNGeometry *geo){
    MDLMesh *mesh = [MDLMesh meshWithSCNGeometry:geo];
    MDLMesh *newMesh = [MDLMesh newSubdividedMesh:mesh submeshIndex:0 subdivisionLevels:0];
    [newMesh removeAttributeNamed:@"normals"];
    //Replace current vertex normals with a non-smooth one. Same result with above line
    //[newMesh addNormalsWithAttributeNamed:@"normals" creaseThreshold:1];
    SCNGeometry *flatGeo = [SCNGeometry geometryWithMDLMesh:newMesh];
    return flatGeo;
}

Or you are more familiar to SceneKit.

SCNGeometry* flatGeoUsingScnKit(SCNGeometry *geo){
    NSArray<SCNGeometrySource*> *SourceArr = geo.geometrySources;
    NSMutableArray<SCNGeometrySource*> *newSourceArr = [NSMutableArray new];
    for (SCNGeometrySource *source in SourceArr) {
        if (source.semantic != SCNGeometrySourceSemanticNormal) {
            [newSourceArr addObject:source];
        }
    }
    SCNGeometry *flatGeo = [SCNGeometry geometryWithSources:newSourceArr elements:geo.geometryElements];
    return flatGeo;
}

This is low polygon SCNSphere created from right one.

enter image description here

Upvotes: 2

Related Questions