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