diff options
-rw-r--r-- | app.go | 7 | ||||
-rw-r--r-- | geometry.go | 5 | ||||
-rw-r--r-- | graphics.go | 71 | ||||
-rw-r--r-- | main.go | 6 | ||||
-rw-r--r-- | stl.go | 52 |
5 files changed, 89 insertions, 52 deletions
@@ -41,7 +41,8 @@ func newApp(stl *StlModel) App { glfw.WindowHint(glfw.Samples, 16) // anti-aliasing log.Println("Creating Window") - app.window, err = glfw.CreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, nil, nil) + app.window, err = glfw.CreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, + WINDOW_TITLE, nil, nil) if err != nil { panic(err) } @@ -58,7 +59,9 @@ func (application *App) handle() { // generate and set transformation trafo := application.homeTrafo - trafo = mgl32.HomogRotate3D(float32(glfw.GetTime()) * 0.4 * 6.282, mgl32.Vec3{0.1, 1, 0}).Mul4(trafo) // apply time-based rotation + trafo = mgl32.HomogRotate3D( + float32(glfw.GetTime()) * 0.4 * 6.282, + mgl32.Vec3{0.1, 1, 0}).Mul4(trafo) // apply time-based rotation application.graphics.setTrafo(trafo) } diff --git a/geometry.go b/geometry.go index 1fc516a..80420a6 100644 --- a/geometry.go +++ b/geometry.go @@ -58,7 +58,10 @@ func (s Surface) getHomeView() mgl32.Mat4 { // calculate and return transformation var trafo mgl32.Mat4 = mgl32.Ident4() - trafo = mgl32.Translate3D(-center.scalars[0], -center.scalars[1], -center.scalars[2]).Mul4(trafo) + trafo = mgl32.Translate3D( + -center.scalars[0], + -center.scalars[1], + -center.scalars[2]).Mul4(trafo) trafo = mgl32.Scale3D(zoom, zoom, zoom).Mul4(trafo) return trafo diff --git a/graphics.go b/graphics.go index fc195eb..a952e40 100644 --- a/graphics.go +++ b/graphics.go @@ -20,37 +20,43 @@ const ( // vertex shader to draw points VERTEX_SHADER = ` - #version 410 +#version 410 - in vec3 vp_model; // vertex position in model coordinate system - in vec3 vn_model; // vertex normal in model coordinate system +in vec3 vp_model; // vertex position in model coordinate system +in vec3 vn_model; // vertex normal in model coordinate system - uniform mat4 trafo; // one single transformation matrix +uniform mat4 trafo; // one single transformation matrix - out vec3 vn_eye; // vertex normal in eye coordinate system +out vec3 vn_eye; // vertex normal in eye coordinate system - void main() { - vn_eye = vec3(trafo * vec4(vn_model, 0.0)); // 0.0 because translation is ignored - gl_Position = trafo * vec4(vp_model, 1.0); - } - ` + "\x00" +void main() { + + // 0.0 because translation is ignored + vn_eye = vec3(trafo * vec4(vn_model, 0.0)); + + gl_Position = trafo * vec4(vp_model, 1.0); + +} + ` + "\x00" // fragment shader to draw surfaces FRAGMENT_SHADER = ` - #version 410 +#version 410 - in vec3 vn_eye; // vertex normal in eye coordinate system +in vec3 vn_eye; // vertex normal in eye coordinate system - out vec4 frag_colour; +out vec4 frag_colour; - void main() { - vec3 ambient = vec3(0.3, 0.3, 0.3); // ambient colour is static - vec3 light_vector_eye = vec3(1.0, 0.1, -1.0); - vec3 diffuse = (vec3(1, 1, 1) - ambient) * max(dot(normalize(vn_eye), normalize(light_vector_eye)), 0.0); - vec3 color = (ambient + diffuse) * vec3(0, 0, 1); // hard-coded vector is color in RGB format - frag_colour = vec4(color, 1.0); // RGBA color format - } - ` + "\x00" +void main() { + vec3 ambient = vec3(0.3, 0.3, 0.3); // ambient colour is static + vec3 light_vector_eye = vec3(1.0, 0.1, -1.0); + vec3 diffuse = (vec3(1, 1, 1) - ambient) * max(dot(normalize(vn_eye), + normalize(light_vector_eye)), 0.0); + // hard-coded vector is color in RGB format: + vec3 color = (ambient + diffuse) * vec3(0, 0, 1); + frag_colour = vec4(color, 1.0); // RGBA color format +} + ` + "\x00" ) type Graphics struct { @@ -83,7 +89,8 @@ func newGraphics() Graphics { if err != nil { log.Fatal(err) } - graphics.fragmentShader, err = compileShader(FRAGMENT_SHADER, gl.FRAGMENT_SHADER) + graphics.fragmentShader, err = compileShader(FRAGMENT_SHADER, + gl.FRAGMENT_SHADER) if err != nil { log.Fatal(err) } @@ -99,8 +106,6 @@ func newGraphics() Graphics { graphics.vao = makeVao(vertices, vertex_normals) // create transformation matrix - //graphics.trafo = mgl32.HomogRotate3D(float32(glfw.GetTime()) * OMEGA, mgl32.Vec3{ROT_X, ROT_Y, ROT_Z}) - //graphics.trafoUniform = gl.GetUniformLocation(graphics.program, gl.Str("trafo\x00")) gl.UniformMatrix4fv(graphics.trafoUniform, 1, false, &graphics.trafo[0]) return graphics @@ -110,11 +115,13 @@ func (graphics Graphics) draw() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.UseProgram(graphics.program) - //graphics.trafo = mgl32.HomogRotate3D(float32(glfw.GetTime()) * OMEGA, mgl32.Vec3{ROT_X, ROT_Y, ROT_Z}) gl.UniformMatrix4fv(graphics.trafoUniform, 1, false, &graphics.trafo[0]) gl.BindVertexArray(graphics.vao) - gl.DrawArrays(gl.TRIANGLES, 0, int32(len(vertices)/3)) // POINTS, LINES, LINE_STRIP, LINE_LOOP, TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN + + // or alternatively POINTS, LINES, LINE_STRIP, LINE_LOOP, TRIANGLES, + // TRIANGLE_STRIP, TRIANGLE_FAN + gl.DrawArrays(gl.TRIANGLES, 0, int32(len(vertices)/3)) } // makeVao initializes and returns a vertex array from the points provided. @@ -125,13 +132,15 @@ func makeVao(points []float32, normals []float32) uint32 { var position_vbo uint32 // VBO ID gl.GenBuffers(1, &position_vbo) gl.BindBuffer(gl.ARRAY_BUFFER, position_vbo) - gl.BufferData(gl.ARRAY_BUFFER, 4*len(points), gl.Ptr(points), gl.STATIC_DRAW) + gl.BufferData(gl.ARRAY_BUFFER, 4*len(points), gl.Ptr(points), + gl.STATIC_DRAW) // vertex buffer object (VBO) for normals: var normal_vbo uint32 // VBO ID gl.GenBuffers(1, &normal_vbo) gl.BindBuffer(gl.ARRAY_BUFFER, normal_vbo) - gl.BufferData(gl.ARRAY_BUFFER, 4*len(normals), gl.Ptr(normals), gl.STATIC_DRAW) + gl.BufferData(gl.ARRAY_BUFFER, 4*len(normals), gl.Ptr(normals), + gl.STATIC_DRAW) // vertex array objects (VAO) to combine VBOs: var vao uint32 // VAO ID @@ -140,12 +149,14 @@ func makeVao(points []float32, normals []float32) uint32 { // connect position_vbo to vao gl.BindBuffer(gl.ARRAY_BUFFER, position_vbo) - gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, nil) // tell GL to use 3D float vectors + // tell GL to use 3D float vectors: + gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, nil) gl.EnableVertexAttribArray(0) // connect normal_vbo to vao gl.BindBuffer(gl.ARRAY_BUFFER, normal_vbo) - gl.VertexAttribPointer(1, 3, gl.FLOAT, false, 0, nil) // tell GL to use 3D float vectors + // tell GL to use 3D float vectors: + gl.VertexAttribPointer(1, 3, gl.FLOAT, false, 0, nil) gl.EnableVertexAttribArray(1) return vao @@ -30,7 +30,8 @@ func main() { } vertices,vertex_normals = stl.toVertices() - // lock this program to one OS thread (details: https://golang.org/pkg/runtime/#LockOSThread) + // lock this program to one OS thread + // (details: https://golang.org/pkg/runtime/#LockOSThread) log.Println("Locking OS thread") runtime.LockOSThread() @@ -50,7 +51,8 @@ func main() { } func (args *cliArgs) read() { - flag.BoolVar(&args.debugOutput, "debug", false, "enable to print log output") + flag.BoolVar(&args.debugOutput, "debug", false, + "enable to print log output") flag.Parse() args.filePath = flag.Arg(0) } @@ -50,8 +50,11 @@ func ReadBinaryStlFile(filePath string) (StlModel, error) { return model,nil } -// parse the 50 bytes of the STL file representing a triangle (surface normal is ignored) -func ParseBinaryStlTriangle(data []byte) *Triangle { // FIXME: This function should only accept 50 byte slices/arrays +// parse the 50 bytes of the STL file representing a triangle (surface normal +// is ignored) +func ParseBinaryStlTriangle(data []byte) *Triangle { + + // FIXME: This function should only accept 50 byte slices/arrays // allocate a new triangle and three corner points on the heap triangle := new(Triangle) @@ -60,24 +63,34 @@ func ParseBinaryStlTriangle(data []byte) *Triangle { // FIXME: This function sh triangle.points[2] = new(Point) // parse x, y and z coordinate for corner point a - triangle.points[0].scalars[0] = math.Float32frombits(binary.LittleEndian.Uint32(data[12:16])) - triangle.points[0].scalars[1] = math.Float32frombits(binary.LittleEndian.Uint32(data[16:20])) - triangle.points[0].scalars[2] = math.Float32frombits(binary.LittleEndian.Uint32(data[20:24])) + triangle.points[0].scalars[0] = math.Float32frombits( + binary.LittleEndian.Uint32(data[12:16])) + triangle.points[0].scalars[1] = math.Float32frombits( + binary.LittleEndian.Uint32(data[16:20])) + triangle.points[0].scalars[2] = math.Float32frombits( + binary.LittleEndian.Uint32(data[20:24])) // parse x, y and z coordinate for corner point b - triangle.points[1].scalars[0] = math.Float32frombits(binary.LittleEndian.Uint32(data[24:28])) - triangle.points[1].scalars[1] = math.Float32frombits(binary.LittleEndian.Uint32(data[28:32])) - triangle.points[1].scalars[2] = math.Float32frombits(binary.LittleEndian.Uint32(data[32:36])) + triangle.points[1].scalars[0] = math.Float32frombits( + binary.LittleEndian.Uint32(data[24:28])) + triangle.points[1].scalars[1] = math.Float32frombits( + binary.LittleEndian.Uint32(data[28:32])) + triangle.points[1].scalars[2] = math.Float32frombits( + binary.LittleEndian.Uint32(data[32:36])) // parse x, y and z coordinate for corner point c - triangle.points[2].scalars[0] = math.Float32frombits(binary.LittleEndian.Uint32(data[36:40])) - triangle.points[2].scalars[1] = math.Float32frombits(binary.LittleEndian.Uint32(data[40:44])) - triangle.points[2].scalars[2] = math.Float32frombits(binary.LittleEndian.Uint32(data[44:48])) + triangle.points[2].scalars[0] = math.Float32frombits( + binary.LittleEndian.Uint32(data[36:40])) + triangle.points[2].scalars[1] = math.Float32frombits( + binary.LittleEndian.Uint32(data[40:44])) + triangle.points[2].scalars[2] = math.Float32frombits( + binary.LittleEndian.Uint32(data[44:48])) return triangle } -func (stl StlModel) toVertices() (vertex_position []float32, vertex_normal []float32) { +func (stl StlModel) toVertices() (vertex_position []float32, + vertex_normal []float32) { vertex_position = make([]float32, stl.numberOfTriangles * 9) vertex_normal = make([]float32, stl.numberOfTriangles * 9) @@ -90,20 +103,25 @@ func (stl StlModel) toVertices() (vertex_position []float32, vertex_normal []flo for scalarIndex,scalar := range(point.scalars) { - vertex_position[triangleIndex*9+pointIndex*3+scalarIndex] = scalar + i := triangleIndex * 9 + pointIndex * 3 + scalarIndex + vertex_position[i] = scalar } } // calculate normal - point0 = Vector3{triangle.points[0].scalars[0], triangle.points[0].scalars[1], triangle.points[0].scalars[2]} - point1 = Vector3{triangle.points[1].scalars[0], triangle.points[1].scalars[1], triangle.points[1].scalars[2]} - point2 = Vector3{triangle.points[2].scalars[0], triangle.points[2].scalars[1], triangle.points[2].scalars[2]} + point0 = Vector3{triangle.points[0].scalars[0], + triangle.points[0].scalars[1], triangle.points[0].scalars[2]} + point1 = Vector3{triangle.points[1].scalars[0], + triangle.points[1].scalars[1], triangle.points[1].scalars[2]} + point2 = Vector3{triangle.points[2].scalars[0], + triangle.points[2].scalars[1], triangle.points[2].scalars[2]} edge0 = point1.subtract(point0) edge1 = point2.subtract(point1) normal = edge0.crossProduct(edge1) - normal.divideScalar(2.0) // length of normal vector corresponds to triangle area + normal.divideScalar(2.0) // length of normal vector corresponds to + // triangle area // save normal to each vertex of the triangle for i := 0; i<3; i++ { |