Bladeren bron

fixed camera up vector issue

Daniel Salvadori 7 jaren geleden
bovenliggende
commit
f752f81b1f
4 gewijzigde bestanden met toevoegingen van 58 en 107 verwijderingen
  1. 19 75
      camera/camera.go
  2. 2 0
      camera/control/orbit_control.go
  3. 2 9
      camera/perspective.go
  4. 35 23
      math32/matrix4.go

+ 19 - 75
camera/camera.go

@@ -36,24 +36,25 @@ func (cam *Camera) Initialize() {
 	cam.target.Set(0, 0, 0)
 	cam.up.Set(0, 1, 0)
 	cam.SetDirection(0, 0, -1)
-	cam.updateQuaternion()
-}
-
-// WorldDirection updates the specified vector with the
-// current world direction the camera is pointed
-func (cam *Camera) WorldDirection(result *math32.Vector3) {
-
-	var wpos math32.Vector3
-	cam.WorldPosition(&wpos)
-	*result = cam.target
-	result.Sub(&wpos).Normalize()
 }
 
 // LookAt sets the camera target position
+// TODO - maybe move to Node, or create similar in Node
 func (cam *Camera) LookAt(target *math32.Vector3) {
 
+	// This method does not support objects with rotated and/or translated parent(s)
+
 	cam.target = *target
-	cam.updateQuaternion()
+
+	var rotMat math32.Matrix4
+	pos := cam.Position()
+	rotMat.LookAt(&pos, &cam.target, &cam.up)
+	log.Error("pos = %v, target = %v", pos, cam.target)
+
+	var q math32.Quaternion
+	q.SetFromRotationMatrix(&rotMat)
+	cam.SetQuaternionQuat(&q)
+
 }
 
 // GetCamera satisfies the ICamera interface
