Пример #1
0
        public override void Run(RenderControl render)
        {
            if (!ReadData())
            {
                return;
            }

            var material = MeshPhongMaterial.Create("cae-material");

            material.GetTemplate().SetVertexColors(true);
            material.SetFaceSide(EnumFaceSide.DoubleSide);


            var position = BufferAttribute.Create(EnumAttributeSemantic.Position, EnumAttributeComponents.Three, mPositions);
            var color    = BufferAttribute.Create(EnumAttributeSemantic.Color, EnumAttributeComponents.Three, mColors);

            BufferGeometry geometry = new BufferGeometry();

            geometry.AddAttribute(position);
            geometry.AddAttribute(color);

            NormalCalculator.ComputeVertexNormals(geometry);

            var node = new PrimitiveSceneNode(geometry, EnumPrimitiveType.TRIANGLES, material);

            node.SetPickable(false);

            PaletteWidget pw = new PaletteWidget();

            pw.Update(mColorTable);

            render.ShowSceneNode(pw);

            render.ShowSceneNode(node);
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="control"></param>
        public override void Load(Control control)
        {
            base.Load(control);

            //

            camera = new PerspectiveCamera(27, control.Width / (float)control.Height, 1, 4000);
            this.camera.Position.Z = 2750;

            scene = new Scene();


            const int segments = 10000;

            var geometry = new BufferGeometry();
            var material = new LineBasicMaterial {
                VertexColors = 2
            };

            var positions = new float[segments * 3];
            var colors    = new float[segments * 3];

            const float r = 800.0f;

            for (var i = 0; i < segments; i++)
            {
                var x = Mat.Random() * r - r / 2;
                var y = Mat.Random() * r - r / 2;
                var z = Mat.Random() * r - r / 2;

                // positions

                positions[i * 3 + 0] = x;
                positions[i * 3 + 1] = y;
                positions[i * 3 + 2] = z;

                // colors

                colors[i * 3 + 0] = (x / r) + 0.5f;
                colors[i * 3 + 1] = (y / r) + 0.5f;
                colors[i * 3 + 2] = (z / r) + 0.5f;
            }

            geometry.AddAttribute("position", new BufferAttribute <float>(positions, 3));
            geometry.AddAttribute("color", new BufferAttribute <float>(colors, 3));

            geometry.ComputeBoundingSphere();

            mesh = new Line(geometry, material);
            scene.Add(mesh);

            renderer.gammaInput  = true;
            renderer.gammaOutput = true;
        }
Пример #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="control"></param>
        public override void Load(Control control)
        {
            base.Load(control);

            camera = new PerspectiveCamera(50, control.Width / (float)control.Height, 1, 10);
            this.camera.Position.Z = 2;

            scene = new Scene();

            // geometry

            const int triangles = 500;

            var geometry = new BufferGeometry();

            var vertices = new BufferAttribute <float>(new float[triangles * 3 * 3], 3);

            for (var i = 0; i < vertices.length / vertices.ItemSize; i++)
            {
                vertices.SetXYZ(i, (float)(Mat.Random() - 0.5), (float)(Mat.Random() - 0.5), (float)(Mat.Random() - 0.5));
            }

            geometry.AddAttribute("position", vertices);

            var colors = new BufferAttribute <float>(new float[triangles * 3 * 4], 4);

            for (var i = 0; i < colors.length / colors.ItemSize; i++)
            {
                colors.SetXYZW(i, Mat.Random(), Mat.Random(), Mat.Random(), Mat.Random());
            }

            geometry.AddAttribute("color", colors);

            // material

            var material = new RawShaderMaterial()
            {
                Uniforms = new Uniforms {
                    { "time", new Uniform()
                      {
                          { "type", "f" }, { "value", 1.0f }
                      } }
                },
                VertexShader   = VertexShader,
                FragmentShader = FragmentShader,
                Side           = Three.DoubleSide,
                Transparent    = true,
            };

            mesh = new Mesh(geometry, material);
            scene.Add(mesh);

            renderer.SetClearColor((Color)colorConvertor.ConvertFromString("#101010"));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="control"></param>
        public override void Load(Control control)
        {
            base.Load(control);

            camera = new PerspectiveCamera(27, control.Width / (float)control.Height, 5, 3500);
            this.camera.Position.Z = 2750;

            scene     = new Scene();
            scene.Fog = new Fog((Color)colorConvertor.ConvertFromString("#050505"), 2000, 3500);

            //

            const int Particles = 500000;

            var positions = new float[Particles * 3];
            var colors    = new float[Particles * 3];

            var n = 1000; var n2 = n / 2; // particles spread in the cube

            for (var i = 0; i < positions.Length; i += 3)
            {
                // positions

                var x = Mat.Random() * n - n2;
                var y = Mat.Random() * n - n2;
                var z = Mat.Random() * n - n2;

                positions[i + 0] = x;
                positions[i + 1] = y;
                positions[i + 2] = z;

                // colors

                var vx = (x / n) + 0.5f;
                var vy = (y / n) + 0.5f;
                var vz = (z / n) + 0.5f;

                colors[i + 0] = vx;
                colors[i + 1] = vy;
                colors[i + 2] = vz;
            }

            var geometry = new BufferGeometry();

            geometry.AddAttribute("position", new BufferAttribute <float>(positions, 3));
            geometry.AddAttribute("color", new BufferAttribute <float>(colors, 3));

            geometry.ComputeBoundingSphere();

            //

            var material = new PointCloudMaterial()
            {
                Size = 15, VertexColors = Three.VertexColors
            };

            particleSystem = new PointCloud(geometry, material);
            scene.Add(particleSystem);

            //

            renderer.SetClearColor(scene.Fog.Color);
        }
Пример #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="control"></param>
        public override void Load(Control control)
        {
            base.Load(control);

            camera = new PerspectiveCamera(27, control.Width / (float)control.Height, 1, 3500);
            this.camera.Position.Z = 2750;

            scene     = new Scene();
            scene.Fog = new Fog((Color)colorConvertor.ConvertFromString("#050505"), 2000, 3500);

            scene.Add(new AmbientLight((Color)colorConvertor.ConvertFromString("#444444")));

            var light1 = new DirectionalLight(Color.White, 0.5f);

            light1.Position = new Vector3(1, 1, 1);
            scene.Add(light1);

            var light2 = new DirectionalLight(Color.White, 1.5f);

            light2.Position = new Vector3(0, -1, 0);
            scene.Add(light2);

            const int triangles = 160000;

            var geometry = new BufferGeometry();

            var indices = new uint[triangles * 3];

            for (uint i = 0; i < indices.Length; i++)
            {
                indices[i] = i;
            }

            var positions = new float[triangles * 3 * 3];
            var normals   = new float[triangles * 3 * 3];
            var colors    = new float[triangles * 3 * 3];

            var color = Color.White;

            const int n = 800; var n2 = n / 2;  // triangles spread in the cube
            const int d = 12; var d2 = d / 2;   // individual triangle size

            for (var i = 0; i < positions.Length; i += 9)
            {
                // positions

                var x = Mat.Random() * n - n2;
                var y = Mat.Random() * n - n2;
                var z = Mat.Random() * n - n2;

                var ax = x + Mat.Random() * d - d2;
                var ay = y + Mat.Random() * d - d2;
                var az = z + Mat.Random() * d - d2;

                var bx = x + Mat.Random() * d - d2;
                var by = y + Mat.Random() * d - d2;
                var bz = z + Mat.Random() * d - d2;

                var cx = x + Mat.Random() * d - d2;
                var cy = y + Mat.Random() * d - d2;
                var cz = z + Mat.Random() * d - d2;

                positions[i + 0] = ax;
                positions[i + 1] = ay;
                positions[i + 2] = az;

                positions[i + 3] = bx;
                positions[i + 4] = by;
                positions[i + 5] = bz;

                positions[i + 6] = cx;
                positions[i + 7] = cy;
                positions[i + 8] = cz;

                // flat face normals

                var pA = new Vector3(ax, ay, az);
                var pB = new Vector3(bx, by, bz);
                var pC = new Vector3(cx, cy, cz);

                var cb = new Vector3().SubtractVectors(pC, pB);
                var ab = new Vector3().SubtractVectors(pA, pB);
                cb.Cross(ab).Normalize();

                var nx = cb.X;
                var ny = cb.Y;
                var nz = cb.Z;

                normals[i + 0] = nx;
                normals[i + 1] = ny;
                normals[i + 2] = nz;

                normals[i + 3] = nx;
                normals[i + 4] = ny;
                normals[i + 5] = nz;

                normals[i + 6] = nx;
                normals[i + 7] = ny;
                normals[i + 8] = nz;

                // colors

                var vx = (x / n) + 0.5;
                var vy = (y / n) + 0.5;
                var vz = (z / n) + 0.5;

                color = Color.FromArgb(255, (int)(vx * 255), (int)(vy * 255), (int)(vz * 255));

                colors[i + 0] = color.R / 255.0f;
                colors[i + 1] = color.G / 255.0f;
                colors[i + 2] = color.B / 255.0f;

                colors[i + 3] = color.R / 255.0f;
                colors[i + 4] = color.G / 255.0f;
                colors[i + 5] = color.B / 255.0f;

                colors[i + 6] = color.R / 255.0f;
                colors[i + 7] = color.G / 255.0f;
                colors[i + 8] = color.B / 255.0f;
            }


            geometry.AddAttribute("index", new BufferAttribute <uint>(indices, 1));
            geometry.AddAttribute("position", new BufferAttribute <float>(positions, 3));
            geometry.AddAttribute("normal", new BufferAttribute <float>(normals, 3));
            geometry.AddAttribute("color", new BufferAttribute <float>(colors, 3));

            geometry.ComputeBoundingSphere();

            var material = new MeshPhongMaterial
            {
                Color        = (Color)colorConvertor.ConvertFromString("#aaaaaa"),
                Ambient      = (Color)colorConvertor.ConvertFromString("#aaaaaa"),
                Specular     = (Color)colorConvertor.ConvertFromString("#ffffff"),
                Shininess    = 250,
                Side         = Three.DoubleSide,
                VertexColors = Three.VertexColors,
            };

            this.mesh = new Mesh(geometry, material);
            scene.Add(mesh);

            renderer.SetClearColor(scene.Fog.Color);

            renderer.gammaInput  = true;
            renderer.gammaOutput = true;
        }
Пример #6
0
        /// <summary>
        ///
        /// </summary>
        private Object3D Parse(string text)
        {
            // v float float float

            var vertex_pattern = @"v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)";

            // vn float float float

            var normal_pattern = @"vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)";

            // vt float float

            var uv_pattern = @"vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)";

            // f vertex vertex vertex ...

            var face_pattern1 = @"f( +-?\d+)( +-?\d+)( +-?\d+)( +-?\d+)?";

            // f vertex/uv vertex/uv vertex/uv ...

            var face_pattern2 = @"f( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+))?";

            // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...

            var face_pattern3 = @"f( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))?";

            // f vertex//normal vertex//normal vertex//normal ...

            var face_pattern4 = @"f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?";


            var lines = text.Split('\n');

            for (var i = 0; i < lines.Length; i++)
            {
                var line = lines[i];
                line = line.Trim();

                if (line.Length == 0 || line[0] == '#')
                {
                    continue;
                }

                {
                    var rgx     = new Regex(vertex_pattern, RegexOptions.IgnoreCase);
                    var matches = rgx.Matches(line);

                    foreach (Match match in matches)
                    {
                        this._vertices.AddRange(new [] { floatParse(match.Groups[1].Value), floatParse(match.Groups[2].Value), floatParse(match.Groups[3].Value) });
                    }

                    if (matches.Count > 0)
                    {
                        continue;
                    }
                }

                {
                    var rgx     = new Regex(normal_pattern, RegexOptions.IgnoreCase);
                    var matches = rgx.Matches(line);

                    foreach (Match match in matches)
                    {
                        this._normals.AddRange(new[] { floatParse(match.Groups[1].Value), floatParse(match.Groups[2].Value), floatParse(match.Groups[3].Value) });
                    }

                    if (matches.Count > 0)
                    {
                        continue;
                    }
                }

                {
                    var rgx     = new Regex(uv_pattern, RegexOptions.IgnoreCase);
                    var matches = rgx.Matches(line);

                    foreach (Match match in matches)
                    {
                        this._uvs.AddRange(new[] { floatParse(match.Groups[1].Value), floatParse(match.Groups[2].Value) });
                    }

                    if (matches.Count > 0)
                    {
                        continue;
                    }
                }

                {
                    var rgx     = new Regex(face_pattern1, RegexOptions.IgnoreCase);
                    var matches = rgx.Matches(line);

                    foreach (Match match in matches)
                    {
                        addFace(
                            intParse(match.Groups[1].Value), intParse(match.Groups[2].Value), intParse(match.Groups[3].Value), intParse(match.Groups[4].Value),
                            null, null, null, null,
                            null, null, null, null);
                    }

                    if (matches.Count > 0)
                    {
                        continue;
                    }
                }

                {
                    var rgx     = new Regex(face_pattern2, RegexOptions.IgnoreCase);
                    var matches = rgx.Matches(line);

                    foreach (Match match in matches)
                    {
                        addFace(
                            intParse(match.Groups[2].Value), intParse(match.Groups[5].Value), intParse(match.Groups[8].Value), intParse(match.Groups[11].Value),
                            intParse(match.Groups[3].Value), intParse(match.Groups[6].Value), intParse(match.Groups[9].Value), intParse(match.Groups[12].Value),
                            null, null, null, null);
                    }

                    if (matches.Count > 0)
                    {
                        continue;
                    }
                }

                {
                    var rgx     = new Regex(face_pattern3, RegexOptions.IgnoreCase);
                    var matches = rgx.Matches(line);

                    foreach (Match match in matches)
                    {
                        addFace(
                            intParse(match.Groups[2].Value), intParse(match.Groups[6].Value), intParse(match.Groups[10].Value), intParse(match.Groups[14].Value),
                            intParse(match.Groups[3].Value), intParse(match.Groups[7].Value), intParse(match.Groups[11].Value), intParse(match.Groups[15].Value),
                            intParse(match.Groups[4].Value), intParse(match.Groups[8].Value), intParse(match.Groups[12].Value), intParse(match.Groups[16].Value));
                    }

                    if (matches.Count > 0)
                    {
                        continue;
                    }
                }


                {
                    var rgx     = new Regex(face_pattern4, RegexOptions.IgnoreCase);
                    var matches = rgx.Matches(line);

                    foreach (Match match in matches)
                    {
                        addFace(
                            intParse(match.Groups[2].Value), intParse(match.Groups[5].Value), intParse(match.Groups[8].Value), intParse(match.Groups[11].Value),
                            null, null, null, null,
                            intParse(match.Groups[3].Value), intParse(match.Groups[6].Value), intParse(match.Groups[9].Value), intParse(match.Groups[12].Value));
                    }

                    if (matches.Count > 0)
                    {
                        continue;
                    }
                }

                if (line.Contains("o "))
                {
                    this._geometry = new Geometry();

                    this._material = new Material();

                    this._object = new Objekt {
                        name = line.Substring(2, line.Length - 2).Trim(), Geometry = this._geometry, Material = this._material
                    };

                    this._objects.Add(this._object);

                    continue;
                }

                if (line.Contains("g "))
                {
                    // group
                    continue;
                }

                if (line.Contains("usemtl "))
                {
                    // material

                    this._material.name = line.Substring(7, line.Length - 7).Trim();

                    continue;
                }

                if (line.Contains("mtllib "))
                {
                    // mtl file
                    continue;
                }

                if (line.Contains("s "))
                {
                    // // smooth shading
                    continue;
                }

                Trace.TraceInformation("OBJLoader: Unhandled line " + line);
            }

            var container = new Object3D();

            for (var i = 0; i < this._objects.Count; i++)
            {
                var obj  = this._objects[i];
                var geom = obj.Geometry;

                var buffergeometry = new BufferGeometry();

                buffergeometry.AddAttribute("position", new BufferAttribute <float>(geom.Vertices.ToArray(), 3));

                if (geom.Normals.Count > 0)
                {
                    buffergeometry.AddAttribute("normal", new BufferAttribute <float>(geom.Normals.ToArray(), 3));
                }

                if (geom.Uvs.Count > 0)
                {
                    buffergeometry.AddAttribute("uv", new BufferAttribute <float>(geom.Uvs.ToArray(), 2));
                }

                var mat = new MeshLambertMaterial();
                mat.Name = obj.Material.name;

                var mesh = new Mesh(buffergeometry, mat);
                mesh.Name = obj.name;

                container.Add(mesh);
            }

            return(container);
        }
Пример #7
0
        /// <summary>
        ///
        /// </summary>
        private BufferGeometry Parse(string data)
        {
            var indices   = new List <uint>();
            var positions = new List <float>();


            // float float float

            {
                string pattern = @"([\+|\-]?[\d]+[\.][\d|\-|e]+)[ ]+([\+|\-]?[\d]+[\.][\d|\-|e]+)[ ]+([\+|\-]?[\d]+[\.][\d|\-|e]+)";

                var rgx     = new Regex(pattern, RegexOptions.IgnoreCase);
                var matches = rgx.Matches(data);

                foreach (Match match in matches)
                {
                    // ["1.0 2.0 3.0", "1.0", "2.0", "3.0"]

                    var x = float.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
                    var y = float.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
                    var z = float.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture);

                    positions.Add(x); positions.Add(y); positions.Add(z);
                }
            }

            // 3 int int int

            {
                string pattern = @"3[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)";

                var rgx     = new Regex(pattern, RegexOptions.IgnoreCase);
                var matches = rgx.Matches(data);

                foreach (Match match in matches)
                {
                    // ["3 1 2 3", "1", "2", "3"]
                    try
                    {
                        var a = uint.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
                        var b = uint.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
                        var c = uint.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture);

                        indices.Add(a); indices.Add(b); indices.Add(c);
                    }
                    catch (Exception e)
                    {
                        Trace.TraceError(e.Message);
                    }
                }
            }

            // 4 int int int int

            {
                string pattern = @"4[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)";

                var rgx     = new Regex(pattern, RegexOptions.IgnoreCase);
                var matches = rgx.Matches(data);

                foreach (Match match in matches)
                {
                    // ["4 1 2 3 4", "1", "2", "3", "4"]

                    var a = uint.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
                    var b = uint.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
                    var c = uint.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture);
                    var d = uint.Parse(match.Groups[4].Value, CultureInfo.InvariantCulture);

                    indices.Add(a); indices.Add(b); indices.Add(d);
                    indices.Add(b); indices.Add(c); indices.Add(d);
                }
            }

            var geometry = new BufferGeometry();

            geometry.AddAttribute("index", new BufferAttribute <uint>(indices.ToArray(), 1));
            geometry.AddAttribute("position", new BufferAttribute <float>(positions.ToArray(), 3));

            return(geometry);
        }
