diff --git a/renderer3/hrend/math.go b/renderer3/hrend/math.go index f4c2d56..1a796de 100644 --- a/renderer3/hrend/math.go +++ b/renderer3/hrend/math.go @@ -245,11 +245,6 @@ func (m *Mat44f) MultiplyPoint3(p Vec3f) (Vec3f, float32) { out.Y = p.X*m.Get(1, 0) + p.Y*m.Get(1, 1) + p.Z*m.Get(1, 2) + m.Get(1, 3) out.Z = p.X*m.Get(2, 0) + p.Y*m.Get(2, 1) + p.Z*m.Get(2, 2) + m.Get(2, 3) w := p.X*m.Get(3, 0) + p.Y*m.Get(3, 1) + p.Z*m.Get(3, 2) + m.Get(3, 3) - // out.X /= w - // if w != 1 { - // out.Y /= w - // out.Z /= w - // } return out, w } diff --git a/renderer3/hrend/render.go b/renderer3/hrend/render.go index 92c3641..dc86100 100644 --- a/renderer3/hrend/render.go +++ b/renderer3/hrend/render.go @@ -128,53 +128,34 @@ func TriangleFlat(fb *RenderBuffer, color uint, v0f Vec3f, v1f Vec3f, v2f Vec3f) } func TriangleTextured(fb *RenderBuffer, texture Framebuffer, intensity float32, v0v Vertex, v1v Vertex, v2v Vertex) { - // if ZClip(v0v.Pos, v1v.Pos, v2v.Pos) { - // return - // } // min, max boundsTLf, boundsBRf := ComputeBoundingBoxF(v0v.Pos, v1v.Pos, v2v.Pos) - // The triangle is fully out of bounds + // The triangle is fully out of bounds; we don't have a proper clipper, so this + // check still needs to be performed if boundsBRf.Y < 0 || boundsBRf.X < 0 || boundsTLf.X >= float32(fb.Width) || boundsTLf.Y >= float32(fb.Height) { //|| - //boundsBRf.Z < 0 || boundsTLf.Z > 1 { return } - // if boundsBRf.Z < 0 || boundsTLf.Z > 1 { - // //log.Print(boundsTLf, boundsBRf) - // return - // } v0 := v0v.Pos.ToVec2i() v1 := v1v.Pos.ToVec2i() v2 := v2v.Pos.ToVec2i() - //boundsTL, boundsBR := ComputeBoundingBox(v0, v1, v2) parea := EdgeFunctioni(v0, v1, v2) - // Disable back face culling + // Still draw back faces (assume someone else culls them) // if parea < 0 { + // log.Print("HEY", parea) // v1, v2 = v2, v1 // parea = EdgeFunctioni(v0, v1, v2) // } - if parea == 0 { + if parea <= 0 { return } boundsTL := Vec2i{ - X: int(max(boundsTLf.X, 0)), //0, float32(fb.Width))), - Y: int(max(boundsTLf.Y, 0)), //Clamp(boundsTLf.Y, 0, float32(fb.Height))), + X: int(max(boundsTLf.X, 0)), + Y: int(max(boundsTLf.Y, 0)), } boundsBR := Vec2i{ X: int(min(boundsBRf.X, float32(fb.Width-1))), Y: int(min(boundsBRf.Y, float32(fb.Height-1))), } - /*if boundsTL.Y < 0 { - boundsTL.Y = 0 - } - if boundsTL.X < 0 { - boundsTL.X = 0 - } - if boundsBR.Y >= int(fb.Height) { - boundsBR.Y = int(fb.Height - 1) - } - if boundsBR.X >= int(fb.Width) { - boundsBR.X = int(fb.Width - 1) - }*/ // Where to start our scanning pstart := Vec2i{boundsTL.X, boundsTL.Y} invarea := 1 / float32(parea) @@ -185,25 +166,6 @@ func TriangleTextured(fb *RenderBuffer, texture Framebuffer, intensity float32, w1_xi, w1_yi := EdgeIncrementi(v2, v0) w2_xi, w2_yi := EdgeIncrementi(v0, v1) - // //v0f := v0v.Pos - // parea := EdgeFunction(v0v.Pos, v1v.Pos, v2v.Pos) - // // Disable back face culling - // // if parea < 0 { - // // v1, v2 = v2, v1 - // // parea = EdgeFunctioni(v0, v1, v2) - // // } - // if parea == 0 { - // return - // } - // pstart := Vec3f{X: float32(boundsTL.X), Y: float32(boundsTL.Y)} - // invarea := 1 / float32(parea) - // w0_y := EdgeFunction(v1v.Pos, v2v.Pos, pstart) - // w1_y := EdgeFunction(v2v.Pos, v0v.Pos, pstart) - // w2_y := EdgeFunction(v0v.Pos, v1v.Pos, pstart) - // w0_xi, w0_yi := EdgeIncrement(v1v.Pos, v2v.Pos) - // w1_xi, w1_yi := EdgeIncrement(v2v.Pos, v0v.Pos) - // w2_xi, w2_yi := EdgeIncrement(v0v.Pos, v1v.Pos) - for y := uint(boundsTL.Y); y <= uint(boundsBR.Y); y++ { w0 := w0_y w1 := w1_y @@ -234,40 +196,23 @@ func TriangleTextured(fb *RenderBuffer, texture Framebuffer, intensity float32, } } -//func PerspectiveAndClip(//o * ObjectDef, screenmat *Mat44f, width int, height int) { - // Return true if the face should be culled func BackfaceCull(v1, v2, v3 Vec3f) bool { - return (v1.X-v2.X)*(v3.Y-v2.Y)-(v1.Y-v2.Y)*(v3.X-v2.X) >= 0 // This is what it essentially is // e1 := v1.Sub(&v2) // e2 := v1.Sub(&v3) // // If viewing front face, it should be pointing in the positive z direction // return e1.CrossProduct(e2).Z <= 0 // But we know we can just use x and y since this is post projection - - //l1 := f[2].Pos.Sub(&f[0].Pos) - //n := l1.CrossProduct(f[1].Pos.Sub(&f[0].Pos)) + return (v1.X-v2.X)*(v3.Y-v2.Y)-(v1.Y-v2.Y)*(v3.X-v2.X) >= 0 } -// func TriangleTextured(fb *RenderBuffer, texture Framebuffer, intensity float32, v0v Vertex, v1v Vertex, v2v Vertex) { -// func PerspectiveAndClip(infaces []Facef, matrix3d *Mat44f, outfaces []Facef) { -func PerspectiveAndClip(face Facef, matrix3d *Mat44f) []Facef { //, outfaces []Facef) { - //var facei = 0 +func PerspectiveAndClip(face Facef, matrix3d *Mat44f) []Facef { outfaces := make([]Facef, 0, 2) var sc Facef var w [3]float32 var d [3]float32 outers := make([]int, 0, 3) - // miny := float32(math.MaxFloat32) - // minyx := float32(math.MaxFloat32) - // minyi := 0 - //var modelmat Mat44f - //var intensity float32 - //modelmat.SetLookAt(&o.Pos, o.Pos.Add(&o.LookVec), &camup) - //modelmat.ScaleSelf(o.Scale) - //matrix3d := modelmat.Multiply(screenmat) - //for _, f := range infaces { for i := range 3 { sc[i] = face[i] sc[i].Pos, w[i] = matrix3d.MultiplyPoint3(face[i].Pos) @@ -275,15 +220,7 @@ func PerspectiveAndClip(face Facef, matrix3d *Mat44f) []Facef { //, outfaces []F if d[i] < 0 { outers = append(outers, i) } - // if sc[i].Pos.Y < miny || sc[i].Pos.Y < { - // miny = sc[i].Pos.Y - // minyi = i - // } - //miny = min(miny, sc[i].Pos.Y) - //minz = min(minz, sc[i].Pos.Z) - //maxz = max(maxz, sc[i].Pos.Z) } - // Just to test: reject any that have points outside. We don't clip if len(outers) > 0 { return outfaces @@ -297,7 +234,7 @@ func PerspectiveAndClip(face Facef, matrix3d *Mat44f) []Facef { //, outfaces []F } } // Backface culling: no need to do anything with triangles facing the wrong way - if !BackfaceCull(sc[0].Pos, sc[1].Pos, sc[2].Pos) { + if EdgeFunction(sc[0].Pos, sc[1].Pos, sc[2].Pos) <= 0 { outfaces = append(outfaces, sc) } //outfaces[facei] = sc @@ -308,28 +245,4 @@ func PerspectiveAndClip(face Facef, matrix3d *Mat44f) []Facef { //, outfaces []F // TODO: Now that we're here doing it like this, might as well remove faces // that are fully outside the other clipping zones. No need to do actual clipping... // just full rejections. This saves a BIT of processing... though not much - - // log.Print(o.Model.Faces[0][0].Pos, o.Model.Faces[0][1].Pos, o.Model.Faces[0][2].Pos) - // log.Print(sc[0].Pos, sc[1].Pos, sc[2].Pos) - // log.Print(matrix3d) - // for i := range 3 { - // // Perspective divide (?) and screen coord - // sc[i].Pos.ViewportSelf(width, height) - // } - // //log.Print(sc[0].Pos, sc[1].Pos, sc[2].Pos, matrix3d) - // if o.Lighting { - // l1 := f[2].Pos.Sub(&f[0].Pos) - // n := l1.CrossProduct(f[1].Pos.Sub(&f[0].Pos)) - // n = n.Normalize() - // // light = lookvec // use this for weird things - // intensity = n.MultSimp(&light) - // if intensity < 0 { - // intensity = 0 - // } - // intensity = (intensity + float32(*minlight)) / (1 + float32(*minlight)) - // } else { - // intensity = 1.0 - // } - // TriangleTextured(&rb, o.Texture, intensity, sc[0], sc[1], sc[2]) - //} } diff --git a/renderer3/main.go b/renderer3/main.go index c9030fc..5f5998c 100644 --- a/renderer3/main.go +++ b/renderer3/main.go @@ -32,26 +32,6 @@ func must(err error) { } } -// type ObjectDef struct { -// Model *hrend.ObjModel -// Texture hrend.Framebuffer // This needs to go somewhere else eventually! -// Pos hrend.Vec3f -// LookVec hrend.Vec3f -// Scale float32 -// Lighting bool -// } -// -// func NewObjectDef(model *hrend.ObjModel, texture hrend.Framebuffer) *ObjectDef { -// result := ObjectDef{ -// Model: model, -// Texture: texture, -// LookVec: hrend.Vec3f{X: 0, Y: 0, Z: -1}, -// Scale: 1, -// Lighting: true, -// } -// return &result -// } - func loadObject(name string) (*hrend.ObjModel, hrend.Framebuffer) { ofile := filepath.Join("../", name+".obj") tfile := filepath.Join("../", name+".jpg") @@ -102,25 +82,29 @@ func CameraInput(yaw, pitch float32) (float32, float32, hrend.Vec3f) { pitch = hrend.Clamp(pitch, LookLock, math.Pi-LookLock) newcamtrans := hrend.Vec3f{X: 0, Y: 0, Z: 0} + move := float32(Movement) + if rl.IsMouseButtonDown(rl.MouseButtonLeft) { + move *= 6 + } if rl.IsKeyDown(rl.KeyD) { - newcamtrans.X += Movement / Fps + newcamtrans.X += move / Fps } if rl.IsKeyDown(rl.KeyA) { - newcamtrans.X -= Movement / Fps + newcamtrans.X -= move / Fps } // Moving forward moves in the negative z direction, since we FACE // the -z axis (the camera does anyway) if rl.IsKeyDown(rl.KeyW) { - newcamtrans.Z -= Movement / Fps + newcamtrans.Z -= move / Fps } if rl.IsKeyDown(rl.KeyS) { - newcamtrans.Z += Movement / Fps + newcamtrans.Z += move / Fps } if rl.IsKeyDown(rl.KeySpace) { - newcamtrans.Y += Movement / Fps + newcamtrans.Y += move / Fps } if rl.IsKeyDown(rl.KeyLeftShift) { - newcamtrans.Y -= Movement / Fps + newcamtrans.Y -= move / Fps } // translate the new camera movement based on the yaw @@ -210,9 +194,8 @@ func main() { objects[len(objects)-1].Pos.Z -= 2 // These don't really change - var projection hrend.Mat44f //, viewport hrend.Mat44f + var projection hrend.Mat44f projection.SetProjection(float32(*fov), float32(Width)/float32(Height), NearClip, FarClip) - //viewport.SetViewportSimple(int(Width), int(Height), 1) //65535) var camera hrend.Mat44f var newcamtrans hrend.Vec3f @@ -234,7 +217,6 @@ func main() { camtrans = *camtrans.Add(&newcamtrans) _ = camera.SetCamera(&camtrans, yaw, pitch, &camup) screenmat := camera.Inverse().Multiply(&projection) - //screenmat = screenmat.Multiply(&viewport) rb.ResetZBuffer() for y := range Height { @@ -243,29 +225,18 @@ func main() { } } - //var faces []hrend.Facef //[3]hrend.Vertex var modelmat hrend.Mat44f var intensity float32 - //var minz = float32(math.MaxFloat32) - //var maxz = float32(-math.MaxFloat32) for _, o := range objects { // Create the final matrix modelmat.SetLookAt(&o.Pos, o.Pos.Add(&o.LookVec), &camup) modelmat.ScaleSelf(o.Scale) matrix3d := modelmat.Multiply(screenmat) for _, f := range o.Model.Faces { + // Generate the new amount of triangles for each face (could be clipped) for _, sc := range hrend.PerspectiveAndClip(f, matrix3d) { - // for i := range 3 { - // sc[i] = f[i] - // sc[i].Pos = matrix3d.MultiplyPoint3(f[i].Pos) - // minz = min(minz, sc[i].Pos.Z) - // maxz = max(maxz, sc[i].Pos.Z) - // } - // log.Print(o.Model.Faces[0][0].Pos, o.Model.Faces[0][1].Pos, o.Model.Faces[0][2].Pos) - // log.Print(sc[0].Pos, sc[1].Pos, sc[2].Pos) - // log.Print(matrix3d) for i := range 3 { - // Perspective divide (?) and screen coord + // Screen coord mapping sc[i].Pos.ViewportSelf(*width, *height) } //log.Print(sc[0].Pos, sc[1].Pos, sc[2].Pos, matrix3d) @@ -276,7 +247,7 @@ func main() { // light = lookvec // use this for weird things intensity = n.MultSimp(&light) if intensity < 0 { - intensity = 0 + intensity = 0 // Don't just not draw the triangle: it should be black } intensity = (intensity + float32(*minlight)) / (1 + float32(*minlight)) } else {