Navigationslinks überspringen  
Navigationslinks überspringen

3DKamera

Um die richtige Ansicht einer Szene zu erhalten, werden in der 3D-Programmierung Kameras definiert, die die intuitiven Eigenschaften einer üblichen Kamera besitzen. wie z.B.: der Ort der Kamera, die Blickrichtung usw.

Definition der Camera-Komponente

In Drawing3D gibt es ein Komponente Camera die sämtliche Informationen kapselt, die für die Darstellung einer Szene erforderlich sind. Die Device entält eine Eigenschaft Camera. Da in ihr alle relevanten Informationen abgelegt sind, kann von einer bestimmten Ansicht einer Szene  die Camera kopiert und später wieder verwendet werden.

Die Klasse Camera enthält folgende Eigenschaften:
  • Base: Sie enthält die Basis der Kamera.
    Der Nullpunkt ist die Position der Kamera
    Die negative (!) Z-Achse ist die Blickichtung (Direction)
    Die Y-Achse ist die mit der Kamera verbundene Richtung nach oben (UpVector)
    Die X-Achse ergibt sich aus dem Vektorproduct BaseZ X BaseY
  • Direction:  Sie beinhaltet die Blickrichtung zu einer Szene und ist die Z-Achse der Camera.Base multipliziert mit -1.
  • UpVector:  Er enthält die mit der Kamera verbundene Richtung nach oben. Gespeichert ist dieser Vektor in Camera.Base.BaseY.
  • Position: Der Standort der Kamera ( Der Nullpunkt von Camera.Base).
  • Angles: Diese Eigenschaft enthält die drei Winkel Pitch, Roll und Yaw. Sie defineren eindeutig die Achsen von  Camera.Base.
    Pitch: Winkel, um den die Kamera nach oben bzw. nach unten gedreht ist ( Rotation um x-Achse).
    Roll : Winkel, um den die Kamera um die Blickrichtung ( Z- Achse ) gedreht ist. Dieser Winkel ist beschränkt auf das Interval [-PI/2, PI/2]
    Yaw: Winkel, um den die Kamera nach links bzw. nach rechts gedreht ist. ( Rotation um y-Achse).
    Diese Winkel beziehen sich auf ein inneres Bezugssystem einer Camera, das standardmäßig die Weltkoordinaten repräsentiert. Geändert werden kann dieses Bezugssystem durch die Methode SetRelativSystem(). Dadurch werden alle Winkel auf Null zurückgestellt. 
  • Yaw: x.Wert von Angles.
  • Pitch: y-Wert von Angles.
  • Roll; z-Wert von Angles.
  • Focus: Der Abstand von der Position zum Center-Punkt in Richtung der negativen z-Achse ( Direction).
  • Center: Werden die Winkel Pitch, Roll, Yaw verändert, so bleibt der Center-Punkt fix. Sind Position und Center-Punkt verschieden, so verändert sich die Position der Camera. Dies wird vor allem dann angewendet, wenn eine Szene von verschiedenen Seiten betrachtet wird. Es wird dabei der Center-Punkt in den Mittelpunkt der Szene gesetzt und die Winkel entsprechend verändert.
    Das Setzen des Center-Punkts geschieht über die Eigenschaft Focus.
  • ZoomFactor: Der Wert = 1 stellt die Szene in 100% Größe dar. Mit Device.PixelsPerUnit kann die Grundeinstellung vorgenommen werden.
  • FieldOfView: Der halbe Blickwinkel, bzw. Öffnungswinkel der Kamera (in Grad!). Bei einem Winkel von 0 Grad erscheint die Szene in Orthogonalprojection. Ist der Winkel sehr groß, z.B.: 90°, so entspricht das einem Weitwinkelobjektiv. Übliche Öffnungswinkel sind etwa 30°. Die Eigenschaft ist gleichgeschltet mit der Eigenschaft FieldOfView der Device.
  • Panning: Das Bild der Kamera wird um einen x-Wert und einen y-Wert in Pixel verschoben. In diesem Fall wandert auch der Blickpunkt, der üblicherweise im Mittelpunkt des Bildschirms ist.
  • NearClipping: Der Abstand von Position nach Direction von wo ein Klippen der Szene beginnt. Default is 1.
 
