Oh my Word guys, the solution was as simple as can be but what a challenge.
The line above:
precessionNode.simdTransform =
float4x4([Float(0.5.squareRoot()),Float(0.5.squareRoot()),0,0],
[-Float(0.5.squareRoot()),Float(0.5.squareRoot()),0,0],[0,0,1,0],[0,0,0,0])
needed to be:
precessionNode.simdTransform =
float4x4([Float(0.5.squareRoot()),Float(0.5.squareRoot()),0,0],
[-Float(0.5.squareRoot()),Float(0.5.squareRoot()),0,0],[0,0,1,0],[0,0,0,1])
How it got corrupted idk. One little character!
Post
Replies
Boosts
Views
Activity
OK, took a while. Here is a greatly reduced bit of code that should, but does not show my nodes.
// ContentView.swift
// SendToForum
//
// Created on 1/25/25.
//
import SwiftUI
import SceneKit
struct ContentView: View {
@State private var fs_cv = "2"
private let scene = makeAScene()
private struct box: Identifiable {
let radius: Int
let position: [simd_float3]
var id: String { String(radius) }
}
private let boxFlake:[box] = [
box(radius: 0, position: [ simd_float3(0, 0, 0)]),
box(radius: 1, position: [ simd_float3(0, 1, 0),
simd_float3(0, -1, 0),
simd_float3(1, 0, 0),
simd_float3(-1, 0, 0) ]),
box(radius: 2, position: [ simd_float3(0, 2, 0),
simd_float3(0, -2, 0),
simd_float3(2, 0, 0),
simd_float3(-2, 0, 0) ]),
box(radius: 3, position: [ simd_float3(3, 3, 0),
simd_float3(3, -3, 0),
simd_float3(-3, 3, 0),
simd_float3(-3, -3, 0) ])
]
var body: some View {
ZStack(alignment: .topTrailing) {
SceneView(scene: scene, options: [.autoenablesDefaultLighting,
.allowsCameraControl, .rendersContinuously])
Picker(""
, selection: self.$fs_cv) {
let boxFlakeList: [String] = ["0","1","2","3"]
ForEach( boxFlakeList, id: \.self ) { Num in Text(Num) }
}.fixedSize()
.onChange(of: fs_cv, {
let selected_boxFlake:[box] = boxFlake.dropLast( 3 - (fs_cv as
NSString).integerValue )
redraw_animate_scene(boxFlake: selected_boxFlake)
} // .onChange(of: fs_cv
) // .onChange
}
} // var body: some View
private func redraw_animate_scene(boxFlake: [box]) {
for box in boxFlake {
for position in box.position {
position.pNode(drawIntoNode: scene.rootNode.childNode(withName: "Spin",
recursively: true)!, radius: String(box.radius))
}
}
animate(node: scene.rootNode)
} // func redraw_animate_scene()
} // struct ContentView: View
func makeAScene() -> SCNScene {
let precessionNode = SCNNode()
let SpinNode = SCNNode()
precessionNode.name = "precession"
precessionNode.simdPosition = SIMD3<Float>(0,0,0)
precessionNode.simdTransform =
float4x4([Float(0.5.squareRoot()),Float(0.5.squareRoot()),0,0],
[-Float(0.5.squareRoot()),Float(0.5.squareRoot()),0,0],[0,0,1,0],[0,0,0,0])
SpinNode.name = "Spin"
SpinNode.simdPosition = SIMD3<Float>(0, 0, 0)
let newScene = SCNScene()
newScene.rootNode.addChildNode(precessionNode)
newScene.rootNode.childNode(withName: "precession", recursively:
true)?.addChildNode(SpinNode)
// newScene.fogDensityExponent = 0.0
newScene.background.contents = NSColor.black
newScene.rootNode.camera = SCNCamera()
newScene.rootNode.camera?.usesOrthographicProjection = true // @abstract
Determines whether the receiver uses an orthographic projection or not.
Defaults to NO. INVISIBLE WITHOUT IT!
newScene.rootNode.camera?.orthographicScale = 20 // the bigger
the number the smaller the image Without specifying 20 view is too close to
nucleus Defaults to 1.
newScene.rootNode.camera?.zNear = -20 // The default
value is 1.0
newScene.rootNode.camera?.zFar = 100 // The
default value is 100.0
// newScene.rootNode.camera?.fieldOfView = 45 // defaults
to 60 degrees
// newScene.rootNode.camera?.automaticallyAdjustsZRange = true
newScene.rootNode.camera?.automaticallyAdjustsZRange = false /* @discussion
When set to YES, the near and far planes are automatically set to fit the
bounding box of the entire scene at render time. */
return newScene
}
extension simd_float3 {
func pNode(drawIntoNode: SCNNode, radius: String) {
let myBox = SCNBox(width: 0.5, height: 0.5, length: 0.5, chamferRadius: 0.1)
let newNode = SCNNode(geometry: myBox)
newNode.name = "box_\(radius)"
newNode.simdPosition = self
newNode.scale = SCNVector3(x: 1.0, y: 1.0, z: 1.0)
newNode.isHidden = false
newNode.opacity = 1.0 // "A value of 0 means 100%
transparency, while a value of 1 means 100% opacity."
assignMaterials(newNode)
drawIntoNode.addChildNode(newNode)
}
}
func animate(node: SCNNode) {
let precession_action = SCNAction.rotate(by: CGFloat(Double.pi*2), around:
SCNVector3Make(0, 1, 0), duration: 79.17)
let Spin_action = SCNAction.rotate(by: CGFloat(Double.pi*2), around:
SCNVector3Make(0, 1, 0), duration: 4)
let boxSpin_action = SCNAction.rotate(by: -CGFloat(Double.pi*2), around:
SCNVector3Make(0, 1, 0), duration: 0.5)
var childNodeList:[SCNNode] = node.childNodes(passingTest: { (anyNode, stop)
-> Bool in anyNode.name == "precession" } )
for kids in childNodeList {
if !kids.hasActions {
kids.runAction(SCNAction.repeatForever(precession_action)) }
}
childNodeList = node.childNodes(passingTest: { (anyNode, stop) -> Bool in
anyNode.name == "Spin" } )
for kids in childNodeList {
if !kids.hasActions { kids.runAction(SCNAction.repeatForever(Spin_action)) }
}
childNodeList = node.childNodes(passingTest: { (anyNode, stop) -> Bool in
anyNode.name!.hasPrefix("box") } )
for kids in childNodeList {
if !kids.hasActions {
kids.runAction(SCNAction.repeatForever(boxSpin_action)) }
}
}
func assignMaterials(
node: SCNNode) {
_
for (index,_) in zip((node.geometry?.elements.indices)!,
node.geometry!.elements) { // see enumerated() for zero based e.g.,
Array() and ContiguousArray() only else zip(_:_:)
node.geometry?.materials[index].diffuse.contents = NSColor.red }
}
Let's start with my scene, some of the oldest code and I was just starting coding after many years.
internal func makeAScene() -> SCNScene {
let firstNode = SCNNode()
let secondNode = SCNNode()
firstNode.name = “firstNode”
firstNode.simdPosition = SIMD3<Float>(0,0,0)
firstNode.simdTransform = float4x4([Float(0.5.squareRoot()),Float(0.5.squareRoot()),0,0],[-Float(0.5.squareRoot()),Float(0.5.squareRoot()),0,0],[0,0,1,0],[0,0,0,0])
secondNode.name = “secondNode”
secondNode.simdPosition = SIMD3<Float>(0,0,0)
let newScene = SCNScene()
newScene.rootNode.addChildNode(firstNode)
newScene.rootNode.childNode(withName: “firstNode”, recursively: true)?.addChoildNode(secondNode)
newScene.background.contents = NSColor.black
newScene.rootNode.camera = SCNCamera()
newScene.rootNode.camera?.usesOrthographicProjection = true
newScene.rootNode.camera?.orthographicScale = 20
newScene.rootNode.camera?.zNear = -20
newScene.rootNode.camera?.zFar = 100
newScene.rootNode.camera?.automaticallyAdjustsZRange = false
return newScene
}
.zNear bothers me because the default is 1 (not a negative number) but doesn't show otherwise. .zFar defaults to 100.
The SceneView is the first view listed within a ZStack{} and is therefore under much Text() and Pickers() etc.
The figure constructed by the many elements and drawn in the scene are no wider nor deeper than 10 units in scale. The center of the figure is @ (0,0,0) of the scene's coordinate system.
The saga continues. So I thought I'd add sixty dummy childNodes complete with the same geometry as all the other children... just setting isHidden = true. It worked... in part. The unHidden children are not all visible. About 1/3 are. lol
Oh, I almost forgot to cite a potentially important clue.
To a view in ContentView I had attached
.onChange(of: scene.rootNode.childNode(withName: "parent-to-few-or-many", recursively: true).childNodes { flushAllChildNodes-reloadFileDescibingChildNodes-reDrawChildNodes }
which had the effect of constantly and alternatively blanking the scene and flashing the desired "fewer" nodes. Proving the childNodes are recognized by SceneKit in the proper position, scale etc. before getting wiped by unknown code.
Before you ask, I had also disabled all calls to my own code that removes childNodes just in case poor coding was calling it somewhere. No luck, the fewer were not displayed any the many had subsequent childNodes added for a real mess.
Thanks for replying Greg
The only thing I hadn't tried in TN3124 was logging .boundingBox, which proved consistent whether few or many nodes. I even tried setting the box (for every childNode) larger to no effect. The parentNode has nil boundingBox.
In playing with the camera options, if .usesOrthographicProjection is false, no nodes appear whether few or many. The default is false per documentation. Yet OP is otherwise not necessary nor desired for my app.
Again, since the common code creates all nodes into a common scene with common camera etc. the only difference I can see is the time required to delete the previous nodes, load-from-file the pattern for the nodes to be drawn. Many nodes take more time than fewer. Yet again, .rendersContinuously is set. |-(
Disappeared on its own.
Solved.
go to .entitlements file and turn-off App Sandbox!
To check if my copying files with drag-n-drop was wrong, I created yet another new project and used the "add files" within the new app. No permissions to anywhere!
How do I add permissions to an app?
OK, if that wasn't odd enough... as a work around I made a Data.dataset folder in the apps assets and copied-in a few files to read. Only, they also say "you don't have permission to view it" referring to Assets.xcassets! Yes, this folder was drag-n-dropped from the old project into this new project.
Yet if I create a new folder in the project and copy the data into it, I have no permissions as well. No permissions within my own project, anywhere! Hmm. Security gone awry.
I have not found an example of using "#selector(copy)" to access the objc "copy" method. All the syntax I have tried fails.
as an attempted work-around I created a global array of mySCNGeometry.copy() which should have allowed the materials to be changed independently as stated in the Developer Documentation. They are in fact all the same geometry whereas changing any one "copy" changes them all.
OK, I have just learned that objc methods can be called with Swift. Most examples are of custom functions or methods.
How can I call the existing objc version of .copy() since Swift's doesn't work?
Thanks
fyi: I could never grasp objc and stopped programming during that period. Please be generous with example code.
.copy() is broken
I have tested dozens of permutations in calling.
curiously, when I use .copy() on an SCNGeometry the geometry?.geometrySourceChannels, geometry?.elements, and geometry?.materials are all == to the original but the test whether the geometries themselves are equal returns false. How can a copy not equal its original?
Idk what else to test for "as missing" from the copy() .