public override void RotateWithEvent(NSEvent theEvent) { base.RotateWithEvent(theEvent); var r = SCNQuaternion.FromAxisAngle(new SCNVector3(0, 0, 1), -theEvent.Rotation / 180); r.Normalize(); Trackball.Rotate(r); }
/// <summary> /// Computes the tangent position of the rope based on a given fixture /// </summary> private SCNVector3 TangentPosition(SCNVector3 fixture) { var r = this.ballRadius; var d = fixture - this.ballPosition; var alpha = (float)Math.Acos(r / d.Length); d = this.ballRadius * SCNVector3.Normalize(d); var rot = SCNQuaternion.FromAxisAngle(this.UpVector, fixture == this.FixturePositionL ? -alpha : alpha); var d_rotated = rot.Act(d); return(d_rotated + this.ballPosition); }
public SlingShotSimulation(SCNNode rootNode, int count, float segmentRadius) : base() { this.InitializeHelpers(); for (var i = 0; i < count; i++) { var isStatic = (i < this.BoneInset) || (i >= count - this.BoneInset); var quaternion = SCNQuaternion.FromAxisAngle(SCNVector3.UnitX, 0); var transform = new SimulatedTransform(SCNVector3.Zero, quaternion, SCNVector3.Zero, !isStatic); this.simulatedTransforms.Add(transform); } }
private void Setup(NVector3 extent) { // Translate and rotate line nodes to the correct transform var halfX = extent.X / 2; var halfY = extent.Y / 2; var halfZ = extent.Z / 2; // Two helper functions to isolate the allocations and casts Action <SCNNode, float, float, float> xlat = (node, extentX, extentY, extentZ) => node.LocalTranslate(new SCNVector3(extentX, extentY, extentZ)); Action <SCNNode, float, float, float, Axis> xlatAndRot = (node, extentX, extentY, extentZ, axis) => { xlat(node, extentX, extentY, extentZ); node.LocalRotate(SCNQuaternion.FromAxisAngle(axis.Normal().ToSCNVector3(), (float)-Math.PI / 2)); }; var halfWidth = extent.X / 2; var halfHeight = extent.Y / 2; var halfDepth = extent.Z / 2; xlatAndRot(lineNodes[0], 0, -halfHeight, -halfDepth, Axis.Z); xlatAndRot(lineNodes[1], -halfWidth, -halfHeight, 0, Axis.X); xlatAndRot(lineNodes[2], 0, -halfHeight, halfDepth, Axis.Z); xlatAndRot(lineNodes[3], halfWidth, -halfHeight, 0, Axis.X); xlat(lineNodes[4], -extent.X, 0, -halfDepth); xlat(lineNodes[5], -halfWidth, 0, halfDepth); xlat(lineNodes[6], halfWidth, 0, -halfDepth); xlat(lineNodes[7], halfWidth, 0, halfDepth); xlatAndRot(lineNodes[8], 0, halfHeight, -halfDepth, Axis.Z); xlatAndRot(lineNodes[9], -halfWidth, halfHeight, 0, Axis.X); xlatAndRot(lineNodes[10], 0, halfHeight, halfDepth, Axis.Z); xlatAndRot(lineNodes[11], halfWidth, halfHeight, 0, Axis.X); // Assign geometries lineNodes[0].Geometry = Cylinder(extent.X); lineNodes[1].Geometry = Cylinder(extent.Z); lineNodes[2].Geometry = Cylinder(extent.X); lineNodes[3].Geometry = Cylinder(extent.Z); lineNodes[4].Geometry = Cylinder(extent.Y); lineNodes[5].Geometry = Cylinder(extent.Y); lineNodes[6].Geometry = Cylinder(extent.Y); lineNodes[7].Geometry = Cylinder(extent.Y); lineNodes[8].Geometry = Cylinder(extent.X); lineNodes[9].Geometry = Cylinder(extent.Z); lineNodes[10].Geometry = Cylinder(extent.X); lineNodes[11].Geometry = Cylinder(extent.Z); }
public void CreateFlagSimulationFromNode(SCNNode node) { var meshData = new ClothSimMetalNode(this.device, Width, Height); var clothNode = SCNNode.FromGeometry(meshData.Geometry); var flag = node.FindChildNode("flagStaticWave", true); if (flag != null) { var boundingBoxMax = SCNVector3.Zero; var boundingBoxMin = SCNVector3.Zero; flag.GetBoundingBox(ref boundingBoxMin, ref boundingBoxMax); var existingFlagBV = boundingBoxMax - boundingBoxMin; var rescaleToMatchSizeMatrix = SCNMatrix4.Scale(existingFlagBV.X / (float)Width); var rotation = SCNQuaternion.FromAxisAngle(SCNVector3.UnitX, (float)Math.PI / 2f); var localTransform = rescaleToMatchSizeMatrix * SCNMatrix4.Rotate(rotation.ToQuaternion()); localTransform.Transpose(); var currentTransform = SCNMatrix4.Transpose(flag.Transform); var newTransform = currentTransform * localTransform; clothNode.Transform = SCNMatrix4.Transpose(newTransform);// flag.Transform * localTransform; if (clothNode.Geometry != null) { clothNode.Geometry.FirstMaterial = flag.Geometry?.FirstMaterial; if (clothNode.Geometry.FirstMaterial != null) { clothNode.Geometry.FirstMaterial.DoubleSided = true; } } flag.ParentNode.ReplaceChildNode(flag, clothNode); clothNode.Geometry.SetupPaintColorMask("flag_flagA"); clothNode.SetPaintColors(); clothNode.FixNormalMaps(); this.clothData.Add(new ClothData(clothNode, meshData)); } }
public override void ViewDidLoad() { base.ViewDidLoad(); // Perform any additional setup after loading the view, typically from a nib. var scene = new SCNScene(); var rnd = new Random(); Func <int, int, bool, float> random = (min, max, clamp) => { float num = (float)((double)rnd.Next(min, max) * rnd.NextDouble()); if (!clamp) { return(num); } else if (num < 1.0f) { return(1.0f); } else { return(num); } }; Enumerable.Range(0, 200).Select <int, int> ((i) => Building( random(2, 5, true), random(2, 5, true), random(2, 10, true), random(-20, 20, false), random(-20, 20, false), scene, rnd )).ToArray(); //Lights! var lightNode = new SCNNode() { Light = new SCNLight(), Position = new SCNVector3(30.0F, 20.0F, 60.0F) }; lightNode.Light.LightType = SCNLightType.Omni; scene.RootNode.AddChildNode(lightNode); var ambientLightNode = new SCNNode() { Light = new SCNLight() }; ambientLightNode.Light.LightType = SCNLightType.Ambient; ambientLightNode.Light.Color = UIColor.DarkGray; scene.RootNode.AddChildNode(ambientLightNode); //Camera! var cameraNode = new SCNNode() { Camera = new SCNCamera() }; scene.RootNode.AddChildNode(cameraNode); cameraNode.Position = new SCNVector3(0.0F, 10.0F, 20.0F); var targetNode = new SCNNode() { Position = new SCNVector3(00.0F, 1.5F, 0.0F) }; scene.RootNode.AddChildNode(targetNode); var lc = SCNLookAtConstraint.Create(targetNode); cameraNode.Constraints = new[] { lc }; var scnView = new SCNView(UIScreen.MainScreen.Bounds) { Scene = scene, AllowsCameraControl = true, ShowsStatistics = true, BackgroundColor = UIColor.FromRGB(52, 152, 219) }; var floorNode = new SCNNode { Geometry = new SCNPlane { Height = 40.0F, Width = 40.0F }, Position = SCNVector3.Zero }; var pi2 = Math.PI / 2.0; floorNode.Orientation = SCNQuaternion.FromAxisAngle(SCNVector3.UnitX, (float)(0.0 - pi2)); scene.RootNode.AddChildNode(floorNode); var material = new SCNMaterial(); material.Diffuse.Contents = UIImage.FromFile("Content/road.jpg"); material.Diffuse.ContentsTransform = SCNMatrix4.Scale(new SCNVector3(10.0f, 10.0f, 1.0f)); material.Diffuse.MinificationFilter = SCNFilterMode.Linear; material.Diffuse.MagnificationFilter = SCNFilterMode.Linear; material.Diffuse.MipFilter = SCNFilterMode.Linear; material.Diffuse.WrapS = SCNWrapMode.Repeat; material.Diffuse.WrapT = SCNWrapMode.Repeat; material.Specular.Contents = UIColor.Gray; floorNode.Geometry.FirstMaterial = material; this.View = scnView; }
internal BoundingBoxSide(PositionName position, NVector3 extent, UIColor color = null) : base() { if (color == null) { color = Utilities.AppYellow; } Tiles = new List <Tile>(); this.color = color; this.face = position; // inline Swift setup() and setupExtensions() functions size = Size(extent); var yAxis = Axis.Y.Normal().ToSCNVector3(); var xAxis = Axis.X.Normal().ToSCNVector3(); var zAxis = Axis.Z.Normal().ToSCNVector3(); float halfTurn = (float)Math.PI; float quarterTurn = (float)Math.PI / 2; switch (face) { case PositionName.Front: LocalTranslate(new SCNVector3(0, 0, extent.Z / 2)); break; case PositionName.Back: LocalTranslate(new SCNVector3(0, 0, -extent.Z / 2)); LocalRotate(SCNQuaternion.FromAxisAngle(yAxis, halfTurn)); break; case PositionName.Left: LocalTranslate(new SCNVector3(-extent.X / 2, 0, 0)); LocalRotate(SCNQuaternion.FromAxisAngle(yAxis, -quarterTurn)); break; case PositionName.Right: LocalTranslate(new SCNVector3(extent.X / 2, 0, 0)); LocalRotate(SCNQuaternion.FromAxisAngle(yAxis, quarterTurn)); break; case PositionName.Bottom: LocalTranslate(new SCNVector3(0, -extent.Y / 2, 0)); LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, halfTurn)); break; case PositionName.Top: LocalTranslate(new SCNVector3(0, extent.Y / 2, 0)); LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, -quarterTurn)); break; } for (int index = 0; index < 12; index++) { var line = new SCNNode(); line.Geometry = Cylinder(lineThickness, extensionLength); if (index < 4) { xAxisExtLines.Add(line); line.LocalRotate(SCNQuaternion.FromAxisAngle(zAxis, -quarterTurn)); if (index == 2 || index == 3) { line.LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, halfTurn)); } xAxisExtNode.AddChildNode(line); } else if (index < 8) { yAxisExtLines.Add(line); if (index == 5 || index == 7) { line.LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, halfTurn)); } yAxisExtNode.AddChildNode(line); } else { zAxisExtLines.Add(line); line.LocalRotate(SCNQuaternion.FromAxisAngle(xAxis, -quarterTurn)); zAxisExtNode.AddChildNode(line); } } UpdateExtensions(); HideXAxisExtensions(); HideYAxisExtensions(); HideZAxisExtensions(); AddChildNode(xAxisExtNode); AddChildNode(yAxisExtNode); AddChildNode(zAxisExtNode); }
public SlingShotPose ComputeInputPose() { // note the -1 here differs from other usage var data = new SlingShotPose { UpVector = -this.UpVector /* negated because the strap Y-axis points down */ }; var startBend = this.CurrentLengthL / this.CurrentTotalLength; var endBend = 1f - this.CurrentLengthR / this.CurrentTotalLength; var leatherOnStraights = this.OriginalLeatherLength - this.CurrentLengthOnBall; var segmentAStart = 0f; var segmentAEnd = this.CurrentLengthL - leatherOnStraights * 0.5f; var segmentCStart = segmentAEnd + this.OriginalLeatherLength; var segmentCEnd = this.CurrentTotalLength; var originalLeatherRange = this.OriginalLeatherLength / this.OriginalTotalLength; var currentLeatherRange = this.OriginalLeatherLength / this.CurrentTotalLength; for (var i = 0; i < this.SimulatedTransformCount; i++) { var l = this.OriginalTotalLength * (float)i / (float)(this.SimulatedTransformCount - 1f); var u = l / this.OriginalTotalLength; // remap the u value depending on the material (rubber vs leather) var isRubber = Math.Abs(0.5f - u) > originalLeatherRange * 0.5f; if (isRubber) { if (u < 0.5f) { u = u / (0.5f - originalLeatherRange * 0.5f); u = (segmentAStart + (segmentAEnd - segmentAStart) * u) / this.CurrentTotalLength; } else { u = 1f - (1f - u) / (0.5f - originalLeatherRange * 0.5f); u = (segmentCStart + (segmentCEnd - segmentCStart) * u) / this.CurrentTotalLength; } } else { u = (startBend + endBend) * 0.5f - (0.5f - u) * (currentLeatherRange / originalLeatherRange); } var p = SCNVector3.Zero; var t = SCNVector3.UnitX; if (u < startBend) { // left straight var value = u / startBend; p = SimdExtensions.Mix(this.FixturePositionL, this.TangentPositionL, new SCNVector3(value, value, value)); // left rubber band t = SCNVector3.Normalize(this.TangentPositionL - this.FixturePositionL); } else if (u > endBend) { // right straight var value = (1f - u) / (1f - endBend); p = SimdExtensions.Mix(this.FixturePositionR, this.TangentPositionR, new SCNVector3(value, value, value)); // right rubber band t = SCNVector3.Normalize(this.FixturePositionR - this.TangentPositionR); } else { // on the ball var upv = this.UpVector; var rot = SCNQuaternion.FromAxisAngle(upv, -this.BetaAngle * (u - startBend) / (endBend - startBend)); p = this.ballPosition + rot.Act(this.TangentPositionL - this.ballPosition); t = SCNVector3.Cross(upv, SCNVector3.Normalize(this.ballPosition - p)); } data.Positions.Add(p); data.Tangents.Add(t); data.Lengths.Add(l); } return(data); }