Und folgende Methoden:
  • Lookat(xyz CamerPosition, xyz CameraLookAt, xyz CameraUpVector).
    In vielen Fällen ist es nicht einfach die Kamera durch ihre Position, die Richtung und die Winkel festzulegen. Diese Winkel sind nützlich, wenn es sich um differentielle Änderungen handelt.
    Lookat wird meistens als erste Einstellung verwendet. Dasselbe Ergebnis erhält man wenn Device.ViewMatrix = Matrix.LookAt(..); setzt.
    Bemerkungen:
    1.
    Der Vektor CameraUpVector muss nicht genau rechtwinklig zur Blickrichtung sein, sondern lediglich in der Ebene, die aufgespannt ist durch die Blickrichtung und dem tatsächlichen UpVector der Kamera. Dieser wird automatisch korrigiert.
    2. Es ist günstig nach jedem Lookat auch ein SetRelativSystem() anzustoßen, wodurch die Angles auf Null zurückgestellt werden.
  • GoForward(doublw Trans): Versetzt die Position um den Trans vorwärts.
  • GoRight(double Delta): Versetzt die Position
  • GoUp(double Delta): Verschiebt die Position nach oben.
  • LookRight(double DeltaAngle): Verdreht die Kamera um die Y-Achse um den Winkel DeltaAngle. Dasselbe erhält man durch Pitch +=DeltaAngle.
  • LookDown(double DeltaAngle): Verdreht die Kamera um die X-Achse um den Winkel DeltaAngle. Dasselbe erhält man durch Yaw +=DeltaAngle.
  • LookRoll(double DeltaAngle): Verdreht die Kamera um die Z-Achse um den Winkel DeltaAngle. Dasselbe erhält man durch Roll +=DeltaAngle.
  • Mit Camera.Animated.RollRight,Camera.Animated.WalkForward,Camera.Animated.LookDown sind die entsprechenden Bewegungen aud animiert auszuführen.

  Und den Konstruktor Camera(MNDevice Device), wobei Device die Ausgabe festlegt.

Ein Beipiel sagt mehr als 1000 Worte:
( Bitte verwende mindestens Version 1.3)

Erstellen wir eine Szene mit einem roten, grünen, gelben und durchsichtigen blauen Quader. Zusätzlich zeichnen wir ein Netz zu besseren Veranschaulichung.

Also in die OnCeated-Methode:

          protected override void OnCreated()
        {
           
           base.OnCreated();
            BackColor = Color.DarkGray;
            Lights[0].Position = new xyz(-10, -5, 3);
            // Setzen des Blickwinkels : Perspektive
            FieldOfView = 30;
         
            Camera.ZoomFactor = 2;
            SnapEnable = false;
            Camera.LookAt(new xyz(-20, -10, 2), new xyz(0, 0, 2), new xyz(0, 0, 1));
            Camera.SetRelativeSystem();  
        }

Und in die Paint-Methode:

            public override void OnPaint()
        {
           base.OnPaint();
            // Draw a lightgray grid
          
           Emission = Color.LightGray;
            int Count = 100;
            double Distance = 2;
            for (int j = 0; j < Count; j++)
                drawLine(new xyz(-Count / 2 * Distance, j * Distance - Count / 2 * Distance, 0), new xyz(Count / 2 * Distance, j * Distance - Count / 2 * Distance, 0));
            for (int j = 0; j < Count; j++)
                drawLine(new xyz(j * Distance - Count / 2 * Distance, -Count / 2 * Distance, 0), new xyz(j * Distance - Count / 2 * Distance, Count / 2 * Distance, 0));


            Emission = Color.Black;
            // save the ambient material
            Color SaveAmbient = Ambient;

            // and draw four Boxes

            Ambient = Color.Red;
            drawBox(new xyz(-4, -1, 0), new xyz(4, 1, 2));

            Ambient = Color.Green;
            drawBox(new xyz(-2, 8, 0), new xyz(4, 2, 5));

            Ambient = Color.Yellow;
            drawBox(new xyz(7, 5, 0), new xyz(3, 4, 4));

            Translucent = 0.6;
            Ambient = Color.Blue;
            drawBox( new xyz(1, 1, 0), new xyz(4, 3, 6));
            Translucent = 1;

            Ambient = SaveAmbient;
          
        }
   

