Beispiel #1
0
        public WavefrontObj(Stream stream)
        {
            Obj?        obj    = null;
            Span <char> buffer = stackalloc char[1024];

            using var reader = new StreamReader(stream);

            var remaining = buffer.Slice(0, reader.Read(buffer));
            var eof       = false;

            while (remaining.Length > 0)
            {
                var index = 0;
                while ((index = remaining.IndexOf('\n')) >= 0 || (remaining.Length > 0 && eof))
                {
                    if (index <= 0)
                    {
                        index = remaining.Length;
                    }

                    var line = remaining.Slice(0, index);
                    remaining = remaining.Slice(Math.Min(remaining.Length, index + 1));

                    while (line.Length > 0 && char.IsWhiteSpace(line[0]))
                    {
                        line = line.Slice(1);
                    }

                    while (line.Length > 0 && char.IsWhiteSpace(line[line.Length - 1]))
                    {
                        line = line.Slice(0, line.Length - 1);
                    }

                    if (line.Length <= 0)
                    {
                        continue;
                    }

                    // obj
                    if (line[0] == 'o' && line.Length > 3)
                    {
                        obj = new Obj(line.Slice(2).ToString());
                        Objects.Add(obj.Name, obj);
                    }
                    else if (line[0] == 'v' && line.Length > 3)
                    {
                        // normal
                        if (line[1] == 'n')
                        {
                            if (Calc.ParseVector3(line.Slice(3), ' ', out var normal))
                            {
                                Normals.Add(normal);
                            }
                        }
                        // tex-coord
                        else if (line[1] == 't')
                        {
                            if (Calc.ParseVector2(line.Slice(3), ' ', out var texcoord))
                            {
                                Texcoords.Add(texcoord);
                            }
                        }
                        // position
                        else
                        {
                            if (Calc.ParseVector3(line.Slice(2), ' ', out var position))
                            {
                                Positions.Add(position);
                            }
                        }
                    }
                    else if (line[0] == 'f' && line.Length > 3)
                    {
                        if (obj == null)
                        {
                            obj = new Obj("Unnamed");
                            Objects.Add(obj.Name, obj);
                        }

                        var face = new Face {
                            VertexIndex = obj.Vertices.Count
                        };
                        var data = line.Slice(2);
                        var next = data;

                        while ((next = NextSplit(ref data, ' ')).Length > 0)
                        {
                            var vertex = new Vertex();
                            var i      = 0;
                            while (next.Length > 0)
                            {
                                var sub = NextSplit(ref next, '/');

                                if (sub.Length > 0)
                                {
                                    if (i == 0)
                                    {
                                        vertex.PositionIndex = int.Parse(sub) - 1;
                                    }
                                    else if (i == 1)
                                    {
                                        vertex.NormalIndex = int.Parse(sub) - 1;
                                    }
                                    else if (i == 2)
                                    {
                                        vertex.TexcoordIndex = int.Parse(sub) - 1;
                                    }
                                }

                                i++;
                            }

                            obj.Vertices.Add(vertex);
                            face.VertexCount++;
                        }

                        obj.Faces.Add(face);
                    }
                }

                // shift memory back & read more
                remaining.CopyTo(buffer);
                var offset = buffer.Slice(remaining.Length);
                var read   = reader.Read(offset);

                // how much is left to read
                remaining = buffer.Slice(0, remaining.Length + read);

                // reached the end
                if (read < offset.Length)
                {
                    eof = true;
                }
            }
        }
