Creating an array of SCNVector3 using Float in Swift - scenekit

I have a bunch of Z coordinates in an array. I want to create geometry using these values, thus I created an array of SCNVector3. X and Y values will be calculated using a simple nested loop, but the Z values will come from my array.
Xcode is telling me: Cannot assign value of type '(x: Float, y: Float, z: Float)' to type SCNVector3
Am I making a bonehead mistake here?
My code right now is:
var width = 10
var height = 20
var zDepth = [Float]()
var verts = [SCNVector3]()
var i = 0
for y in 0 ..< height {
for x in 0 ..< width {
if i < (width*height) {
vert[i] = (x: Float(x), y: Float(y), z: zDepth[i])
i += 1
}
}
}

for what platform is this?
if it is for mac os, then you have to use CGFloat not Float
EDIT:
you can't assign a tuple to vector3. in your code you need to initialize a new vector3 and assign it to your array
var width = 10
var height = 20
var zDepth = [Float]()
var verts = [SCNVector3]()
var i = 0
for y in 0 ..< height {
for x in 0 ..< width {
if i < (width*height) {
verts[i] = SCNVector3(x: Float(x), y: Float(y), z: zDepth[i])
i += 1
}
}
}
EDIT2: i took out cgfloat (i keep thinking in cgfloats)

Related

Draw an image from an array value p5.js

I am fairly new to p5.js, however I am trying to read a .txt file which contains the below text, and draw a picture depending on the value within the .txt file.
00000
20022
00222
22020
11111
I am currently stumped as to how to draw an image depending on the number in the array, as an example '1' would be grass. I have loaded the file in as a string using the following code: track = loadStrings("track1.txt");
I am trying to load it as a 5x5 'tile' if you will. Any help would be appreciated :)
I've used p5.Image to create a picture based on the pixels in the file.
This is a way of writing the code:
let track;
let colors;
let img;
function setup() {
createCanvas(100, 100);
track=loadStrings("track1.txt")
colors = [color(255,0,0),color(0,255,0),color(0,0,255)]
}
function draw() {
background(220);
img = createImage(track.length, track[0].length)
img.loadPixels();
for (let i = 0 ; i < track.length ; i++){
for (let j = 0 ; j < track.length ; j++){
img.set(i, j, colors[int(track[i][j])]);
}
}
img.updatePixels();
image(img, 50, 50);
}
Well you could probs split it up into arrays and also if you'd have some sort of seperator for colors, like: track1.txt: 10, 30, 255\n ... r, g, b\n .... Right now you would have to use the rgb rrrgggbbb
let colors = track.split("\n") // makes every new line into an array
for(let x = 0; x <= width; x ++) // "\n" = new line
for(let y = 0; y <= height; y ++){
let currentCol = []
for(let i = 0; i < 9; i += 3)
currentCol.push(
colors[x + y][0 + i] + // I'm really not sure about the: colors[x + y]...
colors[x + y][1 + i] +
colors[x + y][2 + i]
)
set(x, y, color(currentCol[0], currentCol[1], currentCol[2]))
}
I also made a function with a slightly different formula, which might work better, i am not sure though, but this is the actual formula to get from pixel array
function getColor(x, y, allColorsArr){
let _col = [] // current color, underscore not to accidentally clear your variable
for(let i = 0; i < 3; i ++)
_col.push(
allColorsArr[x + y * width][0 + i * 3] +
allColorsArr[x + y * width][1 + i * 3] +
allColorsArr[x + y * width][2 + i * 3]
)
return {
r: parseInt(_col[0], 10),
g: parseInt(_col[1], 10),
b: parseInt(_col[2], 10)
} // returning an object here just for the `.r`; `.g`; `.b`
} // you could do something like: let Colors = {red: 0, green: 1, blue: 2}
// col[Colors.red], col[Colors.green], col[Colors.blue] if you want
// example: let col = getColor(1, 0, track.split("\n"))
// example: stroke(col.r, col.g, col.b)
THERE IS MOST LIKELY IS A BETTER WAY TO DO THIS, but at least this works...

Index out of range: Mapping the output of a 3-input function to a 3-dimentional floating-point array in Swift 4

