5

I am drawing a sphere in Scene Kit, and it all works ok. I am drawing it like so:

   ...
   let g = SCNSphere(radius: radius)
   geometria.firstMaterial?.diffuse.contents = myColor
   let node = SCNNode(geometry: g)
   node.position = SCNVector3(x: x, y: y, z: z)
   scene.rootNode.addChildNode(node)

This draws the sphere with a smooth surface (see image). I would enter image description here

What I am trying to accomplish is to have the sphere not rendered "smooth" like in the photo but I want to be able to have it so it shows the skeleton... so maybe control how many triangles it uses to draw the surface of the sphere but the triangles need to be empty, so I would just see the sides of the triangles...

Any suggestion?

So here's an image of what zI am trying to make the sphere look like: enter image description here

zumzum
  • 17,984
  • 26
  • 111
  • 172
  • Just the edges of each triangle? – David Rönnqvist Nov 19 '14 at 17:14
  • 8
    to do that you need the `SCNGeometryPrimitiveTypeLine` primitive type. There is no API to create a sphere of that type, but you can instantiate an `SCNSphere` and then create a custom `SCNGeometry` by reusing the geometry sources (`SCNGeometrySource`) from the sphere and create new geometry elements (`SCNGeometryElement`) of type `SCNGeometryPrimitiveTypeLine` – mnuages Nov 19 '14 at 17:35
  • 1
    @mnuages: that's worth posting as an answer. – rickster Mar 05 '15 at 15:37
  • Possible duplicate of [Render an SCNGeometry as a wireframe](https://stackoverflow.com/questions/28793982/render-an-scngeometry-as-a-wireframe) – Morty Jul 15 '17 at 19:00

2 Answers2

4
  • Your wish #1: "not smooth" sphere
  • Your wish #2: wireframe

Past this into Xcode playground:

import Cocoa
import SceneKit
import QuartzCore
import XCPlayground

// create a scene
var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
var scene = SCNScene()
sceneView.scene = scene
XCPShowView("The Scene View", sceneView)
sceneView.autoenablesDefaultLighting = false

// create sphere
let g = SCNSphere(radius: 100)
g.firstMaterial?.diffuse.contents = NSColor.greenColor()

// WISH #1    
g.segmentCount = 12

let node = SCNNode(geometry: g)
node.position = SCNVector3(x: 10, y: 10, z: 10)
scene.rootNode.addChildNode(node)

// WISH #2
glPolygonMode(GLenum(GL_FRONT), GLenum(GL_LINE));
glPolygonMode(GLenum(GL_BACK), GLenum(GL_LINE));

// animate
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 // for infinity
node.addAnimation(spin, forKey: "spin around")
Ef Dot
  • 768
  • 6
  • 18
  • This only *happens* to work in the current version — it relies on state that isn't guaranteed, so I wouldn't count on it continuing to work everywhere. To call `glPolygonMode` or other OpenGL (ES) APIs, there needs to be a current GL context. You haven't created one, or made sure that your code works with the same GL context SceneKit renders into, so it's only a happy accident that said context is active when you call `glPolygonMode`. – rickster Mar 05 '15 at 15:43
  • Also, throwing GL calls like this around SceneKit code, if it works, is going to affect the entire scene — if you have some nodes you want drawn in wireframe and some you don't, this won't help. – rickster Mar 05 '15 at 15:43
  • @rickster Yes, of course, your are right, I just humbly demonstrated possibility :). For real, I really can't recommend (_for now_) using Swift for GL stuff, it is slower in orders of magnitude than C/Obj-C mix. And yes, SceneKit is sitll work-in-progress. For wireframe stuff you should of course use [SCNNodeRendererDelegate](https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SCNNodeRendererDelegate_Protocol/index.html#//apple_ref/occ/intfm/SCNNodeRendererDelegate/renderNode:renderer:arguments:) and save/restore state as needed. – Ef Dot Mar 05 '15 at 21:51
  • I copied and pasted the given code in Playground. It gave me a few errors. I fixed them all but one complaining about glPolygonMode, it says use of unresolved identifier. Even if I comment out Wish #2 on the right I see no scene. – zumzum Mar 06 '15 at 02:53
  • @zumzum Strange... just now copied into new Playground and it works as expected - Xcode 6.1.1, Yosemite 10.10.2 – Ef Dot Mar 06 '15 at 13:38
  • Ok, I'll make sure to check on the version again, I thought I did have the latest. I'll double check. – zumzum Mar 06 '15 at 13:40
4

Taken from the possible duplicate question Render an SCNGeometry as a wireframe, I'm going to copy it here for posterity:

it's possible to set the fillMode of the Material to just lines, which gives the desired effect:

g.firstMaterial?.fillMode = .lines 
// (or possibly geometria.firstMaterial?.fillMode, not clear from your example)

you can then change the 'resolution' of the wireframe using:

g.segmentCount = 12 
// 48 is the default, lower is 'coarser', less than 3 
// is undefined and therefore unsupported

and you can probably also want to set:

g.isGeodesic = true

... which will give you triangular 'tiles' on your wireframe rather than the default rectangles.

mistertim
  • 5,123
  • 4
  • 20
  • 27
  • Definitely answers the question, someone should add a shader based way to make the lines thicker as this method produces 1pt wide lines which are barely visible. – Dan M Jan 18 '22 at 02:54
  • 12 years later and this saved me. Love u man – Jide Jacobs Apr 16 '22 at 22:17