【问题标题】:matlab Rendering a torus from verticesmatlab从顶点渲染圆环
【发布时间】:2014-02-09 01:17:36
【问题描述】:

我有一个任务是渲染一个圆环。这是我第一次使用 matlab,我已经设法用一些可怕的混乱代码完成了 2/3 的部分。

作业的第一步是将一个圆渲染为一组 20 个点。我为此制作了:

circle (IMG)

然后下一步是旋转和平移那个圆并绘制 20 次以表示圆环形状,所以我得到了这个:

torus points (IMG)

下一步是从顶点列表中渲染此圆环的 3d 表示。

我所拥有的是一个 400x3 矩阵中的大量顶点列表,如下所示:

7.66478245119846    -1.84059939326890   0.292371704722737
7.53434247103331    -1.79821687453702   0.573576436351046
7.32764268084884    -1.73105604149887   0.798635510047293
7.06491629627043    -1.64569106442929   0.945518575599317
6.77188080634298    -1.55047806205660   0.999847695156391
6.47722056651889    -1.45473714644104   0.956304755963036
...                 ...                     ...

其中每 20 行是另一个圆圈。

作业建议我使用 surf 函数来渲染它,但我不知道如何。我见过的所有示例都使用 surf 来表示被高度值扭曲的二维平面。这似乎根本不适合渲染这种 3 维形状。

我正在尝试的方法是构建一个人脸列表,然后使用 patch 函数来渲染圆。其中每个圆的前 2 个点与下一个圆对应的 2 个点组成一个正方形,然后进行渲染。

使用这样的东西:

for i=1:400
   face = [(i) (i+1) (i+21) (i+20)];
   patch('Faces',face,'Vertices',torus_vertices,'FaceColor','r'); %Should do this at                       the end
end

为此我得到了这样的东西:

3d Torus (IMG)

它扭曲并且一些侧面和内侧面被弄乱了。我认为这可能与顶点在某些时候翻转的顺序有关。

解决这个问题的最佳方法是什么?如果可能的话,我想用 surf 功能来做。

Ex1.m

%Initial positions
position = [2 0 0];
normal = [0 1 0];

%Rotation matrix
rotate18 = [cos(todeg(18))  -sin(todeg(18))     0;
           sin(todeg(18))  cos(todeg(18))      0;
           0               0                   1];

% translate along the x axis by 5        
translate = [5 0 0];

%% iterate 20 times to get a list of all the vertices
taurus_vertices = zeros(0, 3);
for i=0:20

    %rotate translation by 18 degrees
    translate = translate * rotate18;

    %translate
    position = position + translate;

    %rotate the normal so it faces the right direction
    normal = normal * rotate18;

    %Get vertices for the circle and append to vertices list
    circle_vertices = circle_3D(1, position, normal);  
    taurus_vertices = cat(1, taurus_vertices, circle_vertices);

    %translate back to original position
    position = position - translate;   

end

%scatter3(taurus_vertices(1:end, 1), taurus_vertices(1:end, 2), taurus_vertices(1:end, 3));


%% Render each face
for i=1:400
    face = [(i) (i+1) (i+21) (i+20)];
    patch('Faces',face,'Vertices',taurus_vertices,'FaceColor','r');
end

圆.m

function h_circle=circle_3D(r, M, n)

%% Prepare input parameters
if size(n,2)>size(n,1)
    n=n';
end

if size(M,2)>size(M,1)
    M=M';
end

%% Define unit vectors u and v
% u and v define a new coordinate system in a plane perpendicular to n
a=[1;0;0];
b=[0;1;0];

if isempty(find(cross(a,n), 1))==1
    a=[0;0;1];
elseif isempty(find(cross(b,n), 1))==1
    b=[0;0;1];
end
alpha=dot(n,a)/dot(n,n);
u=a-alpha*n;
v=cross(u,n);%b-beta*n-gamma*u;

u=u/sqrt(sum(u.*u));
v=v/sqrt(sum(v.*v));

%% Plot the circle
hold on
axis equal

degs = 0;
points = 0;
verts = zeros(20, 3);

for phi=0: pi()/180 : 2*pi()
    degs=degs+1;
    if (mod(degs,18) == 0 )
        points = points + 1;
        verts(points,1)=M(1,1)+r*cos(phi)*u(1,1)+r*sin(phi)*v(1,1);
        verts(points,2)=M(2,1)+r*cos(phi)*u(2,1)+r*sin(phi)*v(2,1);
        verts(points,3)=M(3,1)+r*cos(phi)*u(3,1)+r*sin(phi)*v(3,1);
    end
end

h_circle= verts;