I want to set the elements in a mutable 3d array of Doubles to the output of a 3-input function, f(), for the position of that element in the array ([a][n][b]), then print the array.
//3-input function must input and output doubles. This function is an example.
func f(a: Double, n: Double, b: Double) -> Double {
return a * n * b
}
//Size of array: 7*7*7
let aMax = 6
let nMax = 6
let bMax = 6
//Define mutable array; I don't know if I need to initialize array "points".
var points = [[[Double]]]()
//I don't know if I should use ".append" or "=".
for a in 0...aMax {
for n in 0...nMax {
for b in 0...bMax {
points[a][n][b] = f(a: Double(a), n: Double(n), b: Double(b)) //Changing element at position results in "fatal error: Index out of range".
}
}
}
print(points)
The problem is that after doing:
var points = [[[Double]]]()
points is completely empty. So any attempt to access any of the indexes results in the "Index out of range" error.
Since you are going to fill the whole thing, initializing the three dimensions using Array(repeating:count:).
var points = Array(repeating: Array(repeating: Array(repeating: 0.0, count: bMax + 1), count: nMax + 1), count: aMax + 1)
Now the rest of your code will work.
You can try this , for an array declared like this [[[Double]]] you can use append only but for assigning and indexing it you must first init it like this
//Size of array: 7*7*7
let aMax = 7
let nMax = 7
let bMax = 7
//Define mutable array; I don't know if I need to initialize array "points".
var points = [[[Double]]](repeating: [[Double]](repeating: [Double](repeating: 0, count: bMax), count: nMax), count: aMax)
//I don't know if I should use ".append" or "=".
for a in 0..<aMax {
for n in 0..<nMax {
for b in 0..<bMax {
points[a][n][b] = (f(a: Double(a), n: Double(n), b: Double(b))) //Changing element at position results in "fatal error: Index out of range".
}
}
}
print(points)
You can declare and initialize a "3D" array in a single shot, using Array.map(_:):
let (aCount, nCount, bCount) = (8, 8, 8)
let points: [[[Double]]] = (0 ..< aCount).map { aInt in
let a = Double(aInt)
return (0 ..< nCount).map { nInt in
let n = Double(nInt)
return (0 ..< bCount).map { bInt in
return f(a: a, n: n, b: Double(bInt))
}
}
}

Generate a grid from an array

