Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="gameTime"></param>
        void DrawInternal(GameTime gameTime)
        {
            var dev = Game.GraphicsDevice;

            viewMatrix = DMatrix.LookAtRH(cameraPosition, DVector3.Zero, DVector3.UnitY);

            DMatrix vvvM = viewMatrix;

            viewMatrix.TranslationVector = DVector3.Zero;

            var camPos = cameraPosition;

            if (Game.InputDevice.IsKeyDown(Keys.LeftShift))
            {
                DVector3 cameraUp    = cameraPosition / cameraPosition.Length();
                DVector3 lookAtPoint = cameraUp * Config.earthRadius;

                double length = Config.CameraDistance - Config.earthRadius;

                var quat = DQuaternion.RotationAxis(DVector3.UnitY, FreeCamYaw) * DQuaternion.RotationAxis(DVector3.UnitX, FreeCamPitch);

                var qRot = DMatrix.RotationQuaternion(quat);
                var mat  = DMatrix.Identity;

                var xAxis = DVector3.TransformNormal(DVector3.UnitX, DMatrix.RotationAxis(DVector3.UnitY, Yaw));
                xAxis.Normalize();

                mat.Up      = cameraUp;
                mat.Right   = xAxis;
                mat.Forward = DVector3.Cross(xAxis, cameraUp);
                mat.Forward.Normalize();

                var matrix = qRot * mat;

                var c = DVector3.Transform(new DVector3(0, 0, length), matrix);

                var camPoint = new DVector3(c.X, c.Y, c.Z) + lookAtPoint;

                camPos = camPoint;

                viewMatrix = DMatrix.LookAtRH(camPoint, lookAtPoint, cameraUp);
                vvvM       = viewMatrix;
                viewMatrix.TranslationVector = DVector3.Zero;
            }

            viewMatrixFloat = DMatrix.ToFloatMatrix(viewMatrix);
            projMatrixFloat = DMatrix.ToFloatMatrix(projMatrix);

            var viewDir = cameraPosition / cameraPosition.Length();

            constBuffer.Data.ViewProj      = viewMatrixFloat * projMatrixFloat;
            constBuffer.Data.ViewPositionX = camPos.X;
            constBuffer.Data.ViewPositionY = camPos.Y;
            constBuffer.Data.ViewPositionZ = camPos.Z;
            constBuffer.Data.Temp          = new Vector4(0.0f, (float)Config.earthRadius, 0, 0);
            constBuffer.Data.ViewDir       = new Vector4((float)viewDir.X, (float)viewDir.Y, (float)viewDir.Z, 0);
            constBuffer.UpdateCBuffer();

            Game.GraphicsDevice.VertexShaderConstants[0] = constBuffer;

            Game.GraphicsDevice.PixelShaderSamplers[0]  = SamplerState.LinearClamp;
            Game.GraphicsDevice.PixelShaderResources[1] = frame;

            if (gridVertexBuffer != null)
            {
                Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
                    GlobeFlags.DRAW_POLY | GlobeFlags.DRAW_VERTEX_POLY | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_TEXTURED | (Config.ShowFrames ? GlobeFlags.SHOW_FRAMES : GlobeFlags.NONE),
                    Primitive.TriangleList,
                    BlendState.AlphaBlend,
                    RasterizerState.CullCW,
                    DepthStencilState.Readonly);

                Game.GraphicsDevice.PixelShaderResources[0] = gridTex;

                Game.GraphicsDevice.SetupVertexInput(gridVertexBuffer, gridIndexBuffer);
                dev.DrawIndexed(/*Primitive.TriangleList,*/ gridIndexBuffer.Capacity, 0, 0);
            }

            var rastState = Game.InputDevice.IsKeyDown(Keys.Tab) ? RasterizerState.Wireframe : RasterizerState.CullCW;

            Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
                GlobeFlags.DRAW_POLY | GlobeFlags.DRAW_VERTEX_POLY | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_TEXTURED | (Config.ShowFrames ? GlobeFlags.SHOW_FRAMES : GlobeFlags.NONE),
                Primitive.TriangleList,
                BlendState.AlphaBlend,
                rastState,
                DepthStencilState.Default);

            foreach (var globeTile in tilesToRender)
            {
                var tex = Game.GetService <LayerService>().MapLayer.CurrentMapSource.GetTile(globeTile.Value.X, globeTile.Value.Y, globeTile.Value.Z).Tile;
                dev.PixelShaderResources[0] = tex;

                dev.SetupVertexInput(globeTile.Value.VertexBuf, globeTile.Value.IndexBuf);
                dev.DrawIndexed(globeTile.Value.IndexBuf.Capacity, 0, 0);
            }


            dotsBuf.Data.View = viewMatrixFloat;
            dotsBuf.Data.Proj = projMatrixFloat;
            dotsBuf.UpdateCBuffer();

            //// Draw simple railroads
            //if (simpleRailroadsVB != null && Config.ShowRailroads) {
            //	Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
            //		GlobeFlags.DRAW_VERTEX_LINES | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_SEGMENTED_LINES,
            //		Primitive.LineList,
            //		BlendState.AlphaBlend,
            //		RasterizerState.CullNone,
            //		DepthStencilState.None);
            //
            //	constBuffer.Data.Temp = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
            //	constBuffer.UpdateCBuffer();
            //
            //	Game.GraphicsDevice.VertexShaderConstants[1]	= dotsBuf;
            //	Game.GraphicsDevice.GeometryShaderConstants[1]	= dotsBuf;
            //	Game.GraphicsDevice.GeometryShaderConstants[0]	= constBuffer;
            //	Game.GraphicsDevice.VertexShaderConstants[0]	= constBuffer;
            //	Game.GraphicsDevice.PixelShaderConstants[0]		= constBuffer;
            //
            //	Game.GraphicsDevice.PixelShaderResources[0] = railRoadsTex;
            //	Game.GraphicsDevice.PixelShaderSamplers[0]	= SamplerState.LinearWrap;
            //
            //	dev.SetupVertexInput(simpleRailroadsVB, null);
            //	dev.Draw(simpleRailroadsVB.Capacity, 0);
            //}


            //// Draw buildings
            //if (contourBuildingsVB != null && Config.ShowBuildingsContours) {
            //
            //	Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
            //		GlobeFlags.DRAW_POLY | GlobeFlags.DRAW_VERTEX_POLY | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_COLOR,
            //		Primitive.LineList,
            //		BlendState.AlphaBlend,
            //		RasterizerState.CullNone,
            //		DepthStencilState.None);
            //
            //
            //	constBuffer.Data.Temp = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
            //	constBuffer.UpdateCBuffer();
            //
            //	Game.GraphicsDevice.VertexShaderConstants[0]	= constBuffer;
            //	Game.GraphicsDevice.PixelShaderConstants[0]		= constBuffer;
            //
            //	dev.SetupVertexInput(contourBuildingsVB, null);
            //	dev.Draw(contourBuildingsVB.Capacity, 0);
            //}

            // Draw Lines
            if (linesBatch.Count != 0 && Config.ShowRoads)
            {
                Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
                    GlobeFlags.DRAW_POLY | GlobeFlags.DRAW_VERTEX_POLY | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_COLOR,
                    Primitive.LineList,
                    BlendState.AlphaBlend,
                    RasterizerState.CullNone,
                    DepthStencilState.None);


                constBuffer.Data.Temp = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
                constBuffer.UpdateCBuffer();

                Game.GraphicsDevice.VertexShaderConstants[0] = constBuffer;
                Game.GraphicsDevice.PixelShaderConstants[0]  = constBuffer;

                foreach (var vb in linesBatch)
                {
                    dev.SetupVertexInput(vb, null);
                    dev.Draw(vb.Capacity, 0);
                }
            }



            // Draw simple railroads
            if (linesPolyBatch.Count != 0 && Config.ShowRoads)
            {
                Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
                    GlobeFlags.DRAW_VERTEX_LINES | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_LINES,
                    Primitive.LineList,
                    BlendState.AlphaBlend,
                    RasterizerState.CullNone,
                    DepthStencilState.None);

                constBuffer.Data.Temp = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
                constBuffer.UpdateCBuffer();

                Game.GraphicsDevice.VertexShaderConstants[1]   = dotsBuf;
                Game.GraphicsDevice.GeometryShaderConstants[1] = dotsBuf;
                Game.GraphicsDevice.GeometryShaderConstants[0] = constBuffer;
                Game.GraphicsDevice.VertexShaderConstants[0]   = constBuffer;
                Game.GraphicsDevice.PixelShaderConstants[0]    = constBuffer;


                foreach (var vb in linesPolyBatch)
                {
                    dev.SetupVertexInput(vb, null);
                    dev.Draw(vb.Capacity, 0);
                }
            }



            if (Config.ShowPOI)
            {
                dotsBuf.Data.TexWHST = new Vector4(geoObjects.Width, geoObjects.Height, 164.0f, 0.05f);
                dotsBuf.UpdateCBuffer();

                Game.GraphicsDevice.VertexShaderConstants[1]   = dotsBuf;
                Game.GraphicsDevice.GeometryShaderConstants[1] = dotsBuf;
                Game.GraphicsDevice.GeometryShaderConstants[0] = constBuffer;

                Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
                    GlobeFlags.DRAW_VERTEX_LINES | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_DOTS | GlobeFlags.DOTS_WORLDSPACE,
                    Primitive.PointList,
                    BlendState.AlphaBlend,
                    RasterizerState.CullNone,
                    DepthStencilState.None);

                Game.GraphicsDevice.PixelShaderResources[0] = geoObjects;
                Game.GraphicsDevice.PixelShaderSamplers[0]  = SamplerState.LinearClamp;

                dev.SetupVertexInput(dotsVB, null);
                dev.Draw(dotsVB.Capacity - geoObjectStart, geoObjectStart);
            }



            // Draw people
            if (Config.ShowPeople)
            {
                dotsBuf.Data.TexWHST = new Vector4(socioClasses.Width, socioClasses.Height, 64.0f, 0.025f);
                dotsBuf.UpdateCBuffer();

                Game.GraphicsDevice.VertexShaderConstants[1]   = dotsBuf;
                Game.GraphicsDevice.GeometryShaderConstants[1] = dotsBuf;
                Game.GraphicsDevice.GeometryShaderConstants[0] = constBuffer;

                Game.GraphicsDevice.PixelShaderResources[0] = socioClasses;
                Game.GraphicsDevice.PixelShaderSamplers[0]  = SamplerState.LinearClamp;

                Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
                    GlobeFlags.DRAW_VERTEX_LINES | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_DOTS | GlobeFlags.DOTS_WORLDSPACE,
                    Primitive.PointList,
                    BlendState.AlphaBlend,
                    RasterizerState.CullNone,
                    DepthStencilState.None);

                dev.SetupVertexInput(dotsVB, null);
                dev.Draw(geoObjectStart - 1, 0);
            }



            //// Draw heatmap
            //if (Config.ShowHeatMap && heatVB != null) {
            //	constBuffer.Data.Temp = new Vector4((float)Config.MaxHeatMapLevel, Config.HeatMapTransparency, HeatMapDim, 0);
            //	constBuffer.UpdateCBuffer();
            //
            //	Game.GraphicsDevice.VertexShaderConstants[0]	= constBuffer;
            //	Game.GraphicsDevice.PixelShaderConstants[0]		= constBuffer;
            //
            //	Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
            //		GlobeFlags.DRAW_POLY | GlobeFlags.DRAW_VERTEX_POLY | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_HEAT,
            //		Primitive.TriangleList,
            //		BlendState.AlphaBlend,
            //		RasterizerState.CullNone,
            //		DepthStencilState.None);
            //
            //
            //	Game.GraphicsDevice.PixelShaderSamplers[0] = SamplerState.LinearClamp;
            //	Game.GraphicsDevice.PixelShaderSamplers[1] = SamplerState.AnisotropicClamp;
            //
            //	Game.GraphicsDevice.PixelShaderResources[0] = heatMap;
            //	Game.GraphicsDevice.PixelShaderResources[1] = heatMapPalette;
            //
            //	Game.GraphicsDevice.SetupVertexInput(heatVB, heatIB);
            //	Game.GraphicsDevice.DrawIndexed(heatIB.Capacity, 0, 0);
            //}

            //// Draw infection map
            //if (Config.ShowInfectHeatMap && heatVB != null) {
            //	constBuffer.Data.Temp = new Vector4((float)Config.MaxInfectLevel, 0.0f, HeatMapDim, 0);
            //	constBuffer.UpdateCBuffer();
            //
            //	Game.GraphicsDevice.VertexShaderConstants[0]	= constBuffer;
            //	Game.GraphicsDevice.PixelShaderConstants[0]		= constBuffer;
            //
            //	Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
            //		GlobeFlags.DRAW_POLY | GlobeFlags.DRAW_VERTEX_POLY | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_HEAT,
            //		Primitive.TriangleList,
            //		BlendState.AlphaBlend,
            //		RasterizerState.CullNone,
            //		DepthStencilState.None);
            //
            //	Game.GraphicsDevice.PixelShaderSamplers[0] = SamplerState.LinearClamp;
            //	Game.GraphicsDevice.PixelShaderSamplers[1] = SamplerState.AnisotropicClamp;
            //
            //	Game.GraphicsDevice.PixelShaderResources[0] = infectMap;
            //	Game.GraphicsDevice.PixelShaderResources[1] = heatMapPalette;
            //
            //	Game.GraphicsDevice.SetupVertexInput(heatVB, heatIB);
            //	Game.GraphicsDevice.DrawIndexed(/*Primitive.TriangleList,*/ heatIB.Capacity, 0, 0);
            //}


            ////Draw atmosphere
            //if (Config.ShowAtmosphere && atmosVB != null) {
            //	constBuffer.Data.Temp = new Vector4(atmosTime, Config.ArrowsScale, 0.0f, 0);
            //	constBuffer.UpdateCBuffer();
            //
            //	Game.GraphicsDevice.VertexShaderConstants[0]	= constBuffer;
            //	Game.GraphicsDevice.PixelShaderConstants[0]		= constBuffer;
            //
            //
            //	Game.GraphicsDevice.PixelShaderResources[0] = atmosTexture;
            //	Game.GraphicsDevice.PixelShaderResources[1] = heatMapPalette;
            //	Game.GraphicsDevice.PixelShaderResources[2] = atmosNextTexture;
            //	Game.GraphicsDevice.PixelShaderResources[3] = arrowTex;
            //
            //
            //	Game.GraphicsDevice.PixelShaderSamplers[0] = SamplerState.LinearClamp;
            //	Game.GraphicsDevice.PixelShaderSamplers[1] = SamplerState.AnisotropicClamp;
            //
            //	Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
            //		GlobeFlags.DRAW_VERTEX_POLY | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_ATMOSPHERE,
            //		Primitive.TriangleList,
            //		BlendState.AlphaBlend,
            //		RasterizerState.CullNone,
            //		DepthStencilState.None);
            //
            //	Game.GraphicsDevice.SetupVertexInput(atmosVB, atmosIB);
            //	Game.GraphicsDevice.DrawIndexed(atmosIB.Capacity, 0, 0);
            //}


            //Draw airlines
            if (airLinesVB != null && Config.ShowAirLines)
            {
                constBuffer.Data.Temp = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
                constBuffer.UpdateCBuffer();

                Game.GraphicsDevice.VertexShaderConstants[1]   = dotsBuf;
                Game.GraphicsDevice.GeometryShaderConstants[0] = constBuffer;
                Game.GraphicsDevice.GeometryShaderConstants[1] = dotsBuf;

                Game.GraphicsDevice.PipelineState = myMiniFactory.ProducePipelineState(
                    GlobeFlags.DRAW_VERTEX_LINES | GlobeFlags.USE_GEOCOORDS | GlobeFlags.VERTEX_SHADER | GlobeFlags.DRAW_ARCS,
                    Primitive.LineList,
                    BlendState.Additive,
                    RasterizerState.CullNone,
                    DepthStencilState.Readonly);

                dev.SetupVertexInput(airLinesVB, null);
                dev.Draw(/*Primitive.LineList,*/ airLinesVB.Capacity, 0);
            }

            DrawDebugLines();

            //Game.GetService<DebugStrings>().Add("Cam pos     : " + Game.GetService<Camera>().CameraMatrix.TranslationVector, Color.Red);
            //Game.GetService<DebugStrings>().Add("Radius      : " + Config.earthRadius, Color.Red);
            //Game.GetService<DebugStrings>().Add("Level       : " + CurrentLevel, Color.Green);
            //Game.GetService<DebugStrings>().Add("CamDistance : " + Config.CameraDistance, Color.Green);
            //Game.GetService<DebugStrings>().Add("Pitch : " + Pitch, Color.Green);
            //Game.GetService<DebugStrings>().Add("Width : " + Game.GraphicsDevice.Viewport.Width, Color.Green);
            Game.GetService <DebugStrings>().Add("Height : " + (Config.CameraDistance - Config.earthRadius) * 1000.0, Color.Green);
        }