Пример #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="control"></param>
        public override void Load(Control control)
        {
            base.Load(control);

            //

            camera = new PerspectiveCamera(50, control.Width / (float)control.Height, 1, 4000);
            // new OrthographicCamera(-control.Width/20, control.Width / 20, -control.Height / 20, control.Height / 20);//
            this.camera.Position.Z = 50;

            camera.LookAt(new Vector3(0, 0, 0));

            controls = new CamControl(control, camera);

            controls.RotateSpeed = 5;
            controls.ZoomSpeed   = 5;
            controls.PanSpeed    = 2;



            controls.StaticMoving         = true;
            controls.DynamicDampingFactor = 0.4f;

            scene = new Scene();
            scene.Add(camera);

            var material = new LineBasicMaterial {
                VertexColors = ThreeCs.Three.VertexColors
            };

            if (dataList != null)
            {
                foreach (var data in dataList)
                {
                    int segments  = data.Count;
                    var geometry  = new BufferGeometry();
                    var positions = new float[segments * 3];
                    var colors    = new float[segments * 3];

                    for (int i = 0; i < segments; i++)
                    {
                        positions[i * 3 + 0] = data[i].X;
                        positions[i * 3 + 1] = data[i].Y;
                        positions[i * 3 + 2] = data[i].Z * 5;

                        colors[i * 3 + 0] = 0.5f;
                        colors[i * 3 + 1] = 0.5f;
                        colors[i * 3 + 2] = 0.5f;
                    }

                    geometry.AddAttribute("position", new BufferAttribute <float>(positions, 3));
                    geometry.AddAttribute("color", new BufferAttribute <float>(colors, 3));

                    geometry.ComputeBoundingSphere();

                    mesh = new Line(geometry, material);
                    scene.Add(mesh);
                }
            }



            renderer.gammaInput  = true;
            renderer.gammaOutput = true;
        }