I have this array of blocks:
let blocks = [Blocks]()
I add 16 blocks into that array. And here is how I generate a 4x4 grid:
for i in 0...3 {
for j in 0...3 {
for b in blocks {
b.position = CGPoint(x: CGFloat(i)*b.frame.size.width + xOffset, y: yPos)
addChild(b) <<-- Error here
yPos = yPos - b.frame.size.height - yOffset
}
}
I get this error:
Attemped to add a SKNode which already has a parent
What should I do here?
It should work if you replace the line
for b in blocks
with
let b = blocks[i*4 + j]
You are adding all of the blocks 16 times with the current code

Inefficient parsing of Vertex and Index data, looking for more efficient methods

I wrote a method to parse an array containing vertex data. The goal of the method was to produce a new array of unique vertices and a new index from that data.
This is the struct I used to store the vertices in the array.
struct Vertex: Hashable {
var x, y, z,
nx, ny, nz,
s, t: Float
var hashValue: Int {
return "\(self.x),\(self.y),\(self.z),\(self.nx),\(self.ny),\(self.nz),\(self.s),\(self.t),".hashValue
}
static func ==(lhs: Vertex, rhs: Vertex) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
And this is the method I used to create the array of unique vertices and new index. The first argument of the method takes an array with the vertex data already ordered by the original index.
func makeVertexIndex(_ array: [Float]) -> ([Vertex], [Int]) {
var counter = 0
var indexCounter = 0
var holder = [Float]()
var vertices = [Vertex]()
var index = [Int]()
for i in array {
counter += 1
if counter == 8 {
counter = 0
holder.append(i)
let vertex = Vertex(x: holder[0], y: holder[1], z: holder[2],
nx: holder[3], ny: holder[4], nz: holder[5],
s: holder[6], t: holder[7])
if vertices.contains(vertex) {
guard let match = vertices.index(of: vertex) else { continue }
index.append(match)
} else {
vertices.append(vertex)
index.append(indexCounter)
indexCounter += 1
}
holder.removeAll()
} else {
holder.append(i)
}
}
return (vertices, index)
}
I was able to successfully parse lower triangle count meshes, but when I try to run this on higher triangle count meshes it took over an hour to run.
I'm pretty new to coding, Swift is my first language, but I suspect it shouldn't take this long to do this task and I probably just wrote my method really inefficiently or maybe there's a completely different way I could approach this problem.
Anyhow I'd appreciate any help I could get. Thanks for reading.
Update 1:
I re-wrote my method to create the vertex array first then change to it to a set to make the values unique and back to an array then ran it through the vertexArray loop looking for matches in the unique vertices array. This version of the method cut the process time from 21 seconds on my test mesh to about 12 seconds.
func makeVertexIndex(_ array: [Float]) -> ([Vertex], [Int]) {
var counter = 0
var holder = [Float]()
var vertexArray = [Vertex]()
var vertices = [Vertex]()
var index = [Int]()
for i in array {
counter += 1
if counter == 8 {
counter = 0
holder.append(i)
let vertex = Vertex(x: holder[0], y: holder[1], z: holder[2],
nx: holder[3], ny: holder[4], nz: holder[5],
s: holder[6], t: holder[7])
vertexArray.append(vertex)
holder.removeAll()
} else {
holder.append(i)
}
}
let vertexSet = Set(vertexArray)
vertices = Array(vertexSet)
for v in vertexArray {
guard let match = vertices.index(of: v) else { continue }
index.append(match)
}
return (vertices, index)
}
Update 2:
Here are my updated struct and method after implementing some of the recommended solutions.
Struct:
struct Vertex: Hashable {
var x, y, z,
nx, ny, nz,
s, t: Float
var hashValue: Int {
return "\(self.x),\(self.y),\(self.z),\(self.nx),\(self.ny),\(self.nz),\(self.s),\(self.t)".hashValue
}
static func ==(lhs: Vertex, rhs: Vertex) -> Bool {
return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.nx == rhs.nx) &&
(lhs.ny == rhs.ny) && (lhs.nz == rhs.nz) && (lhs.s == rhs.s) && (lhs.t == rhs.t)
}
}
Method:
func makeVertexIndex(_ array: [Float]) -> ([Vertex], [Int]) {
var vertexArray = [Vertex]()
vertexArray.reserveCapacity(array.count / 8)
var vertices = [Vertex]()
var index = [Int]()
// Creating an array of Vertex from an array containing
// position/normal/texcoord in correct order.
for i in stride(from: 0, to: array.count, by: 8) {
let vertex = Vertex(x: array[i], y: array[i + 1], z: array[i + 2],
nx: array[i + 3], ny: array[i + 4], nz: array[i + 5],
s: array[i + 6], t: array[i + 7])
vertexArray.append(vertex)
}
// Making the Vertex array unique by converting to set and back to array.
let vertexSet = Set(vertexArray)
vertices = Array(vertexSet)
// Making new index by finding the matching vertex in the
// unique vertex array and adding that array index to the new index
for v in vertexArray {
guard let match = vertices.index(of: v) else { continue }
index.append(match)
}
return (vertices, index)
}
After trying out various parts of the recommended solutions the method was able to process a model with 70K triangles in 13 minutes, previously it took over an hour and a half.
So this was a huge improvement, appreciate all the solutions so far, going to keep this open for maybe a day or two to see if any other recommendations come.
Is there a particular reason why your == code compares hashes rather than each property? i.e.
static func ==(lhs: Vertex, rhs: Vertex) -> Bool {
return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) &&
(lhs.nx == rhs.nx) && ...etc
}
Then if lhs.x is not equal to rhs.x, the code will fail quickly and move on to the next. Currently you're having to create a hash value again and again. Alternatively, you could speed up your current code by calculating the hash once in the constructor (and, say, making all the properties private(set) like in the simplified example below).
struct Vertex {
private(set) var x, y: Float
let hash: Int
init(x: Float, y: Float) {
self.x = x
self.y = y
hash = "\(x),\(y)".hashValue
}
static func ==(lhs: Vertex, rhs: Vertex) -> Bool {
return lhs.x == rhs.x
}
}
let vertex = Vertex(x: 1.0, y: 2.0)
print(vertex.hash)
It looks like you're trying to end up with a new set of Vertices, and a set of indices. If the new set of vertices contains a duplicate, remove that from the list of vertices, and double the index of the duplicate. Judging from your first function. Your second only added an index when there was a match. Which did you mean?
From the first.. if you have V1 V2 V3 V4, and V4 = V1, you want indices [0,0,1,2].
Is this correct? I would clean that up by iterating over the float array 8 at a time, then determine if there are duplicates, if so, figure out which are duplicates and then create your final two arrays. Here's my take..
func makeVertexIndex(_ array: [Float]) -> ([Vertex], [Int]) {
var newVertices = [Vertex]()
for i in stride(from: 0, to: array.count, by: 8) {
newVertices.append(Vertex(x: array[i], y: array[i + 1], z: array[i + 2],
nx: array[i + 3], ny: array[i + 4], nz: array[i + 5],
s: array[i + 6], t: array[i + 7]))
}
if newVertices.count > Set(newVertices).count {
var uniqueVertices = [Vertex]()
var indices = [Int]()
var vertexIndex = [Vertex: Int]()
var count = 0
for vertex in newVertices {
if let existingVertex = vertexIndex[vertex] {
indices.append(existingVertex)
} else {
vertexIndex[vertex] = count
uniqueVertices.append(vertex)
count += 1
}
}
return (uniqueVertices, indices.sorted())
} else {
return (newVertices, [Int](0..<newVertices.count))
}
}

