你能帮我将我的三维链模型绘制到特定方向吗?

huangapple go评论65阅读模式
英文:

Can you help me draw my 3D model of a chain to a specific direction?

问题

以下是代码的翻译部分:

使用下面的代码,我创建了一个函数来使用Helix Toolkit在C#中绘制3D链条模型。这正是我想要的,但是...现在我正在苦苦思考如何以特定方向绘制链节,从起点到终点,但我上周没有取得多大进展。我知道我需要使用矢量乘法或标量,但我需要一些指导来解决我的问题。

using HelixToolkit.SharpDX.Core;
using HelixToolkit.Wpf.SharpDX;
using SharpDX;

namespace RapiD.Geometry.Models
{
    public partial class ChainLink3D : GeometryBase3D
    {
        [ObservableProperty]
        float radius;
        [ObservableProperty]
        float width;
        [ObservableProperty]
        float diameter;
        [ObservableProperty]
        float length;
        [ObservableProperty]
        int copies;
        [ObservableProperty]
        ObservableCollection<Element3D> elements;
        public ChainLink3D(float diameter, float width, float length, int copies)
        {
            this.width = width;
            this.length = length;
            this.diameter = diameter;
            this.copies = copies;
            this.elements = new ObservableCollection<Element3D&gt();

            OriginalMaterial = PhongMaterials.Chrome;
            DrawChainLink();
        }

        public void DrawChainLink()
        {
            MeshBuilder meshBuilder = new MeshBuilder();
            float radius = (width - diameter) / 2;
            float trans = 0f;
            float translate = length + (radius * 2) - diameter;
            float yoffset = 0;
            int segments = 10;
            float interval = 180 / segments;
            int numOfCopies = copies;
            float startPoint = radius - (diameter / 2);
            float endPoint = -length - radius + (diameter / 2);

            Vector3 startVector = new Vector3(-300, 200f, 0);
            Vector3 endVector = new Vector3(300, 500, 0);

            Vector3 direction = Vector3.Normalize(endVector - startVector);

            //The for loop is drawing the chainlink

            for (int j = 0; j < numOfCopies; j++)
            {
                List<Vector3> single_chain_link = new List<Vector3&gt();

                for (float i = 0; i <= 360; i += interval)
                {
                    if (i > 180)
                        yoffset = -length;
                    else
                        yoffset = 0;

                    float a = i * MathF.PI / 180;
                    float x = radius * MathF.Cos(a);
                    float y = radius * MathF.Sin(a) + yoffset + trans;

                    Vector3 vec = new Vector3(x, y, 0);

                    //Rotates every second chainlink
                    if (j % 2 == 1)
                        vec = new Vector3(0, y, x);

                    vec += startVector;
                    //vec *= direction;

                    single_chain_link.Add(vec);
                }

                // this three are a reference for a new example direction in which I want to draw the chain link to

                meshBuilder.AddSphere(Vector3.Zero, 5, 10, 10);
                meshBuilder.AddSphere(startVector, 5, 10, 10);
                meshBuilder.AddSphere(endVector, 5, 10, 10);

                meshBuilder.AddTube(single_chain_link, diameter, 10, true);
                meshBuilder.AddArrow(new Vector3(0, startPoint + trans, 0), new Vector3(0, endPoint + trans, 0), 2, 10);
                elements.Add(new Element3D(new Vector3(0, startPoint + trans, 0), new Vector3(0, endPoint + trans, 0)));

                //single_chain_link.OrderByDescending(x => x.X);

                MeshGeometry = meshBuilder.ToMeshGeometry3D();
                trans -= translate;
            }
        }
    }
}

我已经成功绘制了链条从特定的起点开始,但我想要绘制元素从给定的起点到终点位置。

英文:

With the code below I created a function to draw a 3D chain model in C# using the helix toolkit. This works exactly how I wanted to but... now I'm breaking my head around a good approach to draw the chainlinks in specific direction, from a startpoint to a endpoint, but I didn't come much further the last week. I know I need to work with vector multiplication or scalars but I need some guidance to right topic to solve my problem.

