2010-11-16 27 views
2

我試圖實現以下任務:映射球體上的圖像並找回展開的equirectangular投影

想象一下2:1縱橫比繪圖畫布。我想在這個畫布上放置矩形圖像(..x,y笛卡爾座標),並且當我將圖像從畫布中心(0,0)進一步移開時,我想讓它看起來像是在滑動超過想象球體的法線。

我相信的邏輯是將圖像的(x,y)2D笛卡爾座標轉換爲相應的緯度,經度球面座標,然後將等軸投影應用到球體並返回圖像以及相應的失真(就好像它是在3D建模軟件包中展開的uvs一樣)。

有一個應用程序正在執行稱爲「HDR Light Studio」的應用程序,該應用程序爲3D場景照明目的生成等矩陣(緯度/經度)HDR圖像。 如果您在他們的網站上查看視頻,您將明白我想要達到的圖像失真的確切類型。

如果可以的話,請給我一些幫助。 我在網上搜索了所有信息,但沒有運氣。

在此先感謝

回答

0

如果我理解正確的問題,你應該能夠實現通過創建一個球體的一部分,並使用圖像作爲紋理一樣的效果。不是移動圖片,而是旋轉球體。

代碼和主窗口的XAML:

namespace WpfBalls 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      Ball ball = new Ball(); 
      ball.ImageSource = "YourPictureHere.jpg"; //path to the picture 
      visualModel.Children.Add(ball); 
     } 
    } 
} 

<Window x:Class="WpfBalls.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfBalls" 
    Title="3D WpfBalls" Height="400" Width="600"> 
    <Grid> 
     <Grid.Background> 
      <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> 
       <LinearGradientBrush.GradientStops> 
        <GradientStop Color="White" Offset="0"/> 
        <GradientStop Color="White" Offset="1"/> 
       </LinearGradientBrush.GradientStops> 
      </LinearGradientBrush> 
     </Grid.Background> 
     <Viewport3D x:Name="viewPort" Grid.Column="0" Grid.Row="0" ClipToBounds="False"> 
      <Viewport3D.Camera> 
       <PerspectiveCamera x:Name="camera" Position="0,0,-8" 
            UpDirection="0,1,0" LookDirection="0,0,1" 
            FieldOfView="25" NearPlaneDistance="0.125"/> 
      </Viewport3D.Camera> 
      <Viewport3D.Children> 
       <ModelVisual3D> 
        <ModelVisual3D.Content> 
         <AmbientLight Color="White" /> 
        </ModelVisual3D.Content> 
       </ModelVisual3D> 
       <ModelVisual3D x:Name="visualModel"> 

         <ModelVisual3D.Transform> 
         <Transform3DGroup> 
          <RotateTransform3D> 
           <RotateTransform3D.Rotation> 
            <AxisAngleRotation3D x:Name="rotationY" 
                  Angle="{Binding ElementName=sliderY,Path=Value}" Axis="0,1,0" /> 
           </RotateTransform3D.Rotation> 
          </RotateTransform3D> 
          <RotateTransform3D> 
           <RotateTransform3D.Rotation> 
            <AxisAngleRotation3D x:Name="rotationX" 
                  Angle="{Binding ElementName=sliderX,Path=Value}" Axis="1,0,0" /> 
           </RotateTransform3D.Rotation> 
          </RotateTransform3D> 
         </Transform3DGroup> 
        </ModelVisual3D.Transform> 

       </ModelVisual3D> 
      </Viewport3D.Children> 
     </Viewport3D> 
     <Slider Height="23" HorizontalAlignment="Left" Margin="25,23,0,0" Name="sliderX" Minimum="-70" Maximum="70" Value="0" VerticalAlignment="Top" Width="100" /> 
     <Slider Height="86" HorizontalAlignment="Left" Margin="25,52,0,0" Name="sliderY" Minimum="110" Maximum="250" Value="180" VerticalAlignment="Top" Width="27" Orientation="Vertical" /> 
    </Grid> 
</Window> 