How to find x,y,z values given the index in a linear 3D array?

Given a 3D space of (10, 10, 10) specified in a linear array:
[10x10x10]
Instead of
[10][10][10]
I understand how to get an index of [x][y][z] by doing the following:
[x + (y * W) ) + ( z * W * H )]
Or
[x + (y * 10) ) + ( z * 10 * 10 )]
How do I go in reverse? If I have the index [i] how do I go about finding (x,y,z)?
For every x, there are 10 elements of y. For every y, there are 10 elements of z. In this sense, z is a sort of iterator that gives the smallest increments in your array. Every time z increments 10*10 times, x increments once:
//x = i/(dim(y)*dim(z)) % dim(x)
x = i/(10*10) % 10 //integer division
Similarly for y, however z only needs to increment 10 times for y to increment.
//y = i/dim(z) % dim(y)
y = i/(10) % 10 //integer division
Finally, z always increments whenever z increments (that sounded stupid, but I was trying to follow my process from the other two. What I'm trying to say is that z will always increment when the iterator increments).
//z = i % dim(z)
z = i % 10
Edit: dim() is supposed to return the size of the specified dimension. It is poorly named in this example and I apologize for that.
I use some function overloading to support 2d and 3d the math is similar to 2d but with the height to figure out the Z axis.
fromPos(x: number, y: number, z: number, width: number, height: number): number
fromPos(x: number, y: number, width: number): number
fromPos(x: number, y: number, zOrWidth: number, width?: number , height?: number): number {
if(width != undefined && height != undefined) {
let z = zOrWidth;
return (x + width * y) + (z * width * height)
} else {
return x + zOrWidth * y;
}
}
fromIndex (index: number, width: number, height: number): Vector3
fromIndex (index: number, width: number): Vector2
fromIndex (index: number, width: number, height?: number): Vector2 {
if(height != undefined) {
return {
x: index % width,
y: Math.floor(index / width % height),
z: Math.floor(index / ( width * height ))
} as Vector3;
} else {
return {
x: index % width,
y: index / width
} as Vector2;
}
}
Use integer division / and the modulus function % in the following algorithm (C-style code)
// find indexes `i`,`j`,`k` from the flat index `q`
// dimensions n,m,l (i=0..n-1, j=0..m-1, k=0..l-1)
// memory is layout is last index `i` changing fastest
// q = i + n*( j + m*k )
i = q % n;
q = q / n;
j = q % m;
i = q / m;
Example per question posted
The elements at (7,3,5) has index q = 7+10*(3+10*5) = 537
i = 537 % 10 = 7
537 / 10 = 53
j = 53 % 10 = 3
k = 53 / 10 = 5
So (i,j,k)=(7,3,5).

Resources