Cylinder Orientation between two points on a sphere, Scenekit, Quaternions IOS

I’ve been trying to draw a cylinder between two points on the outer edge of a sphere using SceneKit. I have already produced a line between these two points using primitive geometry and openGL with SCNRendering Delegate, but now I need to produce a cylinder between these two (well, not just two, but any two 3D vectors that sit on the surface of the sphere). I’ve been working on this for about 3 days straight now, and I’ve gone through everything I could find on implementing Quaternions to make this happen, but as it stands, I can’t get it to work. Academic articles, scientific studies, and nothing, nothing is working to realign a cylinder between two fixed points. I need an algorithm to do this.

Anyway, here’s my most recent code that doesn’t work, but this is just a small snippet of nearly 2k lines of code I’ve worked through so far without the intended result. I know I can move to something more advanced like building my own SCNProgram and/or SCNRenderer to then access GLSL, OpenGL, and Metal complexity, but this seems like something that should be possible using Scenekit and converting between GLKit vector structs to and from SCNVector structs, but so far it’s impossible:

Code:

The following code ingests Longitude and Latitude coordinates and projects them onto the surface of a 3D sphere. These coordinates are returned through a proprietary function I build where I received a SCNVector3 of {x,y,z} coordinates that display accurately on my 3D sphere. I draw a line between two sets of Longitude and Latitude coordinates where the lines that are drawn using primitives shoot through the center of the sphere. So, as I mentioned above, I want this same functionality but with cylinders, not lines (by the way, the longitude and latitude coordinates listed here are bogus, they are randomly generated but both fall on the Earth’s surface).

drawLine = [self lat1:37.76830 lon1:-30.40096 height1:tall lat2:3.97620 lon2:63.73095 height2:tall];

float cylHeight = GLKVector3Distance(SCNVector3ToGLKVector3(cooridnateSetOne.position), SCNVector3ToGLKVector3(coordinateSetTwo.position));

SCNCylinder * cylTest = [SCNCylinder cylinderWithRadius:0.2 height:cylHeight];
SCNNode * test = [SCNNode nodeWithGeometry:cylTest];

SCNMaterial *material = [SCNMaterial material];
[[material diffuse] setContents:[SKColor whiteColor]];
material.diffuse.intensity = 60;
material.emission.contents = [SKColor whiteColor];

material.lightingModelName = SCNLightingModelConstant;
[cylTest setMaterials:@[material]];

GLKVector3 u = SCNVector3ToGLKVector3(cooridnateSetOne.position);
GLKVector3 v = SCNVector3ToGLKVector3(cooridnateSetTwo.position);

GLKVector3 w = GLKVector3CrossProduct(u, v);

GLKQuaternion q = GLKQuaternionMakeWithAngleAndVector3Axis(GLKVector3DotProduct(u,v), GLKVector3Normalize(w));
q.w += GLKQuaternionLength(q);
q = GLKQuaternionNormalize(q);
SCNVector4 final = SCNVector4FromGLKVector4(GLKVector4Make(q.x, q.y, q.z, q.w));

test.orientation = final;

Other code I’ve tried includes this same sort of method, in fact, I even built my own SCNVector3 and SCNVector4 Math libraries in Objective-C to see if my math methods produced different values than using GLKit maths, but I get the same results with both methods. Any help would be awesome, but for now, I’m not looking to jump into anything more complicated than SceneKit. I won’t be diving into Metal and/or OpenGL for another month or two. Thanks!

EDIT:

The variables “cooridnateSetOne” and “cooridnateSetTwo” are SCNNodes that are produced by another function that forces a primitive line geometry into this node and then returns it to a subclass implementation of SCNScene.


Source: ios

Leave a Reply