球類代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Media.Media3D; 
using System.Windows; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 

namespace WpfBalls 
{ 
    public class Ball : ModelVisual3D 
    { 
     public Ball() 
     { 
      this.Content = new GeometryModel3D(); 
      (this.Content as GeometryModel3D).Geometry = Tessellate(); 

     } 

     static double DegToRad(double degrees) 
     { 
      return (degrees/180.0) * Math.PI; 
     } 

     internal Point3D GetPosition(double t, double y) 
     { 
      double r = Math.Sqrt(1 - y * y); 
      double x = r * Math.Cos(t); 
      double z = r * Math.Sin(t); 

      return new Point3D(x, y, z); 
     } 

     private Vector3D GetNormal(double t, double y) 
     { 
      return (Vector3D)GetPosition(t, y); 
     } 

     private Point GetTextureCoordinate(double t, double y) 
     { 
      Matrix TYtoUV = new Matrix(); 
      TYtoUV.Scale(1/(2 * Math.PI), -0.5); 

      Point p = new Point(t, y); 
      p = p * TYtoUV; 

      return p; 
     } 

     public string ImageSource 
     { 
      set { 

       DiffuseMaterial dm = new DiffuseMaterial(); 
       ImageSource imSrc = new 
        BitmapImage(new Uri(value, UriKind.RelativeOrAbsolute)); 
       dm.Brush = new ImageBrush(imSrc); 


       (this.Content as GeometryModel3D).Material = dm; 
      } 
     } 

     public Point3D Offset 
     { 
      set { 
       this.Transform = new 
        TranslateTransform3D(value.X, value.Y, value.Z); 
      } 
     } 

     internal Geometry3D Tessellate() 
     { 
      int tDiv =750; 
      int yDiv = 750; 
      double maxTheta = DegToRad(360); 
      double minY = -1.0; 
      double maxY = 1.0; 

      double dt = maxTheta/tDiv; 
      double dy = (maxY - minY)/yDiv; 

      MeshGeometry3D mesh = new MeshGeometry3D(); 

      for (int yi = 0; yi <= yDiv; yi++) 
      { 
       double y = minY + yi * dy; 

       for (int ti = 0; ti <= tDiv; ti++) 
       { 
        double t = ti * dt; 
        var p = GetPosition(t, y); 
        if (p.Z > 0 && p.X > -.5 && p.X < .5 && p.Y > -.5 && p.Y < .5) 
        { 
        mesh.Positions.Add(p); 
        mesh.Normals.Add(GetNormal(t, y)); 
        mesh.TextureCoordinates.Add(GetTextureCoordinate(t, y)); 
        } 

       } 
      } 

      for (int yi = 0; yi < yDiv; yi++) 
      { 
       for (int ti = 0; ti < tDiv; ti++) 
       { 
        int x0 = ti; 
        int x1 = (ti + 1); 
        int y0 = yi * (tDiv + 1); 
        int y1 = (yi + 1) * (tDiv + 1); 

        mesh.TriangleIndices.Add(x0 + y0); 
        mesh.TriangleIndices.Add(x0 + y1); 
        mesh.TriangleIndices.Add(x1 + y0); 

        mesh.TriangleIndices.Add(x1 + y0); 
        mesh.TriangleIndices.Add(x0 + y1); 
        mesh.TriangleIndices.Add(x1 + y1); 
       } 
      } 

      mesh.Freeze(); 
      return mesh; 
     } 
    } 
} 

的代碼是基於這個例子: http://www.codegod.de/WebAppCodeGod/wpf-3d-animations-and-textures-AID439.aspx

+0

您好,感謝您回答。這個例子很接近,但不是我想要達到的。我希望能夠在畫布周圍移動矩形圖像,但可以看到它在球體表面上的等距矩形投影。 (實際上畫布是解開的球體表面。)就像3D軟件包中的UVW貼圖一樣。請查看「HDR Light Studio」網站視頻,您將明白我需要實現哪種實時圖像失真。再次感謝。 – skokk 2010-11-17 14:34:35