Beispiel #1
0
        protected override void calculateSampling(VolumeBrick brick)
        {
            Matrix modelview        = DrawArgs.Instance.WorldCamera.AbsoluteViewMatrix;
            Matrix modelviewInverse = Matrix.Invert(modelview);

            GMBoundingBox volumeBox = brick.VolumeBox.Clone() as GMBoundingBox;

            volumeBox.Transformation(modelview);

            /*
             * int minIndex;
             * int maxIndex;
             * minIndex = 0;
             * maxIndex = 7;
             * for (int i = 0; i < 8; i++)
             * {
             *  if (volumeBox.Corners[minIndex].Z > volumeBox.Corners[i].Z) minIndex = i;
             *  if (volumeBox.Corners[maxIndex].Z < volumeBox.Corners[i].Z) maxIndex = i;
             * }
             *
             * Vector3 maxv = new Vector3(modelviewInverse.M31 * volumeBox.Corners[maxIndex].Z,
             *                         modelviewInverse.M32 * volumeBox.Corners[maxIndex].Z,
             *                         modelviewInverse.M33 * volumeBox.Corners[maxIndex].Z);
             * Vector3 minv = new Vector3(modelviewInverse.M31 * volumeBox.Corners[minIndex].Z,
             *                         modelviewInverse.M32 * volumeBox.Corners[minIndex].Z,
             *                         modelviewInverse.M33 * volumeBox.Corners[minIndex].Z);
             */

            //_samples = 3000;
            _delta = (float)((DrawArgs.Camera.WorldRadius + 480000) / (double)_samples);
        }
        public void SortBricks(Matrix viewMatrix)
        {
            if (_bricks.Count > 1)
            {
                List <double> sortvals = new List <double>();

                for (int i = 0; i < _bricks.Count; i++)
                {
                    Vector3 center = Vector3.TransformCoordinate(_bricks[i].Center, viewMatrix);

                    sortvals.Add(center.LengthSquared());
                }

                for (int i = 0; i < _bricks.Count; i++)
                {
                    for (int j = i + 1; j < _bricks.Count; ++j)
                    {
                        if (sortvals[i] < sortvals[j])
                        {
                            double      valtmp   = sortvals[i];
                            VolumeBrick bricktmp = _bricks[i];

                            sortvals[i] = sortvals[j];
                            sortvals[j] = valtmp;

                            _bricks[i] = _bricks[j];
                            _bricks[j] = bricktmp;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Calculate the sampling distance
        /// </summary>
        protected virtual void calculateSampling(VolumeBrick brick)
        {
            Matrix modelview        = DrawArgs.Instance.WorldCamera.AbsoluteViewMatrix;
            Matrix modelviewInverse = Matrix.Invert(modelview);

            GMBoundingBox volumeBox = brick.VolumeBox.Clone() as GMBoundingBox;

            volumeBox.Transformation(modelview);

            //计算在视觉矩阵下离视点最远与最近的角点
            int minIndex;
            int maxIndex;

            minIndex = 0;
            maxIndex = 7;
            for (int i = 0; i < 8; i++)
            {
                if (volumeBox.Corners[minIndex].Z > volumeBox.Corners[i].Z)
                {
                    minIndex = i;
                }
                if (volumeBox.Corners[maxIndex].Z < volumeBox.Corners[i].Z)
                {
                    maxIndex = i;
                }
            }

            Vector3 maxv = new Vector3(modelviewInverse.M31 * volumeBox.Corners[maxIndex].Z,
                                       modelviewInverse.M32 * volumeBox.Corners[maxIndex].Z,
                                       modelviewInverse.M33 * volumeBox.Corners[maxIndex].Z);
            Vector3 minv = new Vector3(modelviewInverse.M31 * volumeBox.Corners[minIndex].Z,
                                       modelviewInverse.M32 * volumeBox.Corners[minIndex].Z,
                                       modelviewInverse.M33 * volumeBox.Corners[minIndex].Z);

            float distance = (maxv - minv).Length();

            //_samples = 400;
            _delta = distance / _samples;
        }
Beispiel #4
0
        protected override void DrawViewAlignedSlices(DrawArgs drawArgs, VolumeBrick brick, Matrix viewMatrix)
        {
            double outerplus = 480000, interplus = 100000;
            double r0 = drawArgs.WorldCamera.WorldRadius + interplus;
            double r1 = drawArgs.WorldCamera.WorldRadius + outerplus;
            //drawArgs.device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);

            GMBoundingBox textureBox = brick.TextureBox;
            GMBoundingBox volumeBox  = brick.VolumeBox;
            GMBoundingBox rotatedBox = volumeBox.Clone() as GMBoundingBox;

            rotatedBox.Transformation(viewMatrix);
            GMVector3D tempp = drawArgs.WorldCamera.ReferenceCenter;
            //Vector3 dir = drawArgs.WorldCamera.Position - new Vector3((float)tempp.X, (float)tempp.Y, (float)tempp.Z);
            Vector3 dir = new Vector3(drawArgs.WorldCamera.Position.x - (float)tempp.X, drawArgs.WorldCamera.Position.y - (float)tempp.Y,
                                      drawArgs.WorldCamera.Position.z - (float)tempp.Z);

            Vector3 slicePlaneNormal = new Vector3(-dir.X, -dir.Y, -dir.Z);

            slicePlaneNormal.Normalize();



            calculateSampling(brick);

            drawArgs.device.VertexFormat = PositionTextured3D.Format;
            _effect.Technique            = "Spherical";
            _effect.SetTexture("VolumeTex", brick.Texture(0));
            if (_frameNow != nTime - 1) //当frameTime
            {
                _effect.SetTexture("VolumeTex2", brick.Texture(1));
            }
            else
            {
                _effect.SetTexture("VolumeTex2", brick.Texture(0));
            }

            _effect.Begin(FX.None);
            _effect.BeginPass(0);

            if (true || calculatedSliceRay == Vector3.Zero || calculatedSliceRay != slicePlaneNormal)
            {
                calculatedSlices.Clear();


                //计算两个slice间距
                Vector3 sliceDelta = slicePlaneNormal * _delta;

                Vector3 center     = new Vector3(0, 0, 0);
                Vector3 slicePoint = center + ((float)r1 * slicePlaneNormal) - sliceDelta;

                Vector3 sliceOrtho;

                if (Vector3.Dot(slicePlaneNormal, new Vector3(1, 1, 0)) != 0.0)
                {
                    sliceOrtho = Vector3.Cross(slicePlaneNormal, new Vector3(1, 1, 0));
                }
                else
                {
                    sliceOrtho = Vector3.Cross(slicePlaneNormal, new Vector3(0, 1, 0));
                }
                sliceOrtho.Normalize();


                float left   = (brick.MinX + 180) / 360.0f;
                float buttom = (brick.MinY + 90) / 180.0f;
                float right  = (brick.MinX + 180 + brick._nx * brick.LonStep) / 360.0f;
                float upp    = (brick.MinY + 90 + brick._ny * brick.LatStep) / 180.0f;
                float lowest = brick.MinZ;

                for (int i = 0; i <= _samples; i++)
                {
                    float d = (center - slicePoint).Length();
                    if (r1 > d)
                    {
                        float rg0 = 0.0f;
                        float rg1 = (float)Math.Sqrt(r1 * r1 - d * d);
                        if (r0 > d)
                        {
                            rg0 = (float)Math.Sqrt(r0 * r0 - d * d);
                        }

                        int m = 0;
                        PositionTextured3D[] d3dVerts = new PositionTextured3D[90];
                        for (double theta = -Math.PI / 20.0; theta <= 2 * Math.PI; theta += Math.PI / 20.0)
                        {
                            Vector3 v = sliceOrtho * (float)Math.Cos(theta) + (float)Math.Sin(theta) * Vector3.Cross(slicePlaneNormal, sliceOrtho);
                            v.Normalize();

                            Vector3 v0 = slicePoint + v * rg0;
                            Vector3 v1 = slicePoint + v * rg1;

                            Vector3 LonLat0 = GMMaths.CartesianToSpherical2(v0.X, v0.Y, v0.Z);
                            Vector3 LonLat1 = GMMaths.CartesianToSpherical2(v1.X, v1.Y, v1.Z);

                            if (LonLat0.Z >= max)
                            {
                                max = LonLat0.Z;
                            }
                            if (LonLat1.Z >= max)
                            {
                                max = LonLat1.Z;
                            }
                            if (LonLat0.Z <= min)
                            {
                                min = LonLat0.Z;
                            }
                            if (LonLat1.Z <= min)
                            {
                                min = LonLat1.Z;
                            }

                            Vector3 t0 = new Vector3(0, 0, 0);
                            Vector3 t1 = new Vector3(0, 0, 0);

                            t0.X = (LonLat0.Z + 180) / 360.0f;
                            t0.Y = (LonLat0.Y + 90.0f) / 180.0f;
                            t0.Z = 1.0f - (v0.Length() - (float)r0) / (float)(outerplus - interplus);
                            t1.X = (LonLat1.Z + 180) / 360.0f;
                            t1.Y = (LonLat1.Y + 90.0f) / 180.0f;
                            t1.Z = 1.0f - (v1.Length() - (float)r0) / (float)(outerplus - interplus);

                            t0.X = (t0.X - left) / (right - left);
                            t0.Y = (t0.Y - buttom) / (upp - buttom);
                            t1.X = (t1.X - left) / (right - left);
                            t1.Y = (t1.Y - buttom) / (upp - buttom);

                            d3dVerts[m].X  = v0.X;
                            d3dVerts[m].Y  = v0.Y;
                            d3dVerts[m].Z  = v0.Z;
                            d3dVerts[m].Tu = t0.X;
                            d3dVerts[m].Tv = t0.Y;
                            d3dVerts[m].Tw = t0.Z;
                            m++;
                            d3dVerts[m].X  = v1.X;
                            d3dVerts[m].Y  = v1.Y;
                            d3dVerts[m].Z  = v1.Z;
                            d3dVerts[m].Tu = t1.X;
                            d3dVerts[m].Tv = t1.Y;
                            d3dVerts[m].Tw = t1.Z;
                            m++;
                        }
                        drawArgs.device.DrawUserPrimitives(PrimitiveType.TriangleStrip, m - 4, d3dVerts);

                        calculatedSlices.Add(d3dVerts);
                    }
                    slicePoint -= sliceDelta;
                }
            }
            else
            {
                for (int i = 0; i < calculatedSlices.Count; i++)
                {
                    drawArgs.device.DrawUserPrimitives(PrimitiveType.TriangleStrip, 80, calculatedSlices[i]);
                }
            }


            _effect.EndPass();
            _effect.End();

            calculatedSliceRay = slicePlaneNormal;
        }
        protected virtual void DrawViewAlignedSlices(DrawArgs drawArgs, VolumeBrick brick, Matrix viewMatrix)
        {
            try
            {
                GMBoundingBox textureBox = brick.TextureBox;
                GMBoundingBox volumeBox  = brick.VolumeBox;
                GMBoundingBox rotatedBox = volumeBox.Clone() as GMBoundingBox;
                rotatedBox.Transformation(viewMatrix);

                //计算在视觉矩阵下离视点最远与最近的角点
                int minIndex;
                int maxIndex;
                minIndex = 0;
                maxIndex = 7;
                for (int i = 0; i < 8; i++)
                {
                    // z
                    if (rotatedBox.Corners[minIndex].Z > rotatedBox.Corners[i].Z)
                    {
                        minIndex = i;
                    }
                    if (rotatedBox.Corners[maxIndex].Z < rotatedBox.Corners[i].Z)
                    {
                        maxIndex = i;
                    }
                }

                //计算切割起算点
                Vector3 slicePoint = volumeBox.Corners[minIndex];

                //计算slicePlaneNormal = Vector(0,1,0)  * InvertedViewMatrix;
                Matrix  invertedViewMatrix = Matrix.Invert(viewMatrix);
                Vector3 slicePlaneNormal   = new Vector3(invertedViewMatrix.M31, invertedViewMatrix.M32, invertedViewMatrix.M33);
                slicePlaneNormal.Normalize();

                calculateSampling(brick);
                //计算两个slice间距
                Vector3 sliceDelta = slicePlaneNormal * _delta;

                //
                // Calculate edge intersections between the plane and the boxes
                //
                Vector3[] verts  = new Vector3[6];  // for edge intersections
                Vector3[] tverts = new Vector3[6];  // for texture intersections
                Vector3[] rverts = new Vector3[6];  // for transformed edge intersections

                drawArgs.device.VertexFormat = PositionTextured3D.Format;

                if (isUsingLight)
                {
                    _effect.Technique = "TextureTD_Lighting";
                }
                else
                {
                    _effect.Technique = "TextureTD";
                }

                _effect.SetValue("worldMatrix", drawArgs.device.GetTransform(TransformState.World));
                _effect.SetValue("viewMatrix", drawArgs.device.GetTransform(TransformState.View));
                _effect.SetValue("WorldViewProj", drawArgs.device.GetTransform(TransformState.World) * drawArgs.device.GetTransform(TransformState.View) * drawArgs.device.GetTransform(TransformState.Projection));

                Matrix mi = drawArgs.device.GetTransform(TransformState.World) * drawArgs.device.GetTransform(TransformState.View);
                mi.Invert();
                mi = Matrix.Transpose(mi);
                _effect.SetValue("normalMat", mi);

                _effect.SetTexture("VolumeTex", brick.Texture(0));
                if (_frameNow != nTime - 1) //当frameTime
                {
                    _effect.SetTexture("VolumeTex2", brick.Texture(1));
                }
                else
                {
                    _effect.SetTexture("VolumeTex2", brick.Texture(0));
                }
                //zxq 修改库后变化
                int oldAEnable     = drawArgs.device.GetRenderState(RenderState.AlphaBlendEnable);
                int oldSourceBlend = drawArgs.device.GetRenderState(RenderState.SourceBlend);
                int oldDesBlend    = drawArgs.device.GetRenderState(RenderState.DestinationBlend);
                drawArgs.device.SetRenderState(RenderState.AlphaBlendEnable, true);
                drawArgs.device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
                drawArgs.device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);

                _effect.Begin(FX.None);
                _effect.BeginPass(0);

                for (int i = 0; i <= _samples; i++)
                {
                    int[] order = new int[6] {
                        0, 1, 2, 3, 4, 5
                    };
                    int size = 0;
                    //if (i < 0 | i > 100) continue;
                    //
                    // 计算slice面片和box的交点
                    //
                    size = intersect(slicePoint, slicePlaneNormal, volumeBox, verts, textureBox, tverts, rotatedBox, rverts, minIndex, maxIndex);
                    //
                    // 计算交点的凸壳
                    //
                    findVertexOrder(rverts, order, size);

                    //至少有三个点,绘制面
                    if (size >= 3)
                    {
                        PositionTextured3D[] d3dVerts = new PositionTextured3D[size];
                        for (int fori = 0; fori < size; fori++)
                        {
                            d3dVerts[fori].X  = verts[order[fori]].X;
                            d3dVerts[fori].Y  = verts[order[fori]].Y;
                            d3dVerts[fori].Z  = verts[order[fori]].Z;
                            d3dVerts[fori].Tu = tverts[order[fori]].X;
                            d3dVerts[fori].Tv = tverts[order[fori]].Y;
                            d3dVerts[fori].Tw = tverts[order[fori]].Z;
                        }

                        drawArgs.device.DrawUserPrimitives(PrimitiveType.TriangleFan, size - 2, d3dVerts);
                    }

                    //下一slice平面
                    slicePoint += sliceDelta;
                }
                _effect.EndPass();
                _effect.End();
                //zxq 修改库后变化
                drawArgs.device.SetRenderState(RenderState.AlphaBlendEnable, oldAEnable);
                drawArgs.device.SetRenderState(RenderState.SourceBlend, oldSourceBlend);
                drawArgs.device.SetRenderState(RenderState.DestinationBlend, oldDesBlend);
            }
            catch (Exception ex)
            { }
        }
 public virtual void RenderBrick(DrawArgs drawArgs, VolumeBrick brick)
 {
     DrawViewAlignedSlices(drawArgs, brick, drawArgs.WorldCamera.AbsoluteViewMatrix);
 }