Hallo,
seit ein paar Tagen stehe ich vor dem Problem, das ich ein Panel bzw Form in einer Art 3D darstellen möchte.
Im Anhang befindet sich eine Zeichnung, wie das zum Schluss einmal aussehen soll. Das Transformieren der Form selber gelingt mir schon mittels folgendem Code.
Matrix matrix = new Matrix();
matrix.Shear(0f, (float)-Math.Sin(sys_winkel * PI / 180));
e.Graphics.Transform = matrix;
Wenn ich jetzt allerdings Text auf die Graphic bringe, wird dieser Text zwar richtig mit verzerrt, aber die Proportionen stimmen nicht mehr mit dem Ursprung überein. Sprich der Text wird immer breiter gezogen.
Bei der "Form" selber konnte ich dieses Problem lösen, indem ich die Breite und die Höhe der "Form" neu berechnen lasse, aber bei einem Font ist mir das nicht gelungen.
Zur allgemeinen Info. Die Panel sollten wenn sie Fertig sind eine Maximale drehung von X-Richtung 315° und in Y-Richtung 35° haben. ("voller 3D Effect")
Kann mir jemand sagen, wie ich entweder den Text so angepasst bekomme, das die Proportionen beibehalten werden, oder wie ich das Problem anders angehen kann?
mfG Hans
Hallo,
ich hab nun noch mal das Forum durchstöbert und bin immer wieder auf D2D, Managed DirectX etc. gestoßen. Ich könnte mir vorstellen, das man das mit so einer Technik eventuell recht einfach lösen kann. Aber da ich in dem Bereich noch absolut keine Ahnung habe, kann mir bezogen auf mein Problem (siehe ersten Beitrag) eventuell jemand eine Hilfestellung, Beispielcode geben?
mfG Hans
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Hallo Gü,
danke für den Link zu diesem Projekt. Dieses Projekt hab ich mir auch schon mal nach langer Suche bei Google angeguckt, musste mich aber aufgrund meiner geringen Programmierkenntnisse geschlagen geben. Der Code war mir zu verschachtelt.
Ich vermute, das was mich intererssiet müsste sich in dem Bereich verstecken, wo die mit Vektoren und Matrizen rechen. Gibt es zu diesem Thema ein gutes deutsches Tutorial oder einen einfacheren Beispielcode?
Beim Suchen hab ich auch folgendes gefunden: www.vcskicks.com/image-distortion.php
Leider funkt das nur mit Bitmaps und dauert für meine Zwecke zu lange, da ich vom Verzerrten in die "Normalansicht" eine mehr oder weniger flüssige Bewegung anstrebe.
Kann mir eventuell jemand eines der Projekt soweit erklären, das ich sowas nachbauen kann?
Danke schon mal für eure Hilfe
mfG Hans
Hallo,
mal eine Zwischenfrage: Muss das mit WinForms erledigt werden? WPF würde hierzu bessere Unterstützung bieten. Siehe als Beispiel WPF Healthcare Sample.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Nein es muss nicht WindowsForm sein ... an sich ist es mir egal wie ich die Rechtecke zeichne, Hauptsache ich bekomm es irgendwie so gezeichnet, wie auf dem von mir angefügen Grafik aus dem Startbeitrag
Was allerdings noch gehen muss ist, das wenn ich mit der Maus über ein Recheck gehe, das es ein Event auslöst.
Hallo,
dann verwende WPF - auch das aus deinem letzten Post lässt sich dort leicht erledigen.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Hallo Gü.
nachdem ich mich nun durch zahlreiche Tutorials durchgearbeitet habe, konnte ich bis jetzt nur ein 3D Würfel aufbauen (Viewport3D), den ich im Raum drehen kann.
Aber wie bekommt man da jetzt ein Label etc auf die Textur gemappt?
Wie kann man die Ecken des Würfels sauber abrunden, wenn man das Objekt in Dreiecke aufbauen muss.
Gibt es eventuell eine Möglichekeit, ein Label, oder ähnliches so zu transformieren, das es dem entspricht, das ich mir vorstelle?
Hallo TheBrainiac,
das Abrunden von 2D Flächen wie Labels etc. ist nicht das Problem. Problem macht mir das Abrunden von Ecken in 3D Objekten wie Rechtecken etc.
Beim Label hab ich das Problem, das ich nicht weiß, wie ich das Label so Transformieren kann, das es anschließend so wie in der Grafik aus dem Startbeitrag aussieht.
Sieh dir mal die CodeProject-Beiträge von Sacha Barber an. Vielleicht findest du auf seiner WebSite auch was. Ich bin mir ziemlich sicher, dass ich sowas ähnliches von ihm schon einmal gesehen habe.
Gruß, Christian.
Hallo,
ich hab nun ein ganzes Wochenende versucht mein Vorhaben mittels WPF umzusetzen.
Als Vorbild habe ich mir folgendes Projekt genommen:
Marsa : A 3D Approach to XML read data
Wenn ich ein Objekt erstellen will klappt das auch wie in der Beispielanwendung. Aber wenn ich jedes Objekt um 45° drehen will, so das es wie in meiner Skizze aussieht, wird alles gedreht. Was dann so aussieht wie im Anhang.
Kann mir eventuell jemand ein Beispielcode zur verfügung stellen, wo realisiert ist, mehrere Objekte nebeneinander und jedes um 45° gedreht?
Danke für eure Hilfe
mfG Hans
Das Bild sieht aus als hättest du den Container mit deinen Elementen gedreht. Versuche stattdessen die Elemente einzeln zu drehen.
Das hier ist der Code, den ich aus dem Beispielprojekt rauskopiert habe und an dem ich die ganze Zeit versuche rum zu basteln. (mit wenig Erfolg)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;
using System.Windows.Threading;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Configuration;
namespace WpfApplication1
{
public partial class Window1 : Window
{
private const double MODEL_OFFSET = 1.05;
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
container.Children.Add(CreateModel("", 0, 0));
container.Children.Add(CreateModel("", 0, 1));
container.Children.Add(CreateModel("", 0, 2));
container.Children.Add(CreateModel("", 0, 3));
}
private ModelUIElement3D CreateModel(string imageUri, int row, int col)
{
ModelUIElement3D model3D = new ModelUIElement3D
{
Model = new GeometryModel3D
{
Geometry = new MeshGeometry3D
{
TriangleIndices = new Int32Collection(
new int[] { 0, 1, 2, 2, 3, 0 }),
TextureCoordinates = new PointCollection(
new Point[]
{
new Point(0, 1),
new Point(1, 1),
new Point(1, 0),
new Point(0, 0)
}),
Positions = new Point3DCollection(
new Point3D[]
{
new Point3D(-0.5, -0.5, 0),
new Point3D(0.5, -0.5, 0),
new Point3D(0.5, 0.5, 0),
new Point3D(-0.5, 0.5, 0)
})
},
Material = new DiffuseMaterial
{
Brush = Brushes.Orange
},
BackMaterial = new DiffuseMaterial
{
Brush = Brushes.Red
},
Transform = CreateGroup(row, col)
}
};
return model3D;
}
private Transform3DGroup CreateGroup(int row, int col)
{
Transform3DGroup group = new Transform3DGroup();
group.Children.Add(new TranslateTransform3D
{
OffsetX = col * MODEL_OFFSET,
OffsetY = row * -MODEL_OFFSET,
OffsetZ = 0.0
});
group.Children.Add(new RotateTransform3D
{
Rotation = new AxisAngleRotation3D
{
Angle = 45,
Axis = new Vector3D(0, 1, 0)
}
});
group.Children.Add(new ScaleTransform3D
{
ScaleX = 1.0,
ScaleY = 1.0,
ScaleZ = 1.0
});
return group;
}
}
}
Wo müsste ich hier die Drehung des Einzelobjektes ansetzen?
Das Problem ist das du alle Objekte um die gleiche Achse rotierst. Zumindest vermute ich das 😉.
ja das ist glaube ich auch so ... nur wie kann ich das ändern ... mir fehlt einfach das Wissen im WPF um das umzustellen.
Das hat mit WPF jetzt so direkt nix zu tun. Ist eher eine mathematische Aufgabe. Schau dir dazu mal den Code an den du da kopiert hast. Vor allem wie deine Objekte positioniert werden. Letzendlich musst du das ja nur hier mit einbringen:
Axis = new Vector3D(0, 1, 0)
ja an der Stelle dreht der einfach alles, egal was ich da bis jetzt eingefügt hatte
im Anhang kann man sehen, was geschieht, wenn ich versuche die Z Verschiebung zu kompensieren
Für mein dafürhalten, bräuchte ich einen Ansatz, wie ich das Objekt selber gedreht in die Gruppe plazieren kann. denn an der Stelle
Axis = new Vector3D(0, 1, 0)
ist es glaube ich schon zuspät.
Es müsste denke ich mal hier mit rein:
ModelUIElement3D model3D = new ModelUIElement3D
{
Model = new GeometryModel3D
{
Geometry = new MeshGeometry3D
{
TriangleIndices = new Int32Collection(
new int[] { 0, 1, 2, 2, 3, 0 }),
TextureCoordinates = new PointCollection(
new Point[]
{
new Point(0, 1),
new Point(1, 1),
new Point(1, 0),
new Point(0, 0)
}),
Positions = new Point3DCollection(
new Point3D[]
{
new Point3D(-0.5, -0.5, 0),
new Point3D(0.5, -0.5, 0),
new Point3D(0.5, 0.5, 0),
new Point3D(-0.5, 0.5, 0)
})
},
Material = new DiffuseMaterial
{
Brush = Brushes.Orange
},
BackMaterial = new DiffuseMaterial
{
Brush = Brushes.Red
},
Transform = CreateGroup(row, col)
}
};
nur wo und wie ist dann die Frage.
Nein, es gibt keine Gruppe der Rechtecke sondern die Eckpunkte werden als Gruppe genommen. Die Verschiebung (Translation) findet ja auch dort statt:
group.Children.Add(new TranslateTransform3D
{
OffsetX = col * MODEL_OFFSET,
OffsetY = row * -MODEL_OFFSET,
OffsetZ = 0.0
});
Versuche mal:
Axis = new Vector3D(0, 1 + col * MODEL_OFFSET, 0)
Hallo Lennart,
danke für deine Idee, aber das hat auch nicht das bezweckt, was ich / wir wollten.
An der Tatsache, das er die Gruppe gleichmäßg dreht, hat sich leider nichts geändert (siehe Bild).
Was passiert mit:
Axis = new Vector3D(col * MODEL_OFFSET, 1, 0)
daraus wird was ganz wildes.
Ich hab gestern auch versucht mit vielen Einstellungen an dieser Stelle etwas zu bewegen, aber nichts hat auch nur im Ansatz so ausgesehen, wie ich mir das vorgestellt habe.
Hallo Net_Hans,
also ich hab mir das ganze mal durchgelesen, und kann noch nicht so richtig erkennen, was du eigentlich vorhast. Bzw. was nicht so funktioniert, wie du es gerne hättest.
Wenn ich mir aber das erste Bild anschaue, das du gepostet hast, und deine jetztige Lösung, dann kann ich schonmal sagen, daß deine Transformation verkehrt ist.
Zuerst einmal sind die unterschiedlichen Transformationen in der falschen Reihenfolge. Die richtige Reihenfolge wäre:
Um die Rotation um eine bestimmte Achse durchzuführen, solltest du auch die Center*-Properties der ScaleTransform3D-Klasse setzen. Damit würdest du dir die Verschiebungen sparen.
Andererseits mußt du auch beachten, daß sich die Position der gedrehten Panels ändert, wenn sie am linken Rand so zusammenfallen sollen wie in deinem ersten Bild.
Schöne Grüße,
Christian
Weeks of programming can save you hours of planning
Hallo Christian,
danke für deine Ideen. Ich habe alles soweit angepasst, das es aus meiner Sicht mit deiner Idee übereinstimmt. aber das Ergebnis sieht wie im Beitrag zuvor aus:
Durch Zufall bin ich dann aber über die Kameraeinstellungen gestolpert.
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="528" Width="803">
<Grid Grid.Row="1" Grid.Column="0" x:Name="mainGrid">
<!-- Viewport3D -->
<Viewport3D x:Name="vp" Margin=" 0" >
<!-- Camera -->
<Viewport3D.Camera>
<PerspectiveCamera x:Name="camera" Position="3,0,5" LookDirection="0,0,-1" FieldOfView="90" />
</Viewport3D.Camera>
<!-- Lights -->
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<DirectionalLight Color="#444" Direction="0,0,-1" />
<AmbientLight Color="#BBB" />
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<!-- Container to hold child models -->
<ContainerUIElement3D x:Name="container">
<ContainerUIElement3D.Transform>
<Transform3DGroup>
<TranslateTransform3D x:Name="contTrans" OffsetX="0" OffsetY="0" OffsetZ="0"/>
<ScaleTransform3D ScaleX="1" ScaleY="1" ScaleZ="1"/>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="contAngle" Angle="0" Axis="0,1,0"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Transform3DGroup>
</ContainerUIElement3D.Transform>
</ContainerUIElement3D>
</Viewport3D>
<Button Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click">Button</Button>
</Grid>
</Window>
Ich befürchte jetzt sogar, das schon diese Einstellungen falsch sind.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;
using System.Windows.Threading;
using System.Threading;
using System.Diagnostics;
using System.IO;
namespace WpfApplication1
{
/// <summary>
/// Interaktionslogik für Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private const double MODEL_OFFSET = 1.05;
public Window1()
{
InitializeComponent();
}
private ModelUIElement3D CreateModel(string imageUri, int row, int col, Brush Farbe)
{
ModelUIElement3D model3D = new ModelUIElement3D
{
Model = new GeometryModel3D
{
Geometry = new MeshGeometry3D
{
TriangleIndices = new Int32Collection(
new int[] { 0, 1, 2, 2, 3, 0 }),
TextureCoordinates = new PointCollection(
new Point[]
{
new Point(0, 1),
new Point(1, 1),
new Point(1, 0),
new Point(0, 0)
}),
Positions = new Point3DCollection(
new Point3D[]
{
new Point3D(0, 0, 0),
new Point3D(1, 0, 0),
new Point3D(1, 1, 0),
new Point3D(0, 1, 0)
})
},
Material = new DiffuseMaterial
{
Brush = Farbe
},
BackMaterial = new DiffuseMaterial
{
Brush = Brushes.Black
},
Transform = CreateGroup(row, col)
}
};
return model3D;
}
private Transform3DGroup CreateGroup(int row, int col)
{
Transform3DGroup group = new Transform3DGroup();
group.Children.Add(new RotateTransform3D
{
Rotation = new AxisAngleRotation3D
{
Angle = 45,
Axis = new Vector3D(0, 1, 0)
}
});
group.Children.Add(new ScaleTransform3D
{
ScaleX = 1.0,
ScaleY = 1.0,
ScaleZ = 1.0
});
group.Children.Add(new TranslateTransform3D
{
OffsetX = col * MODEL_OFFSET,
OffsetY = row * -MODEL_OFFSET,
OffsetZ = 0.0
});
return group;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
container.Children.Add(CreateModel("", 1, 0, Brushes.Orange));
container.Children.Add(CreateModel("", 1, 1, Brushes.Orange));
container.Children.Add(CreateModel("", 1, 2, Brushes.Orange));
container.Children.Add(CreateModel("", 1, 3, Brushes.Orange));
container.Children.Add(CreateModel("", 1, 4, Brushes.Orange));
}
}
}
Damit ihr euch mal einen Gesamtüberblick über diesen Haufen Elend verschaffen könnnte, hab ich jetzt mal alles an Code in diesen Beitrag gepackt. Hoffe einer von euch blickt da besser durch als ich.
Hallo Net_Hans,
spiel mal an der Stelle am OffsetX rum. Z.B. nimm nur ein drittel vom MODEL_OFFSET
group.Children.Add(new TranslateTransform3D
{
OffsetX = col * MODEL_OFFSET / 3,
OffsetY = row * -MODEL_OFFSET,
OffsetZ = 0.0
});
Dabei hab ich folgendes Ergebnis erzielen können (Ich hab die Models eingefärbt das man die Überlappung besser sieht):
Hallo,
@riddick: danke für diesen Lösungsansatz.
Nachdem riddick mir seinen Lösungsansatz aufzeigte, hab ich mich noch einwenig mit dem Gesamtkonstruckt auseinander gesetzt und musste feststellen, das das Ganze noch komplexer ist als ich es erwartet hatte. Hier spielt alles zusammen ... Position der Camera ... Anzahl der Objekte, größe der Objekte und und und ...
vondaher werde ich mich mit dem Thema auch noch ein wenig mehr außeinander setzen müssen. Sobald ich eine für mich denkbare Lösung habe, werde ich sie hier veröffentlichen.
Danke noch mal an alle für Ihre Ideen und Ratschläge.
mfg Hans