Пример #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="control"></param>
        public override void Load(Control control)
        {
            base.Load(control);

            camera            = new PerspectiveCamera(27, control.Width / (float)control.Height, 1, 3500);
            camera.Position.Z = 2750;

            scene     = new Scene();
            scene.Fog = new Fog((Color)colorConvertor.ConvertFromString("#050505"), 2000, 3500);

            scene.Add(new AmbientLight((Color)colorConvertor.ConvertFromString("#444444")));

            var light1 = new DirectionalLight(Color.White, 0.5f);

            light1.Position = new Vector3(1, 1, 1);
            scene.Add(light1);

            var light2 = new DirectionalLight(Color.White, 1.5f);

            light2.Position = new Vector3(0, -1, 0);
            scene.Add(light2);

            //

            const int Triangles = 5000;

            var geometry = new BufferGeometry();

            var positions = new float[Triangles * 3 * 3];
            var normals   = new float[Triangles * 3 * 3];
            var colors    = new float[Triangles * 3 * 3];

            var color = new Color();

            const int n = 800; const int n2 = n / 2; // triangles spread in the cube
            const int d = 120; const int d2 = d / 2; // individual triangle size

            for (var i = 0; i < positions.Length; i += 9)
            {
                // positions

                var r = 0.5f;

                var x = getRandom() * n - n2;
                var y = getRandom() * n - n2;
                var z = getRandom() * n - n2;

                var ax = x + getRandom() * d - d2;
                var ay = y + getRandom() * d - d2;
                var az = z + getRandom() * d - d2;

                var bx = x + getRandom() * d - d2;
                var by = y + getRandom() * d - d2;
                var bz = z + getRandom() * d - d2;

                var cx = x + getRandom() * d - d2;
                var cy = y + getRandom() * d - d2;
                var cz = z + getRandom() * d - d2;

                positions[i]     = ax;
                positions[i + 1] = ay;
                positions[i + 2] = az;

                positions[i + 3] = bx;
                positions[i + 4] = by;
                positions[i + 5] = bz;

                positions[i + 6] = cx;
                positions[i + 7] = cy;
                positions[i + 8] = cz;

                // flat face normals

                var pA = new Vector3(ax, ay, az);
                var pB = new Vector3(bx, by, bz);
                var pC = new Vector3(cx, cy, cz);

                var cb = pC - pB;
                var ab = pA - pB;
                cb.Cross(ab).Normalize();

                var nx = cb.X;
                var ny = cb.Y;
                var nz = cb.Z;

                normals[i]     = nx;
                normals[i + 1] = ny;
                normals[i + 2] = nz;

                normals[i + 3] = nx;
                normals[i + 4] = ny;
                normals[i + 5] = nz;

                normals[i + 6] = nx;
                normals[i + 7] = ny;
                normals[i + 8] = nz;

                // colors

                var vx = (x / n) + 0.5;
                var vy = (y / n) + 0.5;
                var vz = (z / n) + 0.5;

                color = Color.FromArgb(255, (int)(vx * 255), (int)(vy * 255), (int)(vz * 255));

                colors[i]     = color.R / 255.0f;
                colors[i + 1] = color.G / 255.0f;
                colors[i + 2] = color.B / 255.0f;

                colors[i + 3] = color.R / 255.0f;
                colors[i + 4] = color.G / 255.0f;
                colors[i + 5] = color.B / 255.0f;

                colors[i + 6] = color.R / 255.0f;
                colors[i + 7] = color.G / 255.0f;
                colors[i + 8] = color.B / 255.0f;
            }

            geometry.AddAttribute("position", new BufferAttribute <float>(positions, 3));
            geometry.AddAttribute("normal", new BufferAttribute <float>(normals, 3));
            geometry.AddAttribute("color", new BufferAttribute <float>(colors, 3));

            geometry.ComputeBoundingSphere();

            var material = new MeshPhongMaterial()
            {
                Color     = (Color)colorConvertor.ConvertFromString("#aaaaaa"),
                Ambient   = (Color)colorConvertor.ConvertFromString("#aaaaaa"),
                Specular  = Color.White,
                Shininess = 250,
                Side      = Three.DoubleSide, VertexColors = Three.VertexColors,
            };

            mesh = new Mesh(geometry, material);
            scene.Add(mesh);

            //

            projector = new Projector();
            raycaster = new Raycaster();

            mouse = new Vector2();

            var geometry2 = new BufferGeometry();

            geometry2.AddAttribute("position", new BufferAttribute <float>(new float[4 * 3], 3));

            var material2 = new LineBasicMaterial()
            {
                Color = Color.White, Linewidth = 2, Transparent = true
            };

            line = new Line(geometry2, material2);
            scene.Add(line);

            renderer.SetClearColor(scene.Fog.Color);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="control"></param>
        public override void Load(Control control)
        {
            base.Load(control);

            camera = new PerspectiveCamera(40, control.Width / (float)control.Height, 1, 10000);
            this.camera.Position.Z = 300;

            scene = new Scene();

            var attributes = new Attributes
            {
                { "size", new Attribute()
                  {
                      { "f", null }
                  } },
                { "customcolor", new Attribute()
                  {
                      { "c", null }
                  } }
            };

            uniforms = new Uniforms
            {
                { "color", new Uniform()
                  {
                      { "type", "c" }, { "value", Color.White }
                  } },
                { "texture", new Uniform()
                  {
                      { "type", "t" }, { "value", ImageUtils.LoadTexture(@"examples\textures/sprites/spark1.png") }
                  } },
            };

            var shaderMaterial = new ShaderMaterial()
            {
                Uniforms       = uniforms,
                Attributes     = attributes,
                VertexShader   = VertexShader,
                FragmentShader = FragmentShader,

                Blending    = ThreeCs.Three.AdditiveBlending,
                DepthTest   = false,
                Transparent = true
            };

            const int Radius = 200;

            geometry = new BufferGeometry();

            var positions    = new float[Particles * 3];
            var values_color = new float[Particles * 3];
            var values_size  = new float[Particles];

            var color = new Color();

            for (var v = 0; v < Particles; v++)
            {
                values_size[v] = 20;

                positions[v * 3 + 0] = (Mat.Random() * 2 - 1) * Radius;
                positions[v * 3 + 1] = (Mat.Random() * 2 - 1) * Radius;
                positions[v * 3 + 2] = (Mat.Random() * 2 - 1) * Radius;

                color = new HSLColor(512 * v / (float)Particles, 1.0f, 0.5f);
                color = Color.DeepPink;

                values_color[v * 3 + 0] = color.R;
                values_color[v * 3 + 1] = color.G;
                values_color[v * 3 + 2] = color.B;
            }

            geometry.AddAttribute("position", new BufferAttribute <float>(positions, 3));
            geometry.AddAttribute("customColor", new BufferAttribute <float>(values_color, 3));
            geometry.AddAttribute("size", new BufferAttribute <float>(values_size, 1));

            particleSystem = new PointCloud(geometry, shaderMaterial);

            scene.Add(particleSystem);
        }