Beispiel #2
0
        protected override void CreateGeometry()
        {
            base.CreateGeometry();

            if (!GenerateGeometry)
            {
                return;
            }

            //create buffer descriptions
            var vDesc = new BufferDesc()
            {
                Width = (uint)Positions.Count, Format = Format.Float3, Type = BufferType.Input
            };
            var nDesc = new BufferDesc()
            {
                Width = (uint)Normals.Count, Format = Format.Float3, Type = BufferType.Input
            };
            var tcDesc = new BufferDesc()
            {
                Width = (uint)Texcoords.Count, Format = Format.Float2, Type = BufferType.Input
            };

            // Create the buffers to hold our geometry data
            var vBuffer  = new OptixBuffer(Context, vDesc);
            var nBuffer  = new OptixBuffer(Context, nDesc);
            var tcBuffer = new OptixBuffer(Context, tcDesc);

            vBuffer.SetData <Vector3>(Positions.ToArray());
            nBuffer.SetData <Vector3>(Normals.ToArray());
            tcBuffer.SetData <Vector2>(Texcoords.ToArray());

            List <GeometryInstance> instances = new List <GeometryInstance>();

            foreach (ObjGroup group in Groups)
            {
                //empty group
                if (group.VIndices.Count == 0 && group.NIndices.Count == 0 && group.TIndices.Count == 0)
                {
                    continue;
                }

                //ValidateGroup( group );

                var normalsUseVIndices = GenerateNormals && group.NIndices.Count == 0 && Normals.Count > 0;

                if (normalsUseVIndices)
                {
                    Debug.Assert(Normals.Count == Positions.Count);
                }

                var numNormIndices = normalsUseVIndices ? group.VIndices.Count : group.NIndices.Count;

                var viDesc = new BufferDesc {
                    Width = (uint)group.VIndices.Count, Format = Format.Int3, Type = BufferType.Input
                };
                var niDesc = new BufferDesc {
                    Width = (uint)numNormIndices, Format = Format.Int3, Type = BufferType.Input
                };
                var tiDesc = new BufferDesc {
                    Width = (uint)group.TIndices.Count, Format = Format.Int3, Type = BufferType.Input
                };

                var viBuffer = new OptixBuffer(Context, viDesc);
                var niBuffer = new OptixBuffer(Context, niDesc);
                var tiBuffer = new OptixBuffer(Context, tiDesc);

                viBuffer.SetData(group.VIndices.ToArray());
                //if normals weren't in the obj and we genereated them, use the vertex indices
                niBuffer.SetData(normalsUseVIndices ? group.VIndices.ToArray() : group.NIndices.ToArray());
                tiBuffer.SetData(group.TIndices.ToArray());

                //create a geometry node and set the buffers
                var geometry = new Geometry(Context);
                geometry.IntersectionProgram = new OptixProgram(Context, IntersecitonProgPath, IntersecitonProgName);
                geometry.BoundingBoxProgram  = new OptixProgram(Context, BoundingBoxProgPath, BoundingBoxProgName);
                geometry.PrimitiveCount      = (uint)group.VIndices.Count;

                geometry["vertex_buffer"].Set(vBuffer);
                geometry["normal_buffer"].Set(nBuffer);
                geometry["texcoord_buffer"].Set(tcBuffer);
                geometry["vindex_buffer"].Set(viBuffer);
                geometry["nindex_buffer"].Set(niBuffer);
                geometry["tindex_buffer"].Set(tiBuffer);

                //create a geometry instance
                GeometryInstance instance = new GeometryInstance(Context);
                instance.Geometry = geometry;
                instance.AddMaterial(_materialResolveFunc(group.mtrl) ?? DefaultMaterial);

                if (group.mtrl != null)
                {
                    ObjMaterial mtrl = mMtrls[group.mtrl];
                    instance["diffuse_color"].SetFloat3(ref mtrl.Kd);
                    instance["emission_color"].SetFloat3(ref mtrl.Ke);
                }
                else
                {
                    instance["diffuse_color"].Set(1.0f, 1.0f, 1.0f);
                }

                instances.Add(instance);
            }

            //create an acceleration structure for the geometry
            var accel = new Acceleration(Context, Builder, Traverser);

            if (Builder == AccelBuilder.Sbvh || Builder == AccelBuilder.TriangleKdTree)
            {
                accel.VertexBufferName = "vertex_buffer";
                accel.IndexBufferName  = "vindex_buffer";
            }

            //now attach the instance and accel to the geometry group
            GeoGroup.Acceleration = accel;
            GeoGroup.AddChildren(instances);
        }