Laden...

Panel in 3D Optik [eigenes Usercontrol]

Erstellt von Net_Hans vor 13 Jahren Letzter Beitrag vor 13 Jahren 9.322 Views
N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren
Panel in 3D Optik [eigenes Usercontrol]

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

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo,

guck mal: A 3D Plotting Library in C#. Ev. hilft dir das weiter.

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

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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

6.911 Beiträge seit 2009
vor 13 Jahren

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

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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.

6.911 Beiträge seit 2009
vor 13 Jahren

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

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

Danke Gü,

dannn werde ich mich jetzt erst mal in das Thema einarbeiten.

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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?

795 Beiträge seit 2006
vor 13 Jahren
`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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.

795 Beiträge seit 2006
vor 13 Jahren

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.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

Kann man das Problem auch irgendwie ohne Viewport3D lösen?

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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

L
416 Beiträge seit 2008
vor 13 Jahren

Das Bild sieht aus als hättest du den Container mit deinen Elementen gedreht. Versuche stattdessen die Elemente einzeln zu drehen.

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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?

L
416 Beiträge seit 2008
vor 13 Jahren

Das Problem ist das du alle Objekte um die gleiche Achse rotierst. Zumindest vermute ich das 😉.

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

ja das ist glaube ich auch so ... nur wie kann ich das ändern ... mir fehlt einfach das Wissen im WPF um das umzustellen.

L
416 Beiträge seit 2008
vor 13 Jahren

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)

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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.

L
416 Beiträge seit 2008
vor 13 Jahren

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)

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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

L
416 Beiträge seit 2008
vor 13 Jahren

Was passiert mit:

Axis = new Vector3D(col * MODEL_OFFSET, 1, 0) 
N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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.

5.658 Beiträge seit 2006
vor 13 Jahren

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:

  • Verschiebung zum Nullpunkt
  • Skalierung
  • Rotation um den Nullpunkt
  • Verschiebung zurück an die ursprüngliche Rotation

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

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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.

R
16 Beiträge seit 2009
vor 13 Jahren

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

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

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