【问题讨论】:

    标签: matlab


    【解决方案1】:

    您的问题非常适合 trisurf - 给定一组点,您需要构建一个三元组来连接网格。 对于您的问题,您可以使用:

       %inner circle points and radius
    N1=20;
    r1=1;
    %outer circle points and radius
    N2=30;
    r2=5;
    %inner cicle angles
    thC=linspace(0,2*pi*(1-1/N1),N1)';
    %inner cicle points
    xyzC=[r1*sin(thC), zeros(N1,1),r1*cos(thC)]';
    
    
    %torus points
    xyzT = zeros(3,N1*N2);
    for i=1:N2
        %circle transformation
        thT = 2*pi*i/N2;
        T = [1 0 0 r2*cos(thT); 0 1 0 r2*sin(thT);0 0 1 0]*[cos(thT) -sin(thT) 0 0;sin(thT) cos(thT) 0 0 ; 0 0 1 0; 0 0 0 1];
        %add points
        xyzT(:,(i-1)*N1+1:i*N1)=T*[xyzC ;ones(1,N1)];
    
    end
    
    %build patch triples
    tri=[];
    for i=1:N2
        for j=1:N1
            %get three points:
            % jth from ith circle
            % j+1th from ith circle
            % jth from i+1th circle
            tri(end+1,:)=[(i-1)*N1+j (i-1)*N1+j+1 i*N1+j];
            %get three points:
            % j+1th from ith circle
            % j+1th from i+1th circle
            % jth from i+1th circle
            tri(end+1,:)=[ i*N1+j (i-1)*N1+j+1 i*N1+j+1];
    
        end
    end
    tri=mod(tri-1,N1*N2)+1;
    trisurf(tri,xyzT(1,:),xyzT(2,:),xyzT(3,:));axis equal
    %fancy
    
    shading interp
    camlight left
    

    并得到:

    【讨论】:

    • 谢谢,我没有采纳您的方法,因为我同时设法制定了自己的方法。我希望我有,因为你的更优雅。
    【解决方案2】:

    谢谢你的例子。使用三角形而不是矩形来渲染圆环会更好,但截止日期大约需要一个小时,我设法让我当前的工作正常!

    我弄清楚是什么导致了我的问题。旋转平移矩阵会对每个圆点的方向产生不利影响(它们不对齐),导致它扭曲。

    在更彻底地查看了笔记(这是几年前的在线笔记)之后,我设法找到了一些用于扫描功能的伪代码,我曾经完全重写过这些代码。我现在在同一个点生成 20 个圆圈,然后通过增加数量来围绕原点旋转每个圆圈。这导致了这个:

    %% Settings
    
    points = 20; %Number of points in each circle
    circles = 20; %Number of circles making up the torus
    radius = 1; %Radius of the circle
    scale = 0.75; %Scale to apply to the whole torus
    center = [2 0 0]; %Center point of the first circle to sweep into a torus
    
    %% Create (circles+1) circles after the other in an array at point [2 0 0]
    
    %The extra circle overlaps the first, this is to make face generation much
    %simpler.
    
    V = zeros(circles*points, 3);
    for i=0:points:points*circles
        for k=1:points
            V(i+k,1) = center(1) + radius * cosd((k-1)*(360/points));
            V(i+k,2) = center(2) + 0;
            V(i+k,3) = center(3) + radius * sind((k-1)*(360/points));
        end
    end
    
    %% Sweep the circles, rotate each circle 18 degrees more than the previous
    
    for n=0:points:circles*points
    
        %Calculate degrees for current circle
        D = (n/points) * 360/circles;
    
        %Create a Z-rotation matrix
        Rz = [
            cosd(D)  sind(D) 0;
            -sind(D) cosd(D) 0;
            0        0       1;
        ];
    
        %Rotate each point of the circle
        for i=1:points
            V(n+i, :) = Rz * V(n+i, :)';
        end
    
    end
    
    %% Scale the torus
    
    %Create a scalar matrix
    S = [
        scale  0       0;
        0      scale   0;
        0      0       scale
    ];
    
    %Scale each point
    for n=0:points:circles*points
        for i=1:points
            V(n+i, :) = S * V(n+i, :)';
        end
    end
    
    %% Generate faces
    
    F = zeros(circles*points, 4);
    for n=1:points:circles*points
        for k=1:points
    
            %If it's an endface then have destination face vertices wrap around to the first face of the current circle
            if(mod(k, points) == 0)
                F((n-1)+k,2)= (n-1)+k+1 - points;
                F((n-1)+k,3)= n+points+k - points;
            else
                %otherwise use the next faces starting vertices
                F((n-1)+k,2)= (n-1)+k+1;
                F((n-1)+k,3)= n+points+k;
            end
    
            %Set the points coming from the previous face
            F((n-1)+k,1)= (n-1)+k;
            F((n-1)+k,4)= n+points+k-1;
    
       end
    end
    
    %% Render
    
    %Configure renderer
    axis equal;
    hold on;
    
    %Render points
    scatter3(V(1:end, 1), V(1:end, 2), V(1:end, 3), 'MarkerEdgeColor', 'b');
    
    %Render faces
    patch('Faces', F, 'Vertices', V, 'FaceColor', 'g');
    

    这使得:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      相关资源
      最近更新 更多