matlab从顶点渲染圆环

时间:2014-02-09 01:17:37

标签: matlab

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

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

circle(IMG)

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

torus points(IMG)

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

我所拥有的是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来表示由高度值扭曲的二维平面。这似乎不适合渲染这种三维形状。

我正在尝试的方法是构建一个面列表,然后使用补丁函数来渲染圆。每个圆的前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)

它扭曲,并且一些侧面和内侧面都搞砸了。我认为这可能与顶点在某个时刻翻转的顺序有关。

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

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

circle.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;

2 个答案:

答案 0 :(得分:2)

你的问题对于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

并得到: enter image description here

答案 1 :(得分:1)

谢谢你的例子。使用三角形而不是矩形来渲染圆环会更好,但截止时间就像一个小时之后,我设法使我当前的一个工作!

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

在仔细查看笔记之后(这将是几年的在线笔记),我设法找到一些用于完全重写的扫描功能的伪代码。我现在在同一个点生成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');

这使得:

torus