Ejemplo n.º 1
0
        private void BuildGeometry(SceneMeshData SceneData, SceneMeshEntity[] sceneMesh, bool hasAreaLights = false, IEnumerable<SceneLightsource> areaLights = null)
        {
            topObject = new GeometryGroup(Session.OptixContext);
            Session.OptixContext["scene_sphere_radius"].Set(SceneData.BoundingSphereRadius);
            Session.OptixContext["scene_sphere_center"].SetFloat3(SceneData.BoundingSphereCenter);

            var vDesc = new BufferDesc { Width = (uint)SceneData.Positions.Count, Format = Format.Float3, Type = BufferType.Input };
            var nDesc = new BufferDesc { Width = (uint)SceneData.Normals.Count, Format = Format.Float3, Type = BufferType.Input };
            var tcDesc = new BufferDesc { Width = (uint)SceneData.TexCoords.Count, Format = Format.Float2, Type = BufferType.Input };

            var vBuffer = new Buffer(Session.OptixContext, vDesc);
            var nBuffer = new Buffer(Session.OptixContext, nDesc);
            var tcBuffer = new Buffer(Session.OptixContext, tcDesc);

            vBuffer.SetData(SceneData.Positions.ToArray());
            nBuffer.SetData(SceneData.Normals.ToArray());
            tcBuffer.SetData(SceneData.TexCoords.ToArray());

            var lightTriangleIndexes = new Dictionary<string, List<int>>(StringComparer.InvariantCultureIgnoreCase);

            var instances = new List<GeometryInstance>();
            var triLights = new List<TriangleLight>();
            int idx = 0;
            foreach (var group in sceneMesh)
            {
                //empty group

                if (group.VertexIndexes.Count == 0 && group.NormalIndexes.Count == 0 && group.TextureIndexes.Count == 0)
                    continue;

                var center = new Vector3();
                foreach (var vi in group.VertexIndexes)
                {
                    center += SceneData.Positions[vi.X];
                    center += SceneData.Positions[vi.Y];
                    center += SceneData.Positions[vi.Z];
                    center /= 3.0f;
                }
                //ValidateGroup( group );

                //var mat = this.ResolveMaterial(group.Material);

                bool normalsUseVIndices = GenerateNormals && group.NormalIndexes.Count == 0 && SceneData.Normals.Count > 0;

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

                int numNormIndices = normalsUseVIndices ? group.VertexIndexes.Count : group.NormalIndexes.Count;

                var viDesc = new BufferDesc() { Width = (uint)group.VertexIndexes.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.TextureIndexes.Count, Format = Format.Int3, Type = BufferType.Input };

                var viBuffer = new Buffer(Session.OptixContext, viDesc);
                var niBuffer = new Buffer(Session.OptixContext, niDesc);
                var tiBuffer = new Buffer(Session.OptixContext, tiDesc);

                viBuffer.SetData(group.VertexIndexes.ToArray());
                niBuffer.SetData(normalsUseVIndices ? group.VertexIndexes.ToArray() : group.NormalIndexes.ToArray());
                tiBuffer.SetData(group.TextureIndexes.ToArray());

                var geometry = new Geometry(Session.OptixContext);
                string intersect_program = "mesh_intersect";
                string isect_script = IntersectionScript;
                //if (!string.IsNullOrWhiteSpace(group.mtrl) && matTypes.ContainsKey(group.mtrl))
                //{
                //    if (matTypes[group.mtrl].Equals("Volume"))
                //    {
                //        intersect_program = "volume_mesh_intersect";
                //        isect_script = GetScript("triangle_mesh_iterative.ptx");
                //    }
                //}

                geometry.IntersectionProgram = new Program(Session.OptixContext, isect_script, intersect_program);
                geometry.BoundingBoxProgram = new Program(Session.OptixContext, isect_script, "mesh_bounds");
                geometry.PrimitiveCount = (uint)group.VertexIndexes.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);

                var instance = new GeometryInstance(Session.OptixContext);
                instance.Geometry = geometry;
                instance["geometric_center"].SetFloat3(center);
                //instance.AddMaterial(mat);
                group.EngineEntity = geometry;
                if (group.Material != null)
                {
                    int lindex;
                    if (hasAreaLights && MeshIsLight(group.Name, out lindex))
                    {
                        instance.AddMaterial(this.GetLightMaterial(group.Material, lindex));
                    }
                    else
                    {
                        var mtrl = ResolveMaterial(group.Material);

                        if (mtrl != null)
                        {
                            group.Material.EngineEntity = mtrl;
                            instance.AddMaterial(mtrl);
                            SetDefaultMaterialProperties(instance, mtrl, group.Material);
                        }
                        else
                        {
                            Tracer.WriteLine("Mesh {0} missed material {1}", group.Name, group.Material.Name);
                        }
                    }
                }
                else
                {
                    Tracer.WriteLine("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ----Mesh {0} missed material {1}", group.Name, group.Material);
                    Console.ReadLine();
                }

                //if (!string.IsNullOrWhiteSpace(LightNameTemplate))
                //{
                //    Regex lightReg = new Regex(LightNameTemplate, RegexOptions.IgnoreCase);

                //    if (lightReg.IsMatch(group.Name))
                //    {
                //        var lt = new Lightsource()
                //        {
                //            Type = LightSourceTypes.Area,
                //            Emission = Scene.LightGain,
                //            Name = group.Name,
                //        };
                //        lt[Lightsource.AreaMeshName] = group.Name;
                //        Scene.Lights = Scene.Lights.Union(new[] { lt }).ToArray();
                //    }
                //}

                if (hasAreaLights)
                {
                    var light =
                        areaLights.FirstOrDefault(
                            lt => lt.Name.Equals(group.Name, StringComparison.InvariantCultureIgnoreCase));
                    //    SetDefaultLightProperties(instance, light);

                    if (light != null)
                    {
                        var ti = new List<int>();
                        lightTriangleIndexes.Add(group.Name, ti);
                        for (int index = 0; index < group.VertexIndexes.Count; index++)
                        {
                            var vIndex = group.VertexIndexes[index];
                            var v1 = SceneData.Positions[vIndex.X];
                            var v2 = SceneData.Positions[vIndex.Y];
                            var v3 = SceneData.Positions[vIndex.Z];
                            var e1 = v2 - v3;
                            var e2 = v1 - v3;
                            Vector3 n = Vector3.Cross(ref e1, ref e2);//SceneGraph.LightOrientation *
                            if (group.NormalIndexes.Any())
                            {
                                n = (SceneData.Normals[group.NormalIndexes[index].X]);//Scene.LightOrientation *
                            }

                            n.Normalize();
                            ti.Add(idx + 1);
                            triLights.Add(new TriangleLight()
                            {
                                color = light.Color, //Emission * emissionScale,
                                v1 = v1,
                                v2 = v2,
                                v3 = v3,
                                normal = n,
                                idx = idx++
                            });
                        }
                    }
                }
                instances.Add(instance);
            }

            var Builder = AccelBuilder.Sbvh;
            var Traverser = AccelTraverser.Bvh;

            //create an acceleration structure for the geometry
            var accel = new Acceleration(Session.OptixContext, 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
            topObject.Acceleration = accel;
            topObject.AddChildren(instances);
            topObject.Acceleration.MarkAsDirty();
            BuildCache.Add("LightTrianglesIndexes", lightTriangleIndexes);
            BuildCache.Add("LightTriangles", triLights);
        }