2010-11-16 9 views
2

Je suis en train de réaliser la tâche suivante:Cartographie d'une image sur la sphère et revenir la projection équirectangulaire déballés

Imaginez 2: toile de dessin format 1. Je veux placer des images rectangulaires sur cette toile (coordonnées cartésiennes ..x, y) et comme je déplace l'image plus loin du centre de la toile (0,0) je veux obtenir la distorsion de l'image comme si elle glissait sur les normales de la sphère imaginaire. La logique que je crois est de convertir les coordonnées cartésiennes 2D (x, y) de l'image en coordonnées sphériques de latitude et longitude correspondantes, puis d'appliquer la projection équirectangulaire à la sphère et de renvoyer l'image avec la distorsion correspondante (comme si c'était un uvs déballé dans un logiciel de modélisation 3D).

Il existe une application appelée "HDR Light Studio" qui génère des images HDR équirectangulaires (lat/long) pour l'éclairage de scène 3D. Si vous regardez les vidéos sur leur site, vous comprendrez exactement quel type de distorsion d'image j'essaie d'atteindre.

S'il vous plaît donnez-moi de l'aide sur le sujet si vous le pouvez. J'ai cherché tout autour du net pour l'information mais pas de chance.

Merci à l'avance

Répondre

0

Si je comprends bien la question que vous devriez être en mesure d'obtenir le même effet en créant une partie d'une sphère et en utilisant l'image comme une texture. Au lieu de déplacer l'image, vous faites pivoter la sphère.

Code et XAML de la fenêtre principale:

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> 

Code de la classe de balle:

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; 
     } 
    } 
} 

Le code est basé sur cet exemple: http://www.codegod.de/WebAppCodeGod/wpf-3d-animations-and-textures-AID439.aspx

+0

Salut et merci pour votre répondre. L'exemple est proche mais pas exactement ce que j'essaie de réaliser. Je veux être capable de déplacer l'image rectangulaire autour de la toile mais voir la projection équirectangulaire de celle-ci sur la surface de la sphère. (En fait, la toile est la surface de la sphère non enveloppée ..) Tout comme une carte UVW dans un logiciel 3d. S'il vous plaît jeter un oeil à "HDR Light Studio" vidéos du site Web et vous comprendrez exactement quel type de distorsion de l'image en temps réel je dois atteindre. Merci encore. – skokk