Esempio n. 1
0
        public OOModel(MannulDraw drawer)
        {
            Drawer = drawer;
            MeshFilter mf = drawer.gameObject.GetComponent <MeshFilter>();

            Model = new OOMesh(mf);
            Box   = new OOBox(Vector3.one * float.MaxValue, Vector3.one * float.MinValue);
            UpdateTransform();
            Head       = new OOItem();
            Tail       = new OOItem();
            Tail.CNext = null;
            Head.CPrev = null;
            Head.CNext = Tail;
            Tail.CPrev = Head;
            CanOcclude = 1;
            // GeoDebugDrawUtils.DrawAABB(Box.Min, Box.Max);
        }
Esempio n. 2
0
        /// <summary>
        /// 绘制一个物体到缓冲区
        /// </summary>
        /// <param name="obj">待绘制物体</param>
        private void DrawOccluder(OOModel obj)
        {
            // 获取物体的模型
            OOMesh mdl = obj.Model;
            // 计算 ModelView 矩阵.注意:这里需要相机的变换矩阵的逆矩阵
            // 另一问题:左手系和右手系问题。
            Matrix4x4 modelViewMatrix = mView * obj.ModelWorldMatrix;

            // 变换mesh的顶点到 相机空间 和 裁剪空间
            for (int i = 0; i < mdl.NumVert; i++)
            {
                // Vector3 p = obj.ModelWorldMatrix.MultiplyPoint3x4(mdl.Vertices[i]);
                Vector4 tmp = modelViewMatrix.MultiplyPoint3x4(mdl.Vertices[i]);
                mdl.CameraSpaceVertices[i] = tmp;
                tmp.w = 1;
                mdl.ClipSpaceVertices[i] = mProject * tmp;
            }
            int xmin = 100000;
            int xmax = 0;
            int ymin = 100000;
            int ymax = 0;

            // 遍历所有面
            for (int i = 0; i < mdl.NumFace; i++)
            {
                // 面索引
                int p1 = mdl.Faces[i][0];
                int p2 = mdl.Faces[i][1];
                int p3 = mdl.Faces[i][2];
                // 计算法向量。此处可以优化成:初始化时计算,而后变换一下法向量即可。
                // 构建右手坐标系 逆时针为正方向
                Vector3 a = mdl.CameraSpaceVertices[p2] - mdl.CameraSpaceVertices[p1];
                Vector3 b = mdl.CameraSpaceVertices[p3] - mdl.CameraSpaceVertices[p1];
                Vector3 n = Vector3.Cross(a, b);
                // 背面剔除。可计算相机的朝向,然后与三角面的法线计算即可。
                // 此处实际上计算 Camera 空间 原点到平面的距离是否小于0
                if (Vector3.Dot(n, mdl.CameraSpaceVertices[p1]) < 0)
                {
                    mClip.mClipSpaceVertices[0] = mdl.ClipSpaceVertices[p1];
                    mClip.mClipSpaceVertices[1] = mdl.ClipSpaceVertices[p2];
                    mClip.mClipSpaceVertices[2] = mdl.ClipSpaceVertices[p3];
                    // 裁剪计算
                    int nv = mClip.ClipAndProject(3);
#if TEST_DRAW_ONE
                    DebugUtils.Info("ClipAndProject", string.Format("world1({0}, {1})", mClip.mScreenSpaceVertices[0][0], mClip.mScreenSpaceVertices[0][1]));
                    DebugUtils.Info("ClipAndProject", string.Format("world2({0}, {1})", mClip.mScreenSpaceVertices[1][0], mClip.mScreenSpaceVertices[1][1]));
                    DebugUtils.Info("ClipAndProject", string.Format("world3({0}, {1})", mClip.mScreenSpaceVertices[2][0], mClip.mScreenSpaceVertices[2][1]));
#endif
                    // 裁剪判断
                    if (nv > 2)
                    {
                        // 裁剪后,计算屏幕区域的AABB
                        for (int j = 0; j < nv; j++)
                        {
                            if (mClip.mScreenSpaceVertices[j][0] < xmin)
                            {
                                xmin = mClip.mScreenSpaceVertices[j][0];
                            }
                            else
                            {
                                if (mClip.mScreenSpaceVertices[j][0] > xmax)
                                {
                                    xmax = mClip.mScreenSpaceVertices[j][0];
                                }
                            }
                            if (mClip.mScreenSpaceVertices[j][1] < ymin)
                            {
                                ymin = mClip.mScreenSpaceVertices[j][1];
                            }
                            else if (mClip.mScreenSpaceVertices[j][1] > ymax)
                            {
                                ymax = mClip.mScreenSpaceVertices[j][1];
                            }
                        }
                        // 绘制多边形到缓冲
                        Map.DrawPolygon(mClip.mScreenSpaceVertices, nv);
                    }
                }
            }
            // 设置该区域内有被覆盖
            Map.SetDirtyRectangle(xmin, ymin, xmax, ymax);
        }