1

我有一个正在与其他人一起制作的程序,但遇到了问题。我正在努力在 XNA 窗口中将多边形模型添加到我们的场景中。我已经完成了那部分。我也有围绕每个多边形绘制的边界球体(我知道我标记为边界框,但没有边界球体标记)。我的问题是,当我在 3D 空间中移动多边形时,边界球的移动量是多边形的两倍。我想象它在我的多边形矩阵中的一些东西,我用它来创建边界球,使它移动两倍,但这只是推测。所以为了澄清,我会给你一个我的问题的例子。如果我按住 D 沿 X 轴移动多边形。(model.position.X--;) 多边形按预期移动,但多边形周围的边界球移动两倍。谢谢你们的帮助!

这是我绘制模型和边界球体的方法:

       public void Draw(Matrix view, Matrix projection, bool drawBoundingSphere)
    {
        Matrix translateMatrix = Matrix.CreateTranslation(position);
        Matrix worldMatrix = translateMatrix * Matrix.CreateScale(scaleRatio);

        foreach (ModelMesh mesh in model.Meshes)
        {
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.World = worldMatrix * modelAbsoluteBoneTransforms[mesh.ParentBone.Index];
                effect.View = view;
                effect.Projection = projection;
                effect.EnableDefaultLighting();
                effect.PreferPerPixelLighting = true;
            }
            mesh.Draw();
            if (drawBoundingSphere)
            {
                // the mesh's BoundingSphere is stored relative to the mesh itself.
                // (Mesh space). We want to get this BoundingSphere in terms of world
                // coordinates. To do this, we calculate a matrix that will transform
                // from coordinates from mesh space into world space....
                Matrix world = modelAbsoluteBoneTransforms[mesh.ParentBone.Index] * worldMatrix;
                // ... and then transform the BoundingSphere using that matrix.
                BoundingSphere sphere = BoundingSphereRenderer.TransformBoundingSphere(mesh.BoundingSphere, world);
                // now draw the sphere with our renderer
                BoundingSphereRenderer.Draw(sphere, view, projection);
            }
        } 

这是 BoundingSphereRenderer 代码:

        private static VertexBuffer vertexBuffer;
    private static BasicEffect effect;
    private static int lineCount;
    public static void Initialize(GraphicsDevice graphicsDevice, int sphereResolution)
    {
        // create our effect
        effect = new BasicEffect(graphicsDevice);
        effect.LightingEnabled = false;
        effect.VertexColorEnabled = true;
        // calculate the number of lines to draw for all circles
        lineCount = (sphereResolution + 1) * 3;
        // we need two vertices per line, so we can allocate our vertices
        VertexPositionColor[] vertices = new VertexPositionColor[lineCount * 2];
        // compute our step around each circle
        float step = MathHelper.TwoPi / sphereResolution;
        // used to track the index into our vertex array
        int index = 0;
        //create the loop on the XY plane first
        for (float angle = 0f; angle < MathHelper.TwoPi; angle += step)
        {
            vertices[index++] = new VertexPositionColor(new Vector3((float)Math.Cos(angle), (float)Math.Sin(angle), 0f), Color.Blue);
            vertices[index++] = new VertexPositionColor(new Vector3((float)Math.Cos(angle + step), (float)Math.Sin(angle + step), 0f), Color.Blue);
        }
        //next on the XZ plane
        for (float angle = 0f; angle < MathHelper.TwoPi; angle += step)
        {
            vertices[index++] = new VertexPositionColor(new Vector3((float)Math.Cos(angle), 0f, (float)Math.Sin(angle)), Color.Red);
            vertices[index++] = new VertexPositionColor(new Vector3((float)Math.Cos(angle + step), 0f, (float)Math.Sin(angle + step)), Color.Red);
        }
        //finally on the YZ plane
        for (float angle = 0f; angle < MathHelper.TwoPi; angle += step)
        {
            vertices[index++] = new VertexPositionColor(new Vector3(0f, (float)Math.Cos(angle), (float)Math.Sin(angle)), Color.Green);
            vertices[index++] = new VertexPositionColor(new Vector3(0f, (float)Math.Cos(angle + step), (float)Math.Sin(angle + step)), Color.Green);
        }
        // now we create the vertex buffer and put the vertices in it
        vertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionColor), vertices.Length, BufferUsage.WriteOnly);
        vertexBuffer.SetData(vertices);
    }

    public static void Draw(this BoundingSphere sphere, Matrix view, Matrix projection)
    {
        if (effect == null)
            throw new InvalidOperationException("You must call Initialize before you can render any spheres.");
        // set the vertex buffer
        effect.GraphicsDevice.SetVertexBuffer(vertexBuffer);
        // update our effect matrices
        effect.World = Matrix.CreateScale(sphere.Radius) * Matrix.CreateTranslation(sphere.Center);
        effect.View = view;
        effect.Projection = projection;
        // draw the primitives with our effect
        effect.CurrentTechnique.Passes[0].Apply();
        effect.GraphicsDevice.DrawPrimitives(PrimitiveType.LineList, 0, lineCount);
    }

    public static BoundingSphere TransformBoundingSphere(BoundingSphere sphere, Matrix transform)
    {
        BoundingSphere transformedSphere;
        // the transform can contain different scales on the x, y, and z components.
        // this has the effect of stretching and squishing our bounding sphere along
        // different axes. Obviously, this is no good: a bounding sphere has to be a
        // SPHERE. so, the transformed sphere's radius must be the maximum of the 
        // scaled x, y, and z radii.
        // to calculate how the transform matrix will affect the x, y, and z
        // components of the sphere, we'll create a vector3 with x y and z equal
        // to the sphere's radius...
        Vector3 scale3 = new Vector3(sphere.Radius, sphere.Radius, sphere.Radius);
        // then transform that vector using the transform matrix. we use
        // TransformNormal because we don't want to take translation into account.
        scale3 = Vector3.TransformNormal(scale3, transform);
        // scale3 contains the x, y, and z radii of a squished and stretched sphere.
        // we'll set the finished sphere's radius to the maximum of the x y and z
        // radii, creating a sphere that is large enough to contain the original 
        // squished sphere.
        transformedSphere.Radius = Math.Max(scale3.X, Math.Max(scale3.Y, scale3.Z));
        // transforming the center of the sphere is much easier. we can just use 
        // Vector3.Transform to transform the center vector. notice that we're using
        // Transform instead of TransformNormal because in this case we DO want to 
        // take translation into account.
        transformedSphere.Center = Vector3.Transform(sphere.Center, transform);
        return transformedSphere;
    }
4

0 回答 0