using HelixToolkit.SharpDX.Core;
using HelixToolkit.Wpf.SharpDX;
using SharpDX;
namespace RapiD.Geometry.Models
{
public partial class ChainLink3D : GeometryBase3D 
{
[ObservableProperty]
float radius;
[ObservableProperty]
float width;
[ObservableProperty]
float diameter;
[ObservableProperty]
float length;
[ObservableProperty]
int copies;
[ObservableProperty]
ObservableCollection<Element3D> elements;
public ChainLink3D(float diameter, float width, float length, int copies)
{
this.width = width;
this.length = length;
this.diameter = diameter;
this.copies = copies;
this.elements= new ObservableCollection<Element3D>();   
OriginalMaterial = PhongMaterials.Chrome;
DrawChainLink();
}
public void DrawChainLink()
{
MeshBuilder meshBuilder = new MeshBuilder();
float radius = (width - diameter) / 2;
float trans = 0f;
float translate = length + (radius * 2) - diameter;
float yoffset = 0;
int segments = 10;
float interval = 180 / segments;
int numOfCopies = copies;
float startPoint = radius - (diameter / 2);
float endPoint = -length -radius + (diameter / 2);
Vector3 startVector = new Vector3(-300, 200f, 0);
Vector3 endVector = new Vector3(300, 500, 0);
Vector3 direction = Vector3.Normalize (endVector - startVector);
//The for loop is drawing the chainlink 
for (int j = 0; j < numOfCopies; j++)
{
List<Vector3> single_chain_link = new List<Vector3>();
for (float i = 0; i <= 360; i += interval)
{
if (i > 180)
yoffset = -length;
else
yoffset = 0;
float a = i * MathF.PI / 180;
float x = radius * MathF.Cos(a);
float y = radius * MathF.Sin(a) + yoffset + trans;
Vector3 vec = new Vector3(x, y, 0);
//Rotates every second chainlink
if (j % 2 == 1)                    
vec =new Vector3(0, y, x);
vec += startVector;
//vec *= direction;
single_chain_link.Add(vec);
}
// this three are a reference for a new example direction in which I want to draw the chain link to
meshBuilder.AddSphere(Vector3.Zero, 5, 10, 10);
meshBuilder.AddSphere(startVector, 5, 10, 10);
meshBuilder.AddSphere(endVector, 5, 10, 10);
meshBuilder.AddTube(single_chain_link, diameter, 10, true);
meshBuilder.AddArrow(new Vector3(0, startPoint + trans, 0), new Vector3(0, endPoint + trans, 0), 2, 10);
elements.Add(new Element3D(new Vector3(0, startPoint + trans, 0), new Vector3(0, endPoint + trans, 0)));
//single_chain_link.OrderByDescending(x => x.X);
MeshGeometry = meshBuilder.ToMeshGeometry3D();
trans -= translate;
}
}
}
}

I did successfully draw the chain form a specific startpoint, but I want to draw the elements from the given startpoint to a endposition.

答案1

得分: 1

你应该使用一个变换来旋转和/或移动你的模型以达到正确的方向。

要从一个方向创建旋转矩阵,了解一些线性代数知识非常有用。特别是两个向量的叉积会得到一个与两者都正交的向量。而一个旋转矩阵实际上不过是三个正交轴。所以你可以像下面的伪代码一样做:

var x = myDirection;
if (x.AlmostEqual(Vector3.UnitY)){
    var y = x.CrossProduct(Vector3.UnitZ);
}
else {
    var y = x.CrossProduct(Vector3.UnitY);
}
var z = y.CrossProduct(x);
// 从 x、y、z 轴创建矩阵

如果你在使用 System.Numerics,可以使用 Matrix4x4.CreateLookAt,它大致完成了这个任务。

一旦你有了一个矩阵,你可以使用它来旋转模型到你想要的任何方向。请注意,通常情况下,会混淆方向,最终得到的结果可能有偏差,比如旋转了90度,或者其他错误。不帮助的是不同的库可能使用不同的约定。我最好的解决办法是分步进行操作,验证结果是否如你所期望的那样。

英文:

You should be using a transformation to rotate and/or move your model to the correct orientation.

To create a rotation matrix from a direction it is useful to know some linear algebra. Notably that the cross product between two vectors result in a vector orthogonal to both. And that a rotation matrix is not really anything more than three ortogonal axes. So you can do something like the following pseudo code

   var x = myDirection;
if(x.AlmostEqual(Vector3.UnitY)){
var y = x.CrossProduct(Vector3.UnitZ);
}
else{
var y = x.CrossProduct(Vector3.UnitY);
}
var z = y.CrossProduct(x);
// Create a matrix from the x, y, z axes

If you are using System.Numerics there is the Matrix4x4.CreateLookAt that does more or less this.

Once you have a matrix you can just transform your model to rotate it in whatever direction you want. Note that it is common, at least for me, to mix up directions and end up with something that is of by 90 degrees, or some other error. It does not help that different libraries can use some different conventions. My best solution is to do things in small steps and verify that the result is as you expect it to be.

huangapple
  • 本文由 发表于 2023年2月10日 16:12:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75408433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定