Пример #2
0
    public void Cut(Plane cutPlane, Vector3 vec)
    {
        //coliboolがfalseの時は何もしない
        if (coliBool == false)
        {
            return;
        }

        //いろいろ、Vector3は精度のためにdoubleで扱えるようにしたDVector3を使用↓にclassあり
        DVector3 p1, p2, p3;
        bool     p1Bool, p2Bool, p3Bool;
        var      uvs1          = new List <Vector2>();
        var      uvs2          = new List <Vector2>();
        var      vertices1     = new List <DVector3>();
        var      vertices2     = new List <DVector3>();
        var      triangles1    = new List <int>();
        var      triangles2    = new List <int>();
        var      normals1      = new List <Vector3>();
        var      normals2      = new List <Vector3>();
        var      crossVertices = new List <DVector3>();

        //カットしたいオブジェクトのメッシュをトライアングルごとに処理
        for (int i = 0; i < attachedMesh.triangles.Length; i += 3)
        {
            //メッシュの3つの頂点を取得
            p1 = new DVector3(transform.TransformPoint(attachedMesh.vertices[attachedMesh.triangles[i]]));
            p2 = new DVector3(transform.TransformPoint(attachedMesh.vertices[attachedMesh.triangles[i + 1]]));
            p3 = new DVector3(transform.TransformPoint(attachedMesh.vertices[attachedMesh.triangles[i + 2]]));

            //頂点がカットする面のどちら側にあるか
            p1Bool = DVector3.Dot(new DVector3(cutPlane.normal), p1) + (double)cutPlane.distance > 0 ? true : false;
            p2Bool = DVector3.Dot(new DVector3(cutPlane.normal), p2) + (double)cutPlane.distance > 0 ? true : false;
            p3Bool = DVector3.Dot(new DVector3(cutPlane.normal), p3) + (double)cutPlane.distance > 0 ? true : false;

            //3つの頂点が同じ側にある場合はそのまま代入、頂点がカットする場合はその処理を行う
            if (p1Bool && p2Bool && p3Bool)
            {
                //3つの頂点が同じ側にある、そのままそれぞれの1に代入
                for (int k = 0; k < 3; k++)
                {
                    vertices1.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + k]]));
                    uvs1.Add(attachedMesh.uv[attachedMesh.triangles[i + k]]);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + k]]);
                    triangles1.Add(vertices1.Count - 1);
                }
            }
            else if (!p1Bool && !p2Bool && !p3Bool)
            {
                //3つの頂点が同じ側にある、そのままそれぞれの2に代入
                for (int k = 0; k < 3; k++)
                {
                    vertices2.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + k]]));
                    uvs2.Add(attachedMesh.uv[attachedMesh.triangles[i + k]]);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + k]]);
                    triangles2.Add(vertices2.Count - 1);
                }
            }
            else
            {
                //3つの頂点が同じ側にない場合の処理1、以下仲間外れの頂点をp,それ以外をcとする
                DVector3 p, c1, c2;
                int      n1, n2, n3;
                if ((p1Bool && !p2Bool && !p3Bool) || (!p1Bool && p2Bool && p3Bool))
                {
                    p  = p1;
                    c1 = p2;
                    c2 = p3;
                    n1 = 0;
                    n2 = 1;
                    n3 = 2;
                }
                else if ((!p1Bool && p2Bool && !p3Bool) || (p1Bool && !p2Bool && p3Bool))
                {
                    p  = p2;
                    c1 = p3;
                    c2 = p1;
                    n1 = 1;
                    n2 = 2;
                    n3 = 0;
                }
                else
                {
                    p  = p3;
                    c1 = p1;
                    c2 = p2;
                    n1 = 2;
                    n2 = 0;
                    n3 = 1;
                }

                //カットした面に生じる新しい頂点を計算、カットする平面の法線方向に対するpとcの距離の比からc-pの長さを決める
                DVector3 cross1 = p + (c1 - p) * (((double)cutPlane.distance + DVector3.Dot(new DVector3(cutPlane.normal), p)) / DVector3.Dot(new DVector3(cutPlane.normal), p - c1));
                DVector3 cross2 = p + (c2 - p) * (((double)cutPlane.distance + DVector3.Dot(new DVector3(cutPlane.normal), p)) / DVector3.Dot(new DVector3(cutPlane.normal), p - c2));

                //新しい頂点のuvを計算、pとcの間で線形補間
                Vector2 cross1Uv = Vector2.Lerp(attachedMesh.uv[attachedMesh.triangles[i + n1]], attachedMesh.uv[attachedMesh.triangles[i + n2]], (float)System.Math.Sqrt((cross1 - p).sqrMagnitude / (p - c1).sqrMagnitude));
                Vector2 cross2Uv = Vector2.Lerp(attachedMesh.uv[attachedMesh.triangles[i + n1]], attachedMesh.uv[attachedMesh.triangles[i + n3]], (float)System.Math.Sqrt((cross2 - p).sqrMagnitude / (p - c2).sqrMagnitude));

                //本来はDVector3内でやりたいがよくわからないのでVector3のInverseTransfromPointを使用
                cross1 = new DVector3(transform.InverseTransformPoint(cross1.ToVector3()));
                cross2 = new DVector3(transform.InverseTransformPoint(cross2.ToVector3()));

                //断面をつくるために取っておく
                crossVertices.Add(cross1);
                crossVertices.Add(cross2);


                //pの2通りの処理、カットする面に対してどちらにあるかで異なる
                if ((p1Bool && !p2Bool && !p3Bool) || (!p1Bool && p2Bool && !p3Bool) || (!p1Bool && !p2Bool && p3Bool))
                {
                    //p側のメッシュを追加
                    vertices1.Add(cross1);
                    uvs1.Add(cross1Uv);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);
                    triangles1.Add(vertices1.Count - 1);

                    vertices1.Add(cross2);
                    uvs1.Add(cross2Uv);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);
                    triangles1.Add(vertices1.Count - 1);

                    vertices1.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + n1]]));
                    uvs1.Add(attachedMesh.uv[attachedMesh.triangles[i + n1]]);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);
                    triangles1.Add(vertices1.Count - 1);

                    //c側のメッシュを追加1
                    vertices2.Add(cross2);
                    uvs2.Add(cross2Uv);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);
                    triangles2.Add(vertices2.Count - 1);

                    vertices2.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + n2]]));
                    uvs2.Add(attachedMesh.uv[attachedMesh.triangles[i + n2]]);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n2]]);
                    triangles2.Add(vertices2.Count - 1);

                    vertices2.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + n3]]));
                    uvs2.Add(attachedMesh.uv[attachedMesh.triangles[i + n3]]);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n3]]);
                    triangles2.Add(vertices2.Count - 1);

                    //c側のメッシュを追加2
                    vertices2.Add(cross2);
                    uvs2.Add(cross2Uv);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);
                    triangles2.Add(vertices2.Count - 1);

                    vertices2.Add(cross1);
                    triangles2.Add(vertices2.Count - 1);
                    uvs2.Add(cross1Uv);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);

                    vertices2.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + n2]]));
                    uvs2.Add(attachedMesh.uv[attachedMesh.triangles[i + n2]]);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n2]]);
                    triangles2.Add(vertices2.Count - 1);
                }
                else
                {
                    //p側のメッシュを追加
                    vertices2.Add(cross1);
                    triangles2.Add(vertices2.Count - 1);
                    uvs2.Add(cross1Uv);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);

                    vertices2.Add(cross2);
                    triangles2.Add(vertices2.Count - 1);
                    uvs2.Add(cross2Uv);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);

                    vertices2.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + n1]]));
                    uvs2.Add(attachedMesh.uv[attachedMesh.triangles[i + n1]]);
                    normals2.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);
                    triangles2.Add(vertices2.Count - 1);

                    //c側のメッシュを追加1
                    vertices1.Add(cross2);
                    triangles1.Add(vertices1.Count - 1);
                    uvs1.Add(cross2Uv);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);

                    vertices1.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + n2]]));
                    uvs1.Add(attachedMesh.uv[attachedMesh.triangles[i + n2]]);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n2]]);
                    triangles1.Add(vertices1.Count - 1);

                    vertices1.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + n3]]));
                    uvs1.Add(attachedMesh.uv[attachedMesh.triangles[i + n3]]);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n3]]);
                    triangles1.Add(vertices1.Count - 1);

                    //c側のメッシュを追加2
                    vertices1.Add(cross2);
                    triangles1.Add(vertices1.Count - 1);
                    uvs1.Add(cross2Uv);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);

                    vertices1.Add(cross1);
                    triangles1.Add(vertices1.Count - 1);
                    uvs1.Add(cross1Uv);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n1]]);

                    vertices1.Add(new DVector3(attachedMesh.vertices[attachedMesh.triangles[i + n2]]));
                    uvs1.Add(attachedMesh.uv[attachedMesh.triangles[i + n2]]);
                    normals1.Add(attachedMesh.normals[attachedMesh.triangles[i + n2]]);
                    triangles1.Add(vertices1.Count - 1);
                }
            }
        }

        //meshを減らす処理を行う。(断面以外の処理)、↓に関数あり
        reduceMesh(ref vertices1, ref uvs1, ref normals1);
        //reduceMesh中でCutの中断を判断した場合にreturnする
        if (returnBool)
        {
            return;
        }
        reduceMesh(ref vertices2, ref uvs2, ref normals2);
        if (returnBool)
        {
            return;
        }


        //断面をつくる処理
        if (crossVertices.Count != 0)
        {
            //断面で頂点を減らす処理、直線状にある頂点を2つのみにする
            for (int i = 0; i < crossVertices.Count; i += 2)
            {
                for (int k = i + 2; k < crossVertices.Count; k += 2)
                {
                    //4つの頂点が一直線上にあるか、まず2つのベクトルが平行かどうか
                    if (System.Math.Abs(DVector3.Dot((crossVertices[i] - crossVertices[i + 1]).normalized, (crossVertices[k] - crossVertices[k + 1]).normalized)) > 1 - delta)
                    {
                        //同一の頂点を持つかどうか→一直線上にある
                        if ((crossVertices[i] - crossVertices[k]).sqrMagnitude < delta || (crossVertices[i] - crossVertices[k + 1]).sqrMagnitude < delta ||
                            (crossVertices[i + 1] - crossVertices[k]).sqrMagnitude < delta || (crossVertices[i + 1] - crossVertices[k + 1]).sqrMagnitude < delta)
                        {
                            //以下重なる点に応じた処理、両端を残して後を消去
                            if ((crossVertices[i] - crossVertices[k]).sqrMagnitude < (crossVertices[i + 1] - crossVertices[k]).sqrMagnitude)
                            {
                                crossVertices.Add(crossVertices[i + 1]);
                                if ((crossVertices[i] - crossVertices[k]).sqrMagnitude < (crossVertices[i] - crossVertices[k + 1]).sqrMagnitude)
                                {
                                    crossVertices.Add(crossVertices[k + 1]);
                                }
                                else
                                {
                                    crossVertices.Add(crossVertices[k]);
                                }
                                crossVertices.RemoveRange(k, 2);
                                crossVertices.RemoveRange(i, 2);
                            }
                            else
                            {
                                crossVertices.Add(crossVertices[i]);
                                if ((crossVertices[i + 1] - crossVertices[k]).sqrMagnitude < (crossVertices[i + 1] - crossVertices[k + 1]).sqrMagnitude)
                                {
                                    crossVertices.Add(crossVertices[k + 1]);
                                }
                                else
                                {
                                    crossVertices.Add(crossVertices[k]);
                                }
                                crossVertices.RemoveRange(k, 2);
                                crossVertices.RemoveRange(i, 2);
                            }
                            i -= 2;
                            break;
                        }
                    }
                }
            }

            //断面の三角形を作る処理

            //等しい点を消去
            for (int i = 0; i < crossVertices.Count; i++)
            {
                for (int j = i + 1; j < crossVertices.Count; j++)
                {
                    if ((crossVertices[i] - crossVertices[j]).sqrMagnitude < delta)
                    {
                        crossVertices.RemoveAt(j);
                        i--;
                        break;
                    }
                }
            }

            //外周の頂点を並び替え、crossVertices[0]と[1]を基準としてそれぞれの点を並び替える
            for (int i = 2; i < crossVertices.Count; i++)
            {
                for (int j = i + 1; j < crossVertices.Count; j++)
                {
                    if (System.Math.Acos(DVector3.Dot((crossVertices[0] - crossVertices[1]).normalized, (crossVertices[0] - crossVertices[i]).normalized)) >= System.Math.Acos(DVector3.Dot((crossVertices[0] - crossVertices[1]).normalized, (crossVertices[0] - crossVertices[j]).normalized)))
                    {
                        //角度が等しい、一直線上にある場合。本来はないはずだが・・・
                        if (System.Math.Acos(DVector3.Dot((crossVertices[0] - crossVertices[1]).normalized, (crossVertices[0] - crossVertices[i]).normalized)) == System.Math.Acos(DVector3.Dot((crossVertices[0] - crossVertices[1]).normalized, (crossVertices[0] - crossVertices[j]).normalized)))
                        {
                            //基準を変える
                            if ((crossVertices[0] - crossVertices[i]).sqrMagnitude > (crossVertices[0] - crossVertices[j]).sqrMagnitude)
                            {
                                crossVertices.Insert(0, crossVertices[j]);
                                crossVertices.RemoveAt(j + 1);
                            }
                            else
                            {
                                crossVertices.Insert(0, crossVertices[i]);
                                crossVertices.RemoveAt(i + 1);
                            }

                            i = 1;
                            break;
                        }
                        //並び替え
                        crossVertices.Insert(i, crossVertices[j]);
                        crossVertices.RemoveAt(j + 1);
                        i = 1;
                        break;
                    }
                }
            }



            for (int i = 1; i < crossVertices.Count - 1; i++)
            {
                //断面のnormalとuvの設定。uvを特別に設定する場合は変えてください
                for (int j = 0; j < 3; j++)
                {
                    normals1.Add(-cutPlane.normal);
                    uvs1.Add(new Vector2(0, 0));
                    normals2.Add(cutPlane.normal);
                    uvs2.Add(new Vector2(0, 0));
                }
                //断面の三角形を追加する 面の表の方向が正しくなるように判断して追加
                if (Vector3.Dot(transform.TransformDirection(DVector3.Cross((crossVertices[i] - crossVertices[0]).normalized, (crossVertices[i + 1] - crossVertices[i]).normalized).ToVector3()), cutPlane.normal) < delta)
                {
                    vertices1.Add(crossVertices[0]);
                    vertices1.Add(crossVertices[i]);
                    vertices1.Add(crossVertices[i + 1]);

                    vertices2.Add(crossVertices[i]);
                    vertices2.Add(crossVertices[0]);
                    vertices2.Add(crossVertices[i + 1]);
                }
                else
                {
                    vertices1.Add(crossVertices[i]);
                    vertices1.Add(crossVertices[0]);
                    vertices1.Add(crossVertices[i + 1]);

                    vertices2.Add(crossVertices[0]);
                    vertices2.Add(crossVertices[i]);
                    vertices2.Add(crossVertices[i + 1]);
                }
            }
        }
        //ひとつのtriangleについてそれぞれ3つずつの頂点を作っているため最後に順番通りにいれる
        triangles1.Clear();
        for (int i = 0; i < vertices1.Count; i++)
        {
            triangles1.Add(i);
        }
        triangles2.Clear();
        for (int i = 0; i < vertices2.Count; i++)
        {
            triangles2.Add(i);
        }

        //DVector3を通常のVector3に直す、もっと賢いやりかたがありそう
        var list1 = new List <Vector3>();

        for (int i = 0; i < vertices1.Count; i++)
        {
            list1.Add(vertices1[i].ToVector3());
        }
        var list2 = new List <Vector3>();

        for (int i = 0; i < vertices2.Count; i++)
        {
            list2.Add(vertices2[i].ToVector3());
        }


        //カット後のオブジェクト生成、いろいろといれる
        GameObject obj  = new GameObject("cut obj", typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider), typeof(Rigidbody), typeof(MeshCut));
        var        mesh = new Mesh();

        mesh.vertices  = list1.ToArray();
        mesh.triangles = triangles1.ToArray();
        mesh.uv        = uvs1.ToArray();
        mesh.normals   = normals1.ToArray();
        obj.GetComponent <MeshFilter>().mesh          = mesh;
        obj.GetComponent <MeshRenderer>().materials   = GetComponent <MeshRenderer>().materials;
        obj.GetComponent <MeshCollider>().sharedMesh  = mesh;
        obj.GetComponent <MeshCollider>().inflateMesh = true;
        obj.GetComponent <MeshCollider>().skinWidth   = skinWidth;
        obj.GetComponent <MeshCollider>().convex      = true;
        obj.GetComponent <MeshCollider>().material    = GetComponent <Collider>().material;
        obj.transform.position   = transform.position;
        obj.transform.rotation   = transform.rotation;
        obj.transform.localScale = transform.localScale;
        obj.GetComponent <Rigidbody>().velocity        = GetComponent <Rigidbody>().velocity + vec / 2 + cutPlane.normal * 2;
        obj.GetComponent <Rigidbody>().angularVelocity = GetComponent <Rigidbody>().angularVelocity;
        obj.GetComponent <MeshCut>().skinWidth         = skinWidth;
        //obj.GetComponent<Collider>().enabled = false;
        Destroy(obj, 1f);

        GameObject obj2  = new GameObject("cut obj", typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider), typeof(Rigidbody), typeof(MeshCut));
        var        mesh2 = new Mesh();

        mesh2.vertices  = list2.ToArray();
        mesh2.triangles = triangles2.ToArray();
        mesh2.uv        = uvs2.ToArray();
        mesh2.normals   = normals2.ToArray();
        obj2.GetComponent <MeshFilter>().mesh          = mesh2;
        obj2.GetComponent <MeshRenderer>().materials   = GetComponent <MeshRenderer>().materials;
        obj2.GetComponent <MeshCollider>().sharedMesh  = mesh2;
        obj2.GetComponent <MeshCollider>().inflateMesh = true;
        obj2.GetComponent <MeshCollider>().skinWidth   = skinWidth;
        obj2.GetComponent <MeshCollider>().convex      = true;
        obj2.GetComponent <MeshCollider>().material    = GetComponent <Collider>().material;
        obj2.transform.position   = transform.position;
        obj2.transform.rotation   = transform.rotation;
        obj2.transform.localScale = transform.localScale;
        obj2.GetComponent <Rigidbody>().velocity        = GetComponent <Rigidbody>().velocity + vec / 2 - cutPlane.normal * 2;
        obj2.GetComponent <Rigidbody>().angularVelocity = GetComponent <Rigidbody>().angularVelocity;
        obj2.GetComponent <MeshCut>().skinWidth         = skinWidth;
        //obj2.GetComponent<Collider>().enabled = false;
        Destroy(obj2, 1f);

        //このオブジェクトをデストロイ
        Destroy(gameObject);
    }