@@ -78,74 +79,17 @@ func (cam *Camera) Up() math32.Vector3 {
 func (cam *Camera) SetUp(up *math32.Vector3) {
 
 	cam.up = *up
-}
-
-// SetPosition sets this camera world position
-// This method overrides the Node method to update
-// the camera quaternion, because changing the camera position
-// may change its rotation
-func (cam *Camera) SetPosition(x, y, z float32) {
-
-	cam.Node.SetPosition(x, y, z)
-	cam.updateQuaternion()
-}
-
-// SetPositionX sets this camera world position
-// This method overrides the Node method to update
-// the camera quaternion, because changing the camera position
-// may change its rotation
-func (cam *Camera) SetPositionX(x float32) {
-	cam.Node.SetPositionX(x)
-	cam.updateQuaternion()
-}
-
-// SetPositionY sets this camera world position
-// This method overrides the Node method to update
-// the camera quaternion, because changing the camera position
-// may change its rotation
-func (cam *Camera) SetPositionY(y float32) {
-	cam.Node.SetPositionY(y)
-	cam.updateQuaternion()
-}
-
-// SetPositionZ sets this camera world position
-// This method overrides the Node method to update
-// the camera quaternion, because changing the camera position
-// may change its rotation
-func (cam *Camera) SetPositionZ(z float32) {
-	cam.Node.SetPositionZ(z)
-	cam.updateQuaternion()
-}
-
-// SetPositionVec sets this node position from the specified vector pointer
-// This method overrides the Node method to update
-// the camera quaternion, because changing the camera position
-// may change its rotation
-func (cam *Camera) SetPositionVec(vpos *math32.Vector3) {
-
-	cam.Node.SetPositionVec(vpos)
-	cam.updateQuaternion()
+	cam.LookAt(&cam.target)
 }
 
 // ViewMatrix returns the current view matrix of this camera
 func (cam *Camera) ViewMatrix(m *math32.Matrix4) {
 
-	var wpos math32.Vector3
-	cam.WorldPosition(&wpos)
-	cam.viewMatrix.LookAt(&wpos, &cam.target, &cam.up)
-	*m = cam.viewMatrix
-}
-
-// updateQuaternion must be called when the camera position or target
-// is changed to update its quaternion.
-// This is important if the camera has children, such as an audio listener
-func (cam *Camera) updateQuaternion() {
-
-	var wdir math32.Vector3
-	cam.WorldDirection(&wdir)
-	var q math32.Quaternion
-	q.SetFromUnitVectors(&math32.Vector3{0, 0, -1}, &wdir)
-	cam.SetQuaternionQuat(&q)
+	matrixWorld := cam.MatrixWorld()
+	err := m.GetInverse(&matrixWorld)
+	if err != nil {
+		panic("Camera.ViewMatrix: Couldn't invert matrix")
+	}
 }
 
 // Project satisfies the ICamera interface and must

+ 2 - 0
camera/control/orbit_control.go

@@ -205,6 +205,7 @@ func (oc *OrbitControl) updateRotate() {
 	position = target
 	position.Add(&vdir)
 	oc.cam.SetPositionVec(&position)
+	oc.cam.LookAt(&target)
 
 	// Reset deltas
 	oc.thetaDelta = 0
@@ -251,6 +252,7 @@ func (oc *OrbitControl) updateRotate2() {
 	position.Add(&vdir)
 	log.Debug("orbit set position")
 	oc.cam.SetPositionVec(&position)
+	oc.cam.LookAt(&target)
 
 	// Reset deltas
 	oc.thetaDelta = 0

+ 2 - 9
camera/perspective.go

@@ -97,19 +97,12 @@ func (cam *Perspective) Project(v *math32.Vector3) (*math32.Vector3, error) {
 // Unproject transforms the specified position from camera projected coordinates to world coordinates.
 func (cam *Perspective) Unproject(v *math32.Vector3) (*math32.Vector3, error) {
 
-	// Get inverted camera view matrix
-	var viewMatrix math32.Matrix4
-	cam.ViewMatrix(&viewMatrix)
-	var invertedViewMatrix math32.Matrix4
-	err := invertedViewMatrix.GetInverse(&viewMatrix)
-	if err != nil {
-		return nil, err
-	}
+	invertedViewMatrix := cam.MatrixWorld()
 
 	// Get inverted camera projection matrix
 	cam.updateProjMatrix()
 	var invertedProjMatrix math32.Matrix4
-	err = invertedProjMatrix.GetInverse(&cam.projMatrix)
+	err := invertedProjMatrix.GetInverse(&cam.projMatrix)
 	if err != nil {
 		return nil, err
 	}

+ 35 - 23
math32/matrix4.go

@@ -211,29 +211,41 @@ func (m *Matrix4) MakeRotationFromQuaternion(q *Quaternion) *Matrix4 {
 // Returns pointer to this updated matrix.
 func (m *Matrix4) LookAt(eye, target, up *Vector3) *Matrix4 {
 
-	var f Vector3
-	var s Vector3
-	var u Vector3
-	f.SubVectors(target, eye).Normalize()
-	s.CrossVectors(&f, up).Normalize()
-	u.CrossVectors(&s, &f)
-
-	m[0] = s.X
-	m[1] = u.X
-	m[2] = -f.X
-	m[3] = 0.0
-	m[4] = s.Y
-	m[5] = u.Y
-	m[6] = -f.Y
-	m[7] = 0.0
-	m[8] = s.Z
-	m[9] = u.Z
-	m[10] = -f.Z
-	m[11] = 0.0
-	m[12] = -s.Dot(eye)
-	m[13] = -u.Dot(eye)
-	m[14] = f.Dot(eye)
-	m[15] = 1.0
+	var x, y, z Vector3
+
+	z.SubVectors(eye, target)
+	if z.LengthSq() == 0 {
+		// Eye and target are in the same position
+		z.Z = 1
+	}
+	z.Normalize()
+
+	x.CrossVectors(up, &z)
+	if x.LengthSq() == 0 {
+		// Up and Z are parallel
+		if Abs(up.Z) == 1 {
+			z.X += 0.0001
+		} else {
+			z.Z += 0.0001
+		}
+		z.Normalize()
+		x.CrossVectors(up, &z)
+	}
+	x.Normalize()
+
+	y.CrossVectors(&z, &x)
+
+	m[0] = x.X
+	m[1] = x.Y
+	m[2] = x.Z
+
+	m[4] = y.X
+	m[5] = y.Y
+	m[6] = y.Z
+
+	m[8] = z.X
+	m[9] = z.Y
+	m[10] = z.Z
 
 	return m
 }