Post by krotus on Apr 5, 2020 23:10:23 GMT
When I started this project, I knew that there would be more than spheres so I created a Primitive class that other shapes would inherit. One of the things that happens when a new shape is created is that it's given a numerical code to identify what kind of shape it is, and a unique integer ID, starting with 0 (for each kind of shape) and ascending from there. This code is working for any kind of shape.
But I'm having a problem implementing a plane.
All tests are passing up to "The normal of a plane is constant everywhere". (Page 122 of the book)
Here is the original NormalAt() functon from Chapter 6: (Page 82 of the book)
But I'm having a problem implementing a plane.
All tests are passing up to "The normal of a plane is constant everywhere". (Page 122 of the book)
Here is the original NormalAt() functon from Chapter 6: (Page 82 of the book)
Public Shared Function NormalAt(MyShape As Primitive, MyWorldPoint As Tuple(Of Double, Double, Double, Double)) As Tuple(Of Double, Double, Double, Double)
Dim result As Tuple(Of Double, Double, Double, Double)
Dim ObjectPoint As Tuple(Of Double, Double, Double, Double) = MyMath.MultiplyMatrixByTuple(MyMath.GetInvertedMatrix(MyShape.Transformation), MyWorldPoint)
'From page 86 of the book
Dim Position As Tuple(Of Double, Double, Double, Double) = New Tuple(Of Double, Double, Double, Double)(0, 0, 0, 1)
Dim ObjectNormal As Tuple(Of Double, Double, Double, Double) = MyMath.SubtractPointsAndVectors(ObjectPoint, Position)
Dim WorldNormal As Tuple(Of Double, Double, Double, Double) = MyMath.MultiplyMatrixByTuple(MyMath.TransposeMatrix(MyMath.GetInvertedMatrix(MyShape.Transformation)), ObjectNormal)
'Set the W of the WorldNormal vector to 0
WorldNormal = New Tuple(Of Double, Double, Double, Double)(WorldNormal.Item1, WorldNormal.Item2, WorldNormal.Item3, 0)
'Normalize the WorldNormal
result = MyMath.NormalizeVector(WorldNormal)
Return result
End Function
Now in Chapter 9, we're changing it: (Page 120 of the book)
Public Shared Function NormalAt(MyShape As Primitive, MyWorldPoint As Tuple(Of Double, Double, Double, Double)) As Tuple(Of Double, Double, Double, Double)
Dim result As Tuple(Of Double, Double, Double, Double)
Dim LocalPoint As Tuple(Of Double, Double, Double, Double) = MyMath.MultiplyMatrixByTuple(MyMath.GetInvertedMatrix(MyShape.Transformation), MyWorldPoint)
Dim LocalNormal As Tuple(Of Double, Double, Double, Double)
'Determine the primtive type
Select Case MyShape.Code
Case 0
LocalNormal = Sphere.GetLocalNormalOfPointAt(MyShape, LocalPoint)
Case 2
LocalNormal = Plane.GetLocalNormalOfPointAt(MyShape, LocalPoint)
End Select
Dim WorldNormal As Tuple(Of Double, Double, Double, Double) = MyMath.MultiplyMatrixByTuple(MyMath.TransposeMatrix(MyMath.GetInvertedMatrix(MyShape.Transformation)), LocalNormal)
'Reset the W of the WorldNormal vector to 0
WorldNormal = New Tuple(Of Double, Double, Double, Double)(WorldNormal.Item1, WorldNormal.Item2, WorldNormal.Item3, 0)
'Normalize the WorldNormal
result = MyMath.NormalizeVector(WorldNormal)
Return result
End Function
So the real difference is that the local normal is now created by the shape's LocalNormalAt() function. So what is this function supposed to do? According to the text, it "accepts a point in local (object) space, and returns the normal in the same space." How does it do that? We're passing it the shape and the local point. In the Chapter 6 version of NormalAt(), Position was subtracted from the ObjectPoint. In Chapter 9, ObjectPoint becomes LocalPoint. So if I pass the shape and LocalPoint to LocalNormalAt(), then I would be subtracting Position from LocalPoint. That works fine for a sphere since Position is point(0, 0, 0, 1) and the shape's position is also (0, 0, 0, 1):
Public Shared Function GetLocalNormalOfPointAt(MyShape As Sphere, MyLocalPoint As Tuple(Of Double, Double, Double, Double)) As Tuple(Of Double, Double, Double, Double)
Dim result As Tuple(Of Double, Double, Double, Double)
result = MyMath.SubtractPointsAndVectors(MyLocalPoint, MyShape.Position)
'Set W to 0
result = New Tuple(Of Double, Double, Double, Double)(result.Item1, result.Item2, result.Item3, 0)
Return result
End Function
but with a plane, if I use Position as point(0, 0, 0, 1), the vector comes out vector(0, 0, 0).
The first test for Plane shows that the local normal of a local point (point(0, 0, 0, 1)) should be vector(0, 1, 0) but how am I supposed to get that if all that LocalNormalAt() does is subtract Position from LocalPoint? What do you use for Position?
Since the plane is infinite in X and Z and passes through the origin, then Y should always be 0. But if every point on a plane has a vector of vector(0, 1, 0), am I supposed to calculate a Position so that any local point on the plane has that vector of vector(0, 1, 0)?