Пример #3
0
    void reduceMesh(ref List <DVector3> vertices, ref List <Vector2> uvs, ref List <Vector3> normals)
    {
        var verticeIndices = new List <int>();
        var pVertices      = new List <DVector3>();
        var pNormals       = new List <Vector3>();
        var pUvs           = new List <Vector2>();

        for (int i = 0; i < vertices.Count; i += 3)
        {
            //まずは同一平面状にある三角形を見つけ出すが、基準となるiをとりあえず追加
            verticeIndices.Clear();
            verticeIndices.Add(i);

            for (int j = i + 3; j < vertices.Count; j += 3)
            {
                //同一の平面上にある三角形かどうか。deltaで調整
                if (DVector3.Dot(DVector3.Cross((vertices[i + 1] - vertices[i]).normalized, (vertices[i + 2] - vertices[i + 1]).normalized).normalized,
                                 DVector3.Cross((vertices[j + 1] - vertices[j]).normalized, (vertices[j + 2] - vertices[j + 1]).normalized).normalized) > 1 - delta)
                {
                    verticeIndices.Add(j);
                }

                //全ての三角形について計算してループの最後に行う処理
                if (j == vertices.Count - 3)
                {
                    //三角形が1つの場合は何もする必要なし
                    if (verticeIndices.Count > 1)
                    {
                        //平面上の三角形が2つ以上ある場合
                        //pの入れ物に三角形を3つの直線にしていれる
                        for (int k = 0; k < verticeIndices.Count; k++)
                        {
                            for (int l = 0; l < 3; l++)
                            {
                                pVertices.Add(vertices[verticeIndices[k] + l]);
                                pNormals.Add(normals[verticeIndices[k] + l]);
                                pUvs.Add(uvs[verticeIndices[k] + l]);

                                pVertices.Add(vertices[verticeIndices[k] + numRep(l + 1)]);
                                pNormals.Add(normals[verticeIndices[k] + numRep(l + 1)]);
                                pUvs.Add(uvs[verticeIndices[k] + numRep(l + 1)]);
                            }
                        }



                        //等しい直線を消す(面の外周でない線を消す)
                        int sameLineCount = 0;
                        for (int k = 0; k < pVertices.Count; k += 2)
                        {
                            for (int l = k + 2; l < pVertices.Count; l += 2)
                            {
                                if (((pVertices[l + 1] - pVertices[k]).sqrMagnitude < delta) && ((pVertices[l] - pVertices[k + 1]).sqrMagnitude < delta))
                                {
                                    sameLineCount++;
                                    pVertices.RemoveRange(l, 2);
                                    pVertices.RemoveRange(k, 2);
                                    pNormals.RemoveRange(l, 2);
                                    pNormals.RemoveRange(k, 2);
                                    pUvs.RemoveRange(l, 2);
                                    pUvs.RemoveRange(k, 2);
                                    k -= 2;

                                    break;
                                }
                            }
                        }
                        //同一平面上のn個の隣接する三角形にはn-1個の等しい直線があるはずが、ない場合(ここまでの処理がうまくいっていない場合)は処理をやめる
                        //ここらへんは検討中 → 新しい処理追加
                        if (sameLineCount != verticeIndices.Count - 1)
                        {
                            //同一平面上にあるが三角形が隣接していない場合(本来同一平面上と判定されるはずの三角形が
                            //同一平面上と判定されなかった(切断面の頂点を求める際にある2点がほぼ同じ値を取ってしまった場合))
                            //にcutPlaneをちょっとずらしてもう一度計算させる。

                            //一度だけ処理させるように以下の分岐でゴニョゴニョ
                            if (returnBool2)
                            {
                                returnBool  = true;
                                returnBool3 = true;
                                return;
                            }
                            returnBool2 = true;
                            //ずらす量は暫定的
                            //Cut(new Plane(cutPlane.normal, -cutPlane.normal * cutPlane.distance + new Vector3(0.02f, 0.02f, 0.02f)));
                            if (returnBool3)
                            {
                                returnBool  = false;
                                returnBool2 = false;
                            }
                            else
                            {
                                returnBool = true;
                            }
                            return;
                        }

                        for (int l = 0; l < pVertices.Count; l += 2)
                        {
                            for (int k = l + 2; k < pVertices.Count; k += 2)
                            {
                                //4つの頂点が一直線上にあるか、2つのベクトルが平行かどうか
                                if (System.Math.Abs(DVector3.Dot((pVertices[l] - pVertices[l + 1]).normalized, (pVertices[k] - pVertices[k + 1]).normalized)) > 1 - delta)
                                {
                                    //同一の点を持つ→一直線上にある
                                    if ((pVertices[l] - pVertices[k]).sqrMagnitude < delta || (pVertices[l] - pVertices[k + 1]).sqrMagnitude < delta ||
                                        (pVertices[l + 1] - pVertices[k]).sqrMagnitude < delta || (pVertices[l + 1] - pVertices[k + 1]).sqrMagnitude < delta)
                                    {
                                        //以下重なる点に応じた処理、両端を残して後を消去
                                        if ((pVertices[l] - pVertices[k]).sqrMagnitude < (pVertices[l + 1] - pVertices[k]).sqrMagnitude)
                                        {
                                            pVertices.Add(pVertices[l + 1]);
                                            pNormals.Add(pNormals[l + 1]);
                                            pUvs.Add(pUvs[l + 1]);

                                            if ((pVertices[l] - pVertices[k]).sqrMagnitude < (pVertices[l] - pVertices[k + 1]).sqrMagnitude)
                                            {
                                                pVertices.Add(pVertices[k + 1]);
                                                pNormals.Add(pNormals[k + 1]);
                                                pUvs.Add(pUvs[k + 1]);
                                            }
                                            else
                                            {
                                                pVertices.Add(pVertices[k]);
                                                pNormals.Add(pNormals[k]);
                                                pUvs.Add(pUvs[k]);
                                            }
                                            pVertices.RemoveRange(k, 2);
                                            pVertices.RemoveRange(l, 2);
                                            pNormals.RemoveRange(k, 2);
                                            pNormals.RemoveRange(l, 2);
                                            pUvs.RemoveRange(k, 2);
                                            pUvs.RemoveRange(l, 2);
                                        }
                                        else
                                        {
                                            pVertices.Add(pVertices[l]);
                                            pNormals.Add(pNormals[l]);
                                            pUvs.Add(pUvs[l]);
                                            if ((pVertices[l + 1] - pVertices[k]).sqrMagnitude < (pVertices[l + 1] - pVertices[k + 1]).sqrMagnitude)
                                            {
                                                pVertices.Add(pVertices[k + 1]);
                                                pNormals.Add(pNormals[k + 1]);
                                                pUvs.Add(pUvs[k + 1]);
                                            }
                                            else
                                            {
                                                pVertices.Add(pVertices[k]);
                                                pNormals.Add(pNormals[k]);
                                                pUvs.Add(pUvs[k]);
                                            }
                                            pVertices.RemoveRange(k, 2);
                                            pVertices.RemoveRange(l, 2);
                                            pNormals.RemoveRange(k, 2);
                                            pNormals.RemoveRange(l, 2);
                                            pUvs.RemoveRange(k, 2);
                                            pUvs.RemoveRange(l, 2);
                                        }

                                        l -= 2;
                                        break;
                                    }
                                }
                            }
                        }


                        //等しい点を消す
                        for (int k = 0; k < pVertices.Count; k++)
                        {
                            for (int l = k + 1; l < pVertices.Count; l++)
                            {
                                if ((pVertices[k] - pVertices[l]).sqrMagnitude < delta)
                                {
                                    pVertices.RemoveAt(l);
                                    pNormals.RemoveAt(l);
                                    pUvs.RemoveAt(l);
                                }
                            }
                        }

                        //外周上の点を順番に並び替える.pVertices[0],[1]を基準として並び替え
                        for (int k = 2; k < pVertices.Count; k++)
                        {
                            for (int l = k + 1; l < pVertices.Count; l++)
                            {
                                if (System.Math.Acos(DVector3.Dot((pVertices[0] - pVertices[1]).normalized, (pVertices[0] - pVertices[k]).normalized)) >= System.Math.Acos(DVector3.Dot((pVertices[0] - pVertices[1]).normalized, (pVertices[0] - pVertices[l]).normalized)))
                                {
                                    //等しくなってしまう場合
                                    if (System.Math.Acos(DVector3.Dot((pVertices[0] - pVertices[1]).normalized, (pVertices[0] - pVertices[k]).normalized)) == System.Math.Acos(DVector3.Dot((pVertices[0] - pVertices[1]).normalized, (pVertices[0] - pVertices[l]).normalized)))
                                    {
                                        if ((pVertices[0] - pVertices[k]).sqrMagnitude > (pVertices[0] - pVertices[l]).sqrMagnitude)
                                        {
                                            pVertices.Insert(0, pVertices[l]);
                                            pVertices.RemoveAt(l + 1);
                                            pNormals.Insert(0, pNormals[l]);
                                            pNormals.RemoveAt(l + 1);
                                            pUvs.Insert(0, pUvs[l]);
                                            pUvs.RemoveAt(l + 1);
                                        }
                                        else
                                        {
                                            pVertices.Insert(0, pVertices[k]);
                                            pVertices.RemoveAt(k + 1);
                                            pNormals.Insert(0, pNormals[k]);
                                            pNormals.RemoveAt(k + 1);
                                            pUvs.Insert(0, pUvs[k]);
                                            pUvs.RemoveAt(k + 1);
                                        }
                                        k = 1;
                                        break;
                                    }
                                    //並び替え
                                    pVertices.Insert(k, pVertices[l]);
                                    pVertices.RemoveAt(l + 1);
                                    pNormals.Insert(k, pNormals[l]);
                                    pNormals.RemoveAt(l + 1);
                                    pUvs.Insert(k, pUvs[l]);
                                    pUvs.RemoveAt(l + 1);
                                    k = 1;
                                    break;
                                }
                            }
                        }


                        //外周上の並び替えられた頂点を全て三角形で結ぶように追加
                        for (int k = 1; k < pVertices.Count - 1; k++)
                        {
                            vertices.Insert(0, pVertices[k + 1]);
                            normals.Insert(0, pNormals[k + 1]);
                            uvs.Insert(0, pUvs[k + 1]);

                            vertices.Insert(0, pVertices[k]);
                            normals.Insert(0, pNormals[k]);
                            uvs.Insert(0, pUvs[k]);

                            vertices.Insert(0, pVertices[0]);
                            normals.Insert(0, pNormals[0]);
                            uvs.Insert(0, pUvs[0]);
                        }

                        //追加したので古いのを消去
                        for (int k = verticeIndices.Count - 1; k >= 0; k--)
                        {
                            vertices.RemoveRange(verticeIndices[k] + 3 * (pVertices.Count - 2), 3);
                            normals.RemoveRange(verticeIndices[k] + 3 * (pVertices.Count - 2), 3);
                            uvs.RemoveRange(verticeIndices[k] + 3 * (pVertices.Count - 2), 3);
                        }
                        //処理した三角形を考慮してループの位置を調整
                        i += 3 * (pVertices.Count - 3);
                        //初期化しておく
                        pVertices.Clear();
                        pNormals.Clear();
                        pUvs.Clear();

                        break;
                    }
                }
            }
        }
    }
Пример #4
0
        void CreateRoadFromLine(RailroadPoint[] line, double width, out VertexBuffer vb, out IndexBuffer ib)
        {
            if (line.Length == 0)
            {
                vb = null;
                ib = null;
                return;
            }

            float distMul = 4.0f;

            List <GeoVert> vertices = new List <GeoVert>();
            List <int>     indeces  = new List <int>();

            for (int i = 0; i < line.Length - 1; i++)
            {
                var p0 = line[i];
                var p1 = line[i + 1];

                var cPos0 = SphericalToCartesian(new DVector2(p0.LonLat.X * (Math.PI / 180.0), p0.LonLat.Y * (Math.PI / 180.0)), Config.earthRadius);
                var cPos1 = SphericalToCartesian(new DVector2(p1.LonLat.X * (Math.PI / 180.0), p1.LonLat.Y * (Math.PI / 180.0)), Config.earthRadius);

                var normal = cPos0;
                normal.Normalize();

                DVector3 dir = cPos1 - cPos0;

                DVector3 sideVec = DVector3.Cross(normal, dir);
                sideVec.Normalize();

                DVector3 sideOffset = sideVec * width;


                // Plane
                var finalPosRight = cPos0 + sideOffset;
                var finalPosLeft  = cPos0 - sideOffset;

                var lonLatRight = CartesianToSpherical(finalPosRight);
                var lonLatLeft  = CartesianToSpherical(finalPosLeft);

                vertices.Add(new GeoVert {
                    Lon      = lonLatRight.X,
                    Lat      = lonLatRight.Y,
                    Color    = Color.Yellow,
                    Tex      = new Vector4((float)p0.Distance * distMul, 0.0f, 0.0f, 0.0f),
                    Position = Vector3.Zero
                });

                vertices.Add(new GeoVert {
                    Lon      = lonLatLeft.X,
                    Lat      = lonLatLeft.Y,
                    Color    = Color.Yellow,
                    Tex      = new Vector4((float)p0.Distance * distMul, 1.0f, 0.0f, 0.0f),
                    Position = Vector3.Zero
                });

                indeces.Add(i * 2);
                indeces.Add(i * 2 + 1);
                indeces.Add((i + 1) * 2);

                indeces.Add(i * 2 + 1);
                indeces.Add((i + 1) * 2 + 1);
                indeces.Add((i + 1) * 2);
            }

            {
                var p0 = line[line.Length - 1];
                var p1 = line[line.Length - 2];

                var cPos0 = SphericalToCartesian(new DVector2(p0.LonLat.X * (Math.PI / 180.0), p0.LonLat.Y * (Math.PI / 180.0)), Config.earthRadius);
                var cPos1 = SphericalToCartesian(new DVector2(p1.LonLat.X * (Math.PI / 180.0), p1.LonLat.Y * (Math.PI / 180.0)), Config.earthRadius);

                var normal = cPos0;
                normal.Normalize();

                DVector3 dir = cPos1 - cPos0;

                DVector3 sideVec = DVector3.Cross(normal, -dir);
                sideVec.Normalize();

                DVector3 sideOffset = sideVec * width;


                // Plane
                var finalPosRight = cPos0 + sideOffset;
                var finalPosLeft  = cPos0 - sideOffset;

                var lonLatRight = CartesianToSpherical(finalPosRight);
                var lonLatLeft  = CartesianToSpherical(finalPosLeft);

                vertices.Add(new GeoVert
                {
                    Lon      = lonLatRight.X,
                    Lat      = lonLatRight.Y,
                    Color    = Color.Yellow,
                    Tex      = new Vector4((float)p0.Distance * distMul, 0.0f, 0.0f, 0.0f),
                    Position = Vector3.Zero
                });

                vertices.Add(new GeoVert
                {
                    Lon      = lonLatLeft.X,
                    Lat      = lonLatLeft.Y,
                    Color    = Color.Yellow,
                    Tex      = new Vector4((float)p0.Distance * distMul, 1.0f, 0.0f, 0.0f),
                    Position = Vector3.Zero
                });
            }


            vb = new VertexBuffer(Game.GraphicsDevice, typeof(GeoVert), vertices.Count);
            vb.SetData(vertices.ToArray(), 0, vertices.Count);

            ib = new IndexBuffer(Game.GraphicsDevice, indeces.Count);
            ib.SetData(indeces.ToArray(), 0, indeces.Count);
        }