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