I’m making a primary interactive globe utilizing SceneKit and SCNNodes. My most important SCNNode, the earth node, is meant to be formed as a sphere (with no background). The background added to a scene is a .scnp star constellation. Once I rotate the globe a black background seems on the EarthNode which covers the SCNParticleSystem. This black background does not at all times seem however normally exhibits up when the globe is rotated.
I attempted: sceneView.backgroundColor = .clear
however this did not work.
import Basis
import SceneKit
import CoreImage
import SwiftUI
import MapKit
public typealias GenericController = UIViewController
public typealias GenericColor = UIColor
public typealias GenericImage = UIImage
public class GlobeViewController: GenericController {
//@Binding var showProf: Bool
var nodePos: CGPoint? = nil
public var earthNode: SCNNode!
non-public var sceneView : SCNView!
non-public var cameraNode: SCNNode!
non-public var worldMapImage: CGImage {
guard let picture = UIImage(named: "earth-dark")?.cgImage else {
fatalError("Not discovered")
}
return picture
}
non-public var dotCount = 50000
public init(earthRadius: Double) {//, showProf: Binding<Bool>
self.earthRadius = earthRadius
//self._showProf = showProf
tremendous.init(nibName: nil, bundle: nil)
}
public init(earthRadius: Double, dotCount: Int) {//, showProf: Binding<Bool>
self.earthRadius = earthRadius
self.dotCount = dotCount
//self._showProf = showProf
tremendous.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been carried out")
}
public override func touchesBegan(_ touches: Set<UITouch>, with occasion: UIEvent?) {
guard let contact = touches.first, contact.view == self.sceneView else {
return
}
let touchLocation = contact.location(in: sceneView)
let hitTestResults = sceneView.hitTest(touchLocation, choices: nil)
let touchLocation3D = sceneView.unprojectPoint(SCNVector3(Float(touchLocation.x), Float(touchLocation.y), 0.0))
print(touchLocation3D)
if let tappedNode = hitTestResults.first?.node {
print(tappedNode)
// Deal with the tapped node
if tappedNode.identify == "NewYorkDot" {
// That is the New York dot, carry out your motion right here
print("Tapped on New York! Place: (tappedNode.place)")
} else if tappedNode.identify == "RegularDot" {
// Deal with different nodes if wanted
print("Tapped on an everyday dot. Place: (tappedNode.place)")
}
}
}
public override func viewDidLoad() {
tremendous.viewDidLoad()
setupScene()
setupParticles()
setupCamera()
setupGlobe()
setupDotGeometry()
}
non-public func setupScene() {
let scene = SCNScene()
sceneView = SCNView(body: view.body)
sceneView.scene = scene
// let tapGesture = UITapGestureRecognizer(goal: self, motion: #selector(handleTap(_:)))
// sceneView.addGestureRecognizer(tapGesture)
sceneView.showsStatistics = true
sceneView.backgroundColor = .clear
sceneView.allowsCameraControl = true
sceneView.isUserInteractionEnabled = true
self.view.addSubview(sceneView)
}
non-public func setupParticles() {
guard let stars = SCNParticleSystem(named: "StarsParticles.scnp", inDirectory: nil) else { return }
stars.isLightingEnabled = false
if sceneView != nil {
sceneView.scene?.rootNode.addParticleSystem(stars)
}
}
non-public func setupCamera() {
self.cameraNode = SCNNode()
cameraNode.digicam = SCNCamera()
cameraNode.place = SCNVector3(x: 0, y: 0, z: 5)
sceneView.scene?.rootNode.addChildNode(cameraNode)
}
non-public func setupGlobe() {
self.earthNode = EarthNode(radius: earthRadius, earthColor: earthColor, earthGlow: glowColor, earthReflection: reflectionColor)
sceneView.scene?.rootNode.addChildNode(earthNode)
}
non-public func setupDotGeometry() {
let textureMap = generateTextureMap(dots: dotCount, sphereRadius: CGFloat(earthRadius))
let newYork = CLLocationCoordinate2D(latitude: 44.0682, longitude: -121.3153)
let newYorkDot = closestDotPosition(to: newYork, in: textureMap)
let dotColor = GenericColor(white: 1, alpha: 1)
let oceanColor = GenericColor(cgColor: UIColor.systemRed.cgColor)
let highlightColor = GenericColor(cgColor: UIColor.systemRed.cgColor)
// threshold to find out if the pixel within the earth-dark.jpg represents terrain (0.03 represents rgb(7.65,7.65,7.65), which is sort of black)
let threshold: CGFloat = 0.03
let dotGeometry = SCNSphere(radius: dotRadius)
dotGeometry.firstMaterial?.diffuse.contents = dotColor
dotGeometry.firstMaterial?.lightingModel = SCNMaterial.LightingModel.fixed
let highlightGeometry = SCNSphere(radius: dotRadius)
highlightGeometry.firstMaterial?.diffuse.contents = highlightColor
highlightGeometry.firstMaterial?.lightingModel = SCNMaterial.LightingModel.fixed
let oceanGeometry = SCNSphere(radius: dotRadius)
oceanGeometry.firstMaterial?.diffuse.contents = oceanColor
oceanGeometry.firstMaterial?.lightingModel = SCNMaterial.LightingModel.fixed
var positions = [SCNVector3]()
var dotNodes = [SCNNode]()
var highlightedNode: SCNNode? = nil
for i in 0...textureMap.rely - 1 {
let u = textureMap[i].x
let v = textureMap[i].y
let pixelColor = self.getPixelColor(x: Int(u), y: Int(v))
let isHighlight = u == newYorkDot.x && v == newYorkDot.y
if (isHighlight) {
let dotNode = SCNNode(geometry: highlightGeometry)
dotNode.identify = "NewYorkDot"
dotNode.place = textureMap[i].place
positions.append(dotNode.place)
dotNodes.append(dotNode)
print("myloc (textureMap[i].place)")
highlightedNode = dotNode
} else if (pixelColor.crimson < threshold && pixelColor.inexperienced < threshold && pixelColor.blue < threshold) {
let dotNode = SCNNode(geometry: dotGeometry)
dotNode.identify = "Different"
dotNode.place = textureMap[i].place
positions.append(dotNode.place)
dotNodes.append(dotNode)
}
}
DispatchQueue.most important.async {
let dotPositions = positions as NSArray
let dotIndices = NSArray()
let supply = SCNGeometrySource(vertices: dotPositions as! [SCNVector3])
let factor = SCNGeometryElement(indices: dotIndices as! [Int32], primitiveType: .level)
let pointCloud = SCNGeometry(sources: [source], components: [element])
let pointCloudNode = SCNNode(geometry: pointCloud)
for dotNode in dotNodes {
pointCloudNode.addChildNode(dotNode)
}
self.sceneView.scene?.rootNode.addChildNode(pointCloudNode)
}
}
}
typealias GenericControllerRepresentable = UIViewControllerRepresentable
@accessible(iOS 13.0, *)
non-public struct GlobeViewControllerRepresentable: GenericControllerRepresentable {
var particles: SCNParticleSystem? = nil
//@Binding public var showProf: Bool
func makeUIViewController(context: Context) -> GlobeViewController {
let globeController = GlobeViewController(earthRadius: 1.0)//, showProf: $showProf
updateGlobeController(globeController)
return globeController
}
func updateUIViewController(_ uiViewController: GlobeViewController, context: Context) {
updateGlobeController(uiViewController)
}
non-public func updateGlobeController(_ globeController: GlobeViewController) {
globeController.dotSize = CGFloat(0.005)
globeController.enablesParticles = true
if let particles = particles {
globeController.particles = particles
}
}
}
@accessible(iOS 13.0, *)
public struct GlobeView: View {
//@Binding public var showProf: Bool
public var physique: some View {
GlobeViewControllerRepresentable()//showProf: $showProf
}
}