コード例 #1
0
        /// <summary>
        /// ペイント処理を行う
        /// CanvasにはMeshColliderが設定されている必要があります
        /// </summary>
        /// <param name="brush">ブラシ</param>
        /// <param name="hitInfo">RaycastのHit情報</param>
        /// <returns>ペイントの成否</returns>
        public bool Paint(PaintBrush brush, RaycastHit hitInfo)
        {
            if (hitInfo.collider != null && hitInfo.collider.gameObject == gameObject)
            {
                #region ErrorCheck

                if (brush == null)
                {
                    Debug.LogError("ブラシが設定されていません");
                    return(false);
                }

                #endregion ErrorCheck

                //MeshColliderが設定されていない場合はヒット位置でペイントを行う
                if (!(GetComponent <Collider>() is MeshCollider))
                {
                    Debug.LogWarning("MeshColliderが設定されていないキャンバスにRayCastを利用したPaintを行うと予期せぬ動作をする場合があります");
                    //頂点のTriangleから一番近いサーフェス上の点を算出してPaintに渡すように
                    return(PaintNearestTriangleSurface(brush, hitInfo.point));
                }
                return(PaintUVDirect(brush, hitInfo.textureCoord));
            }
            return(false);
        }
コード例 #2
0
        /// <summary>
        /// 与えられたworldPosに近いMeshSurface上の点に対してペイント処理を行う
        /// </summary>
        /// <param name="brush">ブラシ</param>
        /// <param name="worldPos">近似点</param>
        /// <param name="renderCamera">レンダリングに利用するカメラ</param>
        /// <returns></returns>
        public bool PaintNearestTriangleSurface(PaintBrush brush, Vector3 worldPos, Camera renderCamera = null)
        {
            var p = transform.worldToLocalMatrix.MultiplyPoint(worldPos);

            //頂点の中で一番近いものを含む三角形を取得
            var tris = Utility.Math.GetNearestVerticesTriangle(p, meshVertices, meshTriangles);

            //それぞれの三角形空間でそれっぽいp'を計算
            var pds = new List <Vector3>();

            for (int i = 0; i < tris.Length; i += 3)
            {
                var i0 = i;
                var i1 = i + 1;
                var i2 = i + 2;
                pds.Add(Utility.Math.TriangleSpaceProjection(p, tris[i0], tris[i1], tris[i2]));
            }

            //HACK:p'が三角形内部にない場合は一番近い頂点位置をp'に設定した方がいい?

            //pに一番近いp'が求めたかったオブジェクト表面
            var pd = pds.OrderBy(t => Vector3.Distance(p, t)).First();

            return(Paint(brush, transform.localToWorldMatrix.MultiplyPoint(pd), renderCamera));
        }
コード例 #3
0
        /// <summary>
        /// Paint of points close to the given world-space position on the Mesh surface.
        /// </summary>
        /// <param name="brush">Brush data.</param>
        /// <param name="worldPos">Approximate point.</param>
        /// <param name="renderCamera">Camera to use to render the object.</param>
        /// <returns>The success or failure of the paint.</returns>
        public bool PaintNearestTriangleSurface(PaintBrush brush, Vector3 worldPos, Camera renderCamera = null)
        {
            var p  = transform.worldToLocalMatrix.MultiplyPoint(worldPos);
            var pd = MeshOperator.NearestLocalSurfacePoint(p);

            return(Paint(brush, transform.localToWorldMatrix.MultiplyPoint(pd), renderCamera));
        }
コード例 #4
0
        /// <summary>
        /// 直接UV座標を指定したペイント処理を行う
        /// </summary>
        /// <param name="brush">ブラシ</param>
        /// <param name="uv">ヒット位置のUV座標</param>
        /// <returns>ペイントの成否</returns>
        public bool PaintUVDirect(PaintBrush brush, Vector2 uv)
        {
            foreach (var p in paintSet)
            {
                //メインテクスチャへのペイント
                if (p.useMainPaint && brush.BrushTexture != null && p.paintMainTexture != null && p.paintMainTexture.IsCreated())
                {
                    var mainPaintTextureBuffer = RenderTexture.GetTemporary(p.mainTexture.width, p.mainTexture.height);
                    SetPaintMainData(brush, uv);
                    Graphics.Blit(p.paintMainTexture, mainPaintTextureBuffer, paintMaterial);
                    Graphics.Blit(mainPaintTextureBuffer, p.paintMainTexture);
                    RenderTexture.ReleaseTemporary(mainPaintTextureBuffer);
                }

                //法線マップへのペイント
                if (p.useNormalPaint && brush.BrushNormalTexture != null && p.paintNormalTexture != null && p.paintNormalTexture.IsCreated())
                {
                    var normalPaintTextureBuffer = RenderTexture.GetTemporary(p.normalTexture.width, p.normalTexture.height);
                    SetPaintNormalData(brush, uv);
                    Graphics.Blit(p.paintNormalTexture, normalPaintTextureBuffer, paintNormalMaterial);
                    Graphics.Blit(normalPaintTextureBuffer, p.paintNormalTexture);
                    RenderTexture.ReleaseTemporary(normalPaintTextureBuffer);
                }
                //ハイトマップへのペイント
                if (p.useHeightPaint && brush.BrushHeightTexture != null && p.paintHeightTexture != null && p.paintHeightTexture.IsCreated())
                {
                    var heightPaintTextureBuffer = RenderTexture.GetTemporary(p.heightTexture.width, p.heightTexture.height);
                    SetPaintHeightData(brush, uv);
                    Graphics.Blit(p.paintHeightTexture, heightPaintTextureBuffer, paintHeightMaterial);
                    Graphics.Blit(heightPaintTextureBuffer, p.paintHeightTexture);
                    RenderTexture.ReleaseTemporary(heightPaintTextureBuffer);
                }
            }
            return(true);
        }
コード例 #5
0
        /// <summary>
        /// ペイントに必要なデータをシェーダーにセットする
        /// </summary>
        /// <param name="brush">ブラシ</param>
        /// <param name="uv">ヒット位置のUV座標</param>
        private void SetPaintMainData(PaintBrush brush, Vector2 uv)
        {
            paintMaterial.SetVector(paintUVPropertyID, uv);
            paintMaterial.SetTexture(brushTexturePropertyID, brush.BrushTexture);
            paintMaterial.SetFloat(brushScalePropertyID, brush.Scale);
            paintMaterial.SetVector(brushColorPropertyID, brush.Color);

            foreach (var key in paintMaterial.shaderKeywords)
            {
                paintMaterial.DisableKeyword(key);
            }
            switch (brush.ColorBlending)
            {
            case PaintBrush.ColorBlendType.UseColor:
                paintMaterial.EnableKeyword(COLOR_BLEND_USE_CONTROL);
                break;

            case PaintBrush.ColorBlendType.UseBrush:
                paintMaterial.EnableKeyword(COLOR_BLEND_USE_BRUSH);
                break;

            case PaintBrush.ColorBlendType.Neutral:
                paintMaterial.EnableKeyword(COLOR_BLEND_NEUTRAL);
                break;

            default:
                paintMaterial.EnableKeyword(COLOR_BLEND_USE_CONTROL);
                break;
            }
        }
コード例 #6
0
 /// <summary>
 /// Paint processing that use raycast hit data.
 /// Must MeshCollider is set to the canvas.
 /// </summary>
 /// <param name="brush">Brush data.</param>
 /// <param name="hitInfo">Raycast hit info.</param>
 /// <returns>The success or failure of the paint.</returns>
 public bool Paint(PaintBrush brush, RaycastHit hitInfo)
 {
     if (hitInfo.collider != null && hitInfo.collider.gameObject == gameObject)
     {
         if (!(GetComponent <Collider>() is MeshCollider))
         {
             Debug.LogWarning("If you want to paint using a Raycast, need set MeshCollider for canvas object.");
             return(PaintNearestTriangleSurface(brush, hitInfo.point));
         }
         return(PaintUVDirect(brush, hitInfo.textureCoord));
     }
     return(false);
 }
コード例 #7
0
        /// <summary>
        /// ペイント処理を行う
        /// </summary>
        /// <param name="brush">ブラシ</param>
        /// <param name="worldPos">
        /// キャンバス上の塗る点(World-Space)
        /// メッシュが構成する形状のサーフェスの上の点
        /// </param>
        /// <param name="renderCamera">レンダリングに利用するカメラ</param>
        /// <returns>ペイント成否</returns>
        public bool Paint(PaintBrush brush, Vector3 worldPos, Camera renderCamera = null)
        {
            if (renderCamera == null)
            {
                renderCamera = Camera.main;
            }

            int     index0;
            int     index1;
            int     index2;
            Vector3 t1;
            Vector3 t2;
            Vector3 t3;
            Vector3 p = transform.InverseTransformPoint(worldPos);

            for (var i = 0; i < meshTriangles.Length; i += 3)
            {
                index0 = i + 0;
                index1 = i + 1;
                index2 = i + 2;

                t1 = meshVertices[meshTriangles[index0]];
                t2 = meshVertices[meshTriangles[index1]];
                t3 = meshVertices[meshTriangles[index2]];

                //平面上に存在しない
                if (!Utility.Math.ExistPointInPlane(p, t1, t2, t3))
                {
                    continue;
                }
                //三角形の辺または内部に存在しない
                if (!Utility.Math.ExistPointOnTriangleEdge(p, t1, t2, t3) && !Utility.Math.ExistPointInTriangle(p, t1, t2, t3))
                {
                    continue;
                }

                //UV座標算出
                var       uv1 = meshUV[meshTriangles[index0]];
                var       uv2 = meshUV[meshTriangles[index1]];
                var       uv3 = meshUV[meshTriangles[index2]];
                Matrix4x4 mvp = renderCamera.projectionMatrix * renderCamera.worldToCameraMatrix * transform.localToWorldMatrix;
                var       uv  = Utility.Math.TextureCoordinateCalculation(p, t1, uv1, t2, uv2, t3, uv3, mvp);

                return(PaintUVDirect(brush, uv));
            }
            return(false);
        }
コード例 #8
0
        /// <summary>
        /// To set the data needed to height map paint shader.
        /// </summary>
        /// <param name="brush">Brush data.</param>
        /// <param name="uv">UV coordinates for the hit location.</param>
        private void SetPaintHeightData(PaintBrush brush, Vector2 uv)
        {
            paintHeightMaterial.SetVector(paintUVPropertyID, uv);
            paintHeightMaterial.SetTexture(brushTexturePropertyID, brush.BrushTexture);
            paintHeightMaterial.SetTexture(brushHeightTexturePropertyID, brush.BrushHeightTexture);
            paintHeightMaterial.SetFloat(brushScalePropertyID, brush.Scale);
            paintHeightMaterial.SetFloat(brushHeightBlendPropertyID, brush.HeightBlend);
            paintHeightMaterial.SetVector(brushHeightColorPropertyID, brush.Color);

            foreach (var key in paintHeightMaterial.shaderKeywords)
            {
                paintHeightMaterial.DisableKeyword(key);
            }
            switch (brush.HeightBlending)
            {
            case PaintBrush.HeightBlendType.UseBrush:
                paintHeightMaterial.EnableKeyword(HEIGHT_BLEND_USE_BRUSH);
                break;

            case PaintBrush.HeightBlendType.Add:
                paintHeightMaterial.EnableKeyword(HEIGHT_BLEND_ADD);
                break;

            case PaintBrush.HeightBlendType.Sub:
                paintHeightMaterial.EnableKeyword(HEIGHT_BLEND_SUB);
                break;

            case PaintBrush.HeightBlendType.Min:
                paintHeightMaterial.EnableKeyword(HEIGHT_BLEND_MIN);
                break;

            case PaintBrush.HeightBlendType.Max:
                paintHeightMaterial.EnableKeyword(HEIGHT_BLEND_MAX);
                break;

            case PaintBrush.HeightBlendType.ColorRGB_HeightA:
                paintHeightMaterial.EnableKeyword(HEIGHT_BLEND_COLOR_RGB_HEIGHT_A);
                break;

            default:
                paintHeightMaterial.EnableKeyword(HEIGHT_BLEND_ADD);
                break;
            }
        }
コード例 #9
0
        /// <summary>
        /// Paint processing that UV coordinates to the specified.
        /// </summary>
        /// <param name="brush">Brush data.</param>
        /// <param name="uv">UV coordinates for the hit location.</param>
        /// <returns>The success or failure of the paint.</returns>
        public bool PaintUVDirect(PaintBrush brush, Vector2 uv)
        {
            #region ErrorCheck

            if (brush == null)
            {
                Debug.LogError("Do not set the brush.");
                return(false);
            }

            #endregion ErrorCheck

            foreach (var p in paintSet)
            {
                if (p.useMainPaint && brush.BrushTexture != null && p.paintMainTexture != null && p.paintMainTexture.IsCreated())
                {
                    var mainPaintTextureBuffer = RenderTexture.GetTemporary(p.paintMainTexture.width, p.paintMainTexture.height);
                    SetPaintMainData(brush, uv);
                    Graphics.Blit(p.paintMainTexture, mainPaintTextureBuffer, paintMaterial);
                    Graphics.Blit(mainPaintTextureBuffer, p.paintMainTexture);
                    RenderTexture.ReleaseTemporary(mainPaintTextureBuffer);
                }

                if (p.useNormalPaint && brush.BrushNormalTexture != null && p.paintNormalTexture != null && p.paintNormalTexture.IsCreated())
                {
                    var normalPaintTextureBuffer = RenderTexture.GetTemporary(p.paintNormalTexture.width, p.paintNormalTexture.height);
                    SetPaintNormalData(brush, uv);
                    Graphics.Blit(p.paintNormalTexture, normalPaintTextureBuffer, paintNormalMaterial);
                    Graphics.Blit(normalPaintTextureBuffer, p.paintNormalTexture);
                    RenderTexture.ReleaseTemporary(normalPaintTextureBuffer);
                }

                if (p.useHeightPaint && brush.BrushHeightTexture != null && p.paintHeightTexture != null && p.paintHeightTexture.IsCreated())
                {
                    var heightPaintTextureBuffer = RenderTexture.GetTemporary(p.paintHeightTexture.width, p.paintHeightTexture.height);
                    SetPaintHeightData(brush, uv);
                    Graphics.Blit(p.paintHeightTexture, heightPaintTextureBuffer, paintHeightMaterial);
                    Graphics.Blit(heightPaintTextureBuffer, p.paintHeightTexture);
                    RenderTexture.ReleaseTemporary(heightPaintTextureBuffer);
                }
            }
            return(true);
        }
コード例 #10
0
        /// <summary>
        /// ペイント処理を行う
        /// </summary>
        /// <param name="brush">ブラシ</param>
        /// <param name="worldPos">
        /// キャンバス上の塗る点(World-Space)
        /// メッシュが構成する形状のサーフェスの上の点
        /// </param>
        /// <param name="renderCamera">レンダリングに利用するカメラ</param>
        /// <returns>ペイント成否</returns>
        public bool Paint(PaintBrush brush, Vector3 worldPos, Camera renderCamera = null)
        {
            Vector2 uv;

            if (renderCamera == null)
            {
                renderCamera = Camera.main;
            }

            Vector3   p   = transform.InverseTransformPoint(worldPos);
            Matrix4x4 mvp = renderCamera.projectionMatrix * renderCamera.worldToCameraMatrix * transform.localToWorldMatrix;

            if (meshOperator.LocalPointToUV(p, mvp, out uv))
            {
                return(PaintUVDirect(brush, uv));
            }

            return(false);
        }
コード例 #11
0
        /// <summary>
        /// 法線マップペイントに必要なデータをシェーダーにセットする
        /// </summary>
        /// <param name="brush">ブラシ</param>
        /// <param name="uv">ヒット位置のUV座標</param>
        private void SetPaintNormalData(PaintBrush brush, Vector2 uv)
        {
            paintNormalMaterial.SetVector(paintUVPropertyID, uv);
            paintNormalMaterial.SetTexture(brushTexturePropertyID, brush.BrushTexture);
            paintNormalMaterial.SetTexture(brushNormalTexturePropertyID, brush.BrushNormalTexture);
            paintNormalMaterial.SetFloat(brushScalePropertyID, brush.Scale);
            paintNormalMaterial.SetFloat(brushNormalBlendPropertyID, brush.NormalBlend);

            foreach (var key in paintNormalMaterial.shaderKeywords)
            {
                paintNormalMaterial.DisableKeyword(key);
            }
            switch (brush.NormalBlending)
            {
            case PaintBrush.NormalBlendType.UseBrush:
                paintNormalMaterial.EnableKeyword(NORMAL_BLEND_USE_BRUSH);
                break;

            case PaintBrush.NormalBlendType.Add:
                paintNormalMaterial.EnableKeyword(NORMAL_BLEND_ADD);
                break;

            case PaintBrush.NormalBlendType.Sub:
                paintNormalMaterial.EnableKeyword(NORMAL_BLEND_SUB);
                break;

            case PaintBrush.NormalBlendType.Min:
                paintNormalMaterial.EnableKeyword(NORMAL_BLEND_MIN);
                break;

            case PaintBrush.NormalBlendType.Max:
                paintNormalMaterial.EnableKeyword(NORMAL_BLEND_MAX);
                break;

            default:
                paintNormalMaterial.EnableKeyword(NORMAL_BLEND_USE_BRUSH);
                break;
            }
        }
コード例 #12
0
        /// <summary>
        /// Paint processing that use world-space surface position.
        /// </summary>
        /// <param name="brush">Brush data.</param>
        /// <param name="worldPos">Point on object surface (world-space).</param>
        /// <param name="renderCamera">Camera to use to render the object.</param>
        /// <returns>The success or failure of the paint.</returns>
        public bool Paint(PaintBrush brush, Vector3 worldPos, Camera renderCamera = null)
        {
            Vector2 uv;

            if (renderCamera == null)
            {
                renderCamera = Camera.main;
            }

            Vector3   p   = transform.InverseTransformPoint(worldPos);
            Matrix4x4 mvp = renderCamera.projectionMatrix * renderCamera.worldToCameraMatrix * transform.localToWorldMatrix;

            if (MeshOperator.LocalPointToUV(p, mvp, out uv))
            {
                return(PaintUVDirect(brush, uv));
            }
            else
            {
                Debug.LogWarning("Could not get the point on the surface.");
                return(PaintNearestTriangleSurface(brush, worldPos, renderCamera));
            }
        }