private SCNGeometry CreateTrailMesh(List <SCNVector3> positions, List <SCNVector4> colors) { SCNGeometry result = null; if (positions.Count >= 4) { var array = new byte[positions.Count]; for (byte i = 0; i < positions.Count; i++) { array[i] = i; } var positionSource = SCNGeometrySource.FromVertices(positions.ToArray()); var colorSource = SCNGeometrySourceExtensions.Create(colors); var element = SCNGeometryElement.FromData(NSData.FromArray(array), SCNGeometryPrimitiveType.TriangleStrip, positions.Count - 2, 2); result = SCNGeometry.Create(new SCNGeometrySource[] { positionSource, colorSource }, new SCNGeometryElement[] { element }); var material = result.FirstMaterial; if (material == null) { throw new Exception("created geometry without material"); } material.DoubleSided = true; material.LightingModelName = SCNLightingModel.Constant; material.BlendMode = SCNBlendMode.Add; material.WritesToDepthBuffer = false; } return(result); }
public SCNGeometry ImportOBJ(string path) { string[] fileContents = File.ReadLines(path).ToArray(); GetLines(fileContents); polygonCount = indexLines.Length; int[] vertexIndexPrefix = SplitIndices(indexLines).Item1; int[] vertexIndices = SplitIndices(indexLines).Item2; int[] normalIndices = SplitIndices(indexLines).Item3; SCNVector3[] vertexPoints = LinesToPoints(vertexLines); SCNVector3[] normalPoints = LinesToPoints(normalLines); SCNVector3[] vertices = OrderPoints(vertexPoints, vertexIndices); SCNVector3[] normals = OrderPoints(normalPoints, normalIndices); vertexIndices = ReorderIndices(vertexIndexPrefix, vertexIndices); NSData vertexIndexData = IndexData(vertexIndices); SCNGeometrySource vertexSource = SCNGeometrySource.FromVertices(vertices); SCNGeometrySource normalSource = SCNGeometrySource.FromNormals(normals); SCNGeometryElement vertexElement = SCNGeometryElement.FromData(vertexIndexData, SCNGeometryPrimitiveType.Polygon, polygonCount, sizeof(int)); return(SCNGeometry.Create(new[] { vertexSource, normalSource }, new[] { vertexElement })); }
static SCNGeometry CreateGeometry(nfloat width, nfloat height) => SCNGeometry.Create( CreateGeometrySources(width, height), new [] { CreatePlane(width, height), CreatePlane(width, height), CreateLines(width, height) });
public static void UpdateGeometry(this SCNNode node, SCNGeometry geometry) { var oldGeometry = node.Geometry; node.Geometry = geometry; oldGeometry.Dispose(); oldGeometry = null; }
public SCNPhysicsBody CreatePlanePhysics(SCNGeometry geometry) { var body = SCNPhysicsBody.CreateStaticBody(); body.PhysicsShape = SCNPhysicsShape.Create(geometry, new NSDictionary()); body.Restitution = 0.5f; body.Friction = 0.5f; return(body); }
public PlayerCharacter(SCNNode characterNode) : base(characterNode) { CategoryBitMask = NodeCategory.Lava; velocity = SCNVector3.Zero; IsWalking = false; changingDirection = false; baseWalkSpeed = 0.0167f; JumpBoost = 0.0f; WalkSpeed = baseWalkSpeed * 2; Jumping = false; groundPlaneHeight = 0.0f; playerWalkDirection = WalkDirection.Right; cameraHelper = new SCNNode { Position = new SCNVector3(1000f, 200f, 0f) }; AddChildNode(cameraHelper); CollideSphere = new SCNNode { Position = new SCNVector3(0f, 80f, 0f) }; SCNGeometry geo = SCNCapsule.Create(90f, 160f); SCNPhysicsShape shape2 = SCNPhysicsShape.Create(geo, (NSDictionary)null); CollideSphere.PhysicsBody = SCNPhysicsBody.CreateBody(SCNPhysicsBodyType.Kinematic, shape2); CollideSphere.PhysicsBody.CollisionBitMask = GameCollisionCategory.Banana | GameCollisionCategory.Coin | GameCollisionCategory.Coconut | GameCollisionCategory.Lava; CollideSphere.PhysicsBody.CategoryBitMask = GameCollisionCategory.Player; AddChildNode(CollideSphere); DustPoof = GameSimulation.LoadParticleSystemWithName("dust"); NSString artResourcePath = (NSString)GameSimulation.PathForArtResource("level/effects/effects_transparent.png"); DustPoof.ParticleImage = artResourcePath; DustWalking = GameSimulation.LoadParticleSystemWithName("dustWalking"); DustWalking.ParticleImage = artResourcePath; dustWalkingBirthRate = DustWalking.BirthRate; // Load the animations and store via a lookup table. SetupIdleAnimation(); SetupRunAnimation(); SetupJumpAnimation(); SetupBoredAnimation(); SetupHitAnimation(); PlayIdle(); }
public SCNPhysicsBody MakePhysicsBody(SCNGeometry geometry) { var option = new SCNPhysicsShapeOptions(); option.KeepAsCompound = true; option.ShapeType = SCNPhysicsShapeType.ConcavePolyhedron; var shape = SCNPhysicsShape.Create(geometry, option); return(SCNPhysicsBody.CreateBody(type: SCNPhysicsBodyType.Static, shape)); }
public SCNGeometry MakeMeshGeometry(SCNVector3[] vertices, SCNVector3[] normals, List <int> faces) { var geometrySources = new[] { SCNGeometrySource.FromVertices(vertices), SCNGeometrySource.FromNormals(normals) }; var array = faces.SelectMany(v => BitConverter.GetBytes(v)).ToArray(); var indexData = NSData.FromArray(array); var elementSource = SCNGeometryElement.FromData(indexData, SCNGeometryPrimitiveType.Triangles, (nint)(faces.Count / 3), (nint)sizeof(int)); var geometry = SCNGeometry.Create(geometrySources, new[] { elementSource }); geometry.WantsAdaptiveSubdivision = false; return(geometry); }
public override SCNPhysicsBody CreatePlanePhysics(SCNGeometry geometry) { var body = SCNPhysicsBody.CreateStaticBody(); body.PhysicsShape = SCNPhysicsShape.Create(geometry, new SCNPhysicsShapeOptions { ShapeType = SCNPhysicsShapeType.BoundingBox }); body.Restitution = 0.5f; body.Friction = 0.5f; return(body); }
public static SCNGeometry ToSCNGeometry(this Solid csg) { if (csg.Polygons.Count == 0) { return(SCNGeometry.Create()); } else { var verts = csg. Polygons. SelectMany(x => x.Vertices). Select(ToSCNVector3). ToArray(); var norms = csg. Polygons. SelectMany(x => { var n = x.Plane.Normal.ToSCNVector3(); return(x.Vertices.Select(_ => n)); }). ToArray(); var vertsSource = SCNGeometrySource.FromVertices(verts); var normsSource = SCNGeometrySource.FromNormals(norms); var sources = new[] { vertsSource, normsSource }; var triStream = new System.IO.MemoryStream(); var triWriter = new System.IO.BinaryWriter(triStream); var triCount = 0; var vi = 0; foreach (var p in csg.Polygons) { for (var i = 2; i < p.Vertices.Count; i++) { triWriter.Write(vi); triWriter.Write(vi + i - 1); triWriter.Write(vi + i); } triCount += p.Vertices.Count - 2; vi += p.Vertices.Count; } triWriter.Flush(); var triData = NSData.FromArray(triStream.ToArray()); var elem = SCNGeometryElement.FromData(triData, SCNGeometryPrimitiveType.Triangles, triCount, 4); var elements = new[] { elem }; var g = SCNGeometry.Create(sources, elements); g.FirstMaterial.Diffuse.ContentColor = NSColor.LightGray; return(g); } }
public static void SetupPaintColorMask(this SCNGeometry geometry, string name) { // if we've already set it up, don't do it again if (geometry.ValueForKey(new NSString(PaintMaskColorKey)) == null) { if (PaintColorMaskTextures.TryGetValue(name, out string paintMask)) { // all textures are absolute paths from the app folder var texturePath = $"art.scnassets/textures/{paintMask}.ktx"; if (name.Contains("catapult")) { //os_log(.debug, "visited %s for texture", name) } var surfaceScript = @" #pragma arguments texture2d<float> paintMaskTexture; //sampler paintMaskSampler; float4 paintMaskColor; #pragma body // 0 is use diffuse texture.rgb, 1 is use paintMaskColor.rgb float paintMaskSelector = paintMaskTexture.sample( sampler(filter::linear), // paintMaskSampler, _surface.diffuseTexcoord.xy).r; _surface.diffuse.rgb = mix(_surface.diffuse.rgb, paintMaskColor.rgb, paintMaskSelector); "; geometry.ShaderModifiers = new SCNShaderModifiers() { EntryPointSurface = surfaceScript }; // mask pro var prop = SCNMaterialProperty.Create(new NSString(texturePath)); prop.MinificationFilter = SCNFilterMode.Linear; prop.MagnificationFilter = SCNFilterMode.Nearest; prop.MipFilter = SCNFilterMode.Nearest; prop.MaxAnisotropy = 1; // set the uniforms, these will be overridden in the runtime geometry.SetTexture("paintMaskTexture", prop); geometry.SetFloat4(PaintMaskColorKey, SCNVector4.One); } } }
private SCNNode CreateBlock(SCNVector3 position, SCNVector3 size) { if (DiceMesh == null) { DiceMesh = CreateBlockMesh(size); } var model = SCNNode.Create(); model.Position = position; model.Geometry = DiceMesh; model.PhysicsBody = SCNPhysicsBody.CreateDynamicBody(); return(model); }
internal static SCNGeometry CreateVisualization(NVector3[] points, UIColor color, float size) { if (points.Length == 0) { return(null); } unsafe { var stride = sizeof(float) * 3; // Pin the data down so that it doesn't move fixed(NVector3 *pPoints = &points[0]) { // Grab a pointer to the data and treat it as a byte buffer of the appropriate length var intPtr = new IntPtr(pPoints); var pointData = NSData.FromBytes(intPtr, (System.nuint)(stride * points.Length)); // Create a geometry source (factory) configured properly for the data (3 vertices) var source = SCNGeometrySource.FromData( pointData, SCNGeometrySourceSemantics.Vertex, points.Length, true, 3, sizeof(float), 0, stride ); // Don't unpin yet, because geometry creation is lazy // Create geometry element // The null and bytesPerElement = 0 look odd, but this is just a template object var element = SCNGeometryElement.FromData(null, SCNGeometryPrimitiveType.Point, points.Length, 0); element.PointSize = 0.001F; element.MinimumPointScreenSpaceRadius = size; element.MaximumPointScreenSpaceRadius = size; // Stitch the data (source) together with the template (element) to create the new object var pointsGeometry = SCNGeometry.Create(new[] { source }, new[] { element }); pointsGeometry.Materials = new[] { Utilities.Material(color) }; return(pointsGeometry); } } }
private void AddPrimitive(SCNGeometry geometry, float yPos, CABasicAnimation rotationAnimation, SCNMaterial sharedMaterial) { var xPos = 13.0f * (float)Math.Sin((float)Math.PI * 2 * PrimitiveIndex / 9.0f); var zPos = 13.0f * (float)Math.Cos((float)Math.PI * 2 * PrimitiveIndex / 9.0f); var node = SCNNode.Create(); node.Position = new SCNVector3(xPos, yPos, zPos); node.Geometry = geometry; node.Geometry.FirstMaterial = sharedMaterial; CarouselNode.AddChildNode(node); PrimitiveIndex++; rotationAnimation.TimeOffset = -PrimitiveIndex; node.AddAnimation(rotationAnimation, new NSString("rotationAnimation")); }
private static void FixNormalMap(this SCNGeometry geometry) { foreach (var material in geometry.Materials) { var prop = material.Normal; // astc needs gggr and .ag to compress to L+A, // but will compress rg01 to RGB single plane (less quality) // bc/eac/explicit/no compression use rg01 and .rg // rg01 is easier to see and edit in texture editors // set the normal to RED | GREEN (rg01 compression) // uses single plane on ASTC, dual on BC5/EAC_RG11/Explicit prop.TextureComponents = SCNColorMask.Red | SCNColorMask.Green; // set the normal to ALPHA | GREEN (gggr compression) // uses dual plane for ASTC, BC3nm // prop.textureComponents = [.alpha, .green] } }
SCNNode CreateTorchNode() { SCNGeometry geometry = SCNBox.Create(20f, 100f, 20f, 0f); geometry.FirstMaterial.Diffuse.Contents = AppKit.NSColor.Brown; var template = new SCNNode { Geometry = geometry }; var particleEmitter = new SCNNode { Position = new SCNVector3(0f, 50f, 0f) }; SCNParticleSystem fire = GameSimulation.LoadParticleSystemWithName("torch", "spark"); particleEmitter.AddParticleSystem(fire); particleEmitter.Light = TorchLight; template.AddChildNode(particleEmitter); return(template); }
/// <summary> /// must copy geometry and materials to set unique data on both here we only want /// </summary> public static SCNGeometry CopyGeometryAndMaterials(this SCNGeometry geometry) { var result = geometry; if (geometry.Copy() is SCNGeometry geometryCopy) { var materialsCopy = new List <SCNMaterial>(); foreach (var material in geometryCopy.Materials) { if (material.Copy() is SCNMaterial materialCopy) { materialsCopy.Add(materialCopy); } } geometryCopy.Materials = materialsCopy.ToArray(); result = geometryCopy; } return(result); }
public ClothSimMetalNode(IMTLDevice device, uint width, uint height) { var vector3Size = System.Runtime.InteropServices.Marshal.SizeOf <OpenTK.NVector3>(); var vertices = new List <SCNVector3>(); var normals = new List <SCNVector3>(); var uvs = new List <OpenTK.Vector2>(); var indices = new List <byte>(); for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { var p = new SCNVector3(x, 0, y); vertices.Add(p); normals.Add(SCNVector3.UnitY); uvs.Add(new OpenTK.Vector2(p.X / width, p.Z / height)); } } for (var y = 0; y < (height - 1); y++) { for (var x = 0; x < (width - 1); x++) { // make 2 triangles from the 4 vertices of a quad var i0 = (byte)(y * width + x); var i1 = (byte)(i0 + 1); var i2 = (byte)(i0 + width); var i3 = (byte)(i2 + 1); // triangle 1 indices.Add(i0); indices.Add(i2); indices.Add(i3); // triangle 2 indices.Add(i0); indices.Add(i3); indices.Add(i1); } } var vertexBuffer1 = device.CreateBuffer(vertices.ToArray(), MTLResourceOptions.CpuCacheModeWriteCombined); var vertexBuffer2 = device.CreateBuffer((nuint)(vertices.Count * vector3Size), MTLResourceOptions.CpuCacheModeWriteCombined); var vertexSource = SCNGeometrySource.FromMetalBuffer(vertexBuffer1, MTLVertexFormat.Float3, SCNGeometrySourceSemantics.Vertex, vertices.Count, 0, vector3Size); var normalBuffer = device.CreateBuffer(normals.ToArray(), MTLResourceOptions.CpuCacheModeWriteCombined); var normalWorkBuffer = device.CreateBuffer((nuint)(normals.Count * vector3Size), MTLResourceOptions.CpuCacheModeWriteCombined); var normalSource = SCNGeometrySource.FromMetalBuffer(normalBuffer, MTLVertexFormat.Float3, SCNGeometrySourceSemantics.Normal, normals.Count, 0, vector3Size); var uvBuffer = device.CreateBuffer(uvs.ToArray(), MTLResourceOptions.CpuCacheModeWriteCombined); var uvSource = SCNGeometrySource.FromMetalBuffer(uvBuffer, MTLVertexFormat.Float2, SCNGeometrySourceSemantics.Texcoord, uvs.Count, 0, OpenTK.Vector2.SizeInBytes); var data = NSData.FromArray(indices.ToArray()); var indexElement = SCNGeometryElement.FromData(data, SCNGeometryPrimitiveType.Triangles, 1178, 4); var geometry = SCNGeometry.Create(new SCNGeometrySource[] { vertexSource, normalSource, uvSource }, new SCNGeometryElement[] { indexElement }); // velocity buffers var velocityBuffer1 = device.CreateBuffer((nuint)(vertices.Count * vector3Size), MTLResourceOptions.CpuCacheModeWriteCombined); var velocityBuffer2 = device.CreateBuffer((nuint)(vertices.Count * vector3Size), MTLResourceOptions.CpuCacheModeWriteCombined); this.Geometry = geometry; this.VertexCount = vertices.Count; this.Vb1 = vertexBuffer1; this.Vb2 = vertexBuffer2; this.NormalBuffer = normalBuffer; this.NormalWorkBuffer = normalWorkBuffer; this.VelocityBuffers = new List <IMTLBuffer> { velocityBuffer1, velocityBuffer2 }; }
private void AddPrimitive (SCNGeometry geometry, float yPos, CABasicAnimation rotationAnimation, SCNMaterial sharedMaterial) { var xPos = 13.0f * NMath.Sin (NMath.PI * 2 * PrimitiveIndex / 9.0f); var zPos = 13.0f * NMath.Cos (NMath.PI * 2 * PrimitiveIndex / 9.0f); var node = SCNNode.Create (); node.Position = new SCNVector3 (xPos, yPos, zPos); node.Geometry = geometry; node.Geometry.FirstMaterial = sharedMaterial; CarouselNode.AddChildNode (node); PrimitiveIndex++; rotationAnimation.TimeOffset = -PrimitiveIndex; node.AddAnimation (rotationAnimation, new NSString ("rotationAnimation")); }
// https://developer.apple.com/documentation/scenekit/scnshadable#1654834 // Some of these can be animated inside of an SCNTransaction. // Sets shader modifier data onto a material or all materials in a geometry. public static void SetTexture(this SCNGeometry geometry, string uniform, SCNMaterialProperty texture) { // this must be the texture name, and not the sampler name geometry.SetValueForKey(texture, new NSString(uniform)); }
private SCNNode CreateBlock (SCNVector3 position, SCNVector3 size) { if (DiceMesh == null) { DiceMesh = CreateBlockMesh (size); } var model = SCNNode.Create (); model.Position = position; model.Geometry = DiceMesh; model.PhysicsBody = SCNPhysicsBody.CreateDynamicBody (); return model; }
public static void SetFloat4(this SCNGeometry geometry, string uniform, SCNVector4 value) { geometry.SetValueForKey(NSValue.FromVector(value), new NSString(uniform)); }
public static void SetColor(this SCNGeometry geometry, string uniform, UIColor value) { geometry.SetValueForKey(value, new NSString(uniform)); }
public static bool HasUniform(this SCNGeometry geometry, string uniform) { return(geometry.ValueForKey(new NSString(uniform)) != null); }
public static void TileTexture(this SCNGeometry box, int num) { box.FirstMaterial.Diffuse.WrapS = SCNWrapMode.Mirror; box.FirstMaterial.Diffuse.WrapT = SCNWrapMode.Mirror; box.FirstMaterial.Diffuse.ContentsTransform = SCNMatrix4.Scale(num, num, num); }