Dies sieht dann verkleinert so aus:

Beachte, dass die Position der Kamera standardmäßig bei (0,0,30) ist und die Direction bei (0,0,-1). Der Wert Focus ist bei 30, sodass der Nullpunkt bei Dehrungen immer fix bleibt.

Fügen wir nun eine andere Startposition der Kamera im Loadabschnitt ein.:

...
Device.Camera.LookAt(new xyz(-20, -10, 2), new xyz(0, 0, 2), new xyz(0, 0, 1)); 

...

Mit dem Ergebnis



Nun wird es aber Zeit, dass wir mit der Kamera etwas unternehmen:
Zunächst ins Form_load:
     // Keyevents
        KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
kopieren. Und in den Body von Form1 das Event
  private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Left:
                    xyz B = Device.Camera.Angles;
                    Device.Camera.Angles = new xyz(0.2, 0.3,0.4);
                    Device.Camera.Angles = B;
                    Device.Camera.Yaw = Device.Camera.Yaw - 0.1;
                    break;

                case Keys.Right:
                    Device.Camera.Yaw = Device.Camera.Yaw + 0.1;
                    break;

                case Keys.Up:
                    Device.Camera.Pitch = Device.Camera.Pitch + 0.1;
                    break;

                case Keys.Down:
                    Device.Camera.Pitch = Device.Camera.Pitch - 0.1;
                     break;

                case Keys.R: // Roll
                    if (Form.ModifierKeys == Keys.Shift)
                        Device.Camera.Roll = Device.Camera.Roll - 0.1;
                    else
                        Device.Camera.Roll = Device.Camera.Roll + 0.1;
                     break;

                case Keys.W:// Walk in Z-Axis 0.5
                    if (Form.ModifierKeys == Keys.Shift)
                        Device.Camera.GoForward(-0.5f);
                    else
                        Device.Camera.GoForward(0.5f);
              
                    break;

                case Keys.X: // X-Panning
                    {
                        
                        Point Panning = Device.Camera.Panning;
                        if (Form.ModifierKeys == Keys.Shift)
                            Device.Camera.Panning = new Point(Panning.X - 5, Panning.Y);
                        else
                            Device.Camera.Panning = new Point(Panning.X + 5, Panning.Y);
                      
                    }
                    break;

                case Keys.Y: // Y-Panning
                    {
                        Point Panning = Device.Camera.Panning;
                        if (Form.ModifierKeys == Keys.Shift)
                            Device.Camera.Panning = new Point(Panning.X, Panning.Y - 5);
                        else
                            Device.Camera.Panning = new Point(Panning.X, Panning.Y + 5);
                      
                    }
                    break;

                case Keys.N:// Walk in XY- Plane of camera in x-direction
                    if (Form.ModifierKeys == Keys.Shift)
                        Device.Camera.GoForward(-0.2f);
                    else
                        Device.Camera.GoForward(0.2f);
                  

                    break;

                case Keys.M:// Walk in XY- Plane of camera in y-direction
                    if (Form.ModifierKeys == Keys.Shift)
                        Device.Camera.GoRight( -0.2f);
                    else
                        Device.Camera.GoRight(0.2f);
                  

                    break;

                case Keys.Z: // Zooming
                    if (Form.ModifierKeys == Keys.Shift)
                        Device.Camera.ZoomFactor = 0.9 * Device.Camera.ZoomFactor;
                    else
                        Device.Camera.ZoomFactor =1.1* Device.Camera.ZoomFactor;
                   
                    break;
            }
        }

Viel Spaß bei der Reise durch die Welt der vier Quader.
Bemerkung:

 Die Standardnavigierung kann jetzt ausgeschaltet werden:
...
 //Device.Navigate = NavigateKind.ZoomRotateTrans;
...
Ein mögliches Ergebnis:

Codezusammenfassung

 
Copyright © Drawing3D inc