// NewModel creates a new model. func NewModel(id string, shaders sm.ShaderManager, textures tm.TextureManager) *Model { m := Model{ id: id, shaders: shaders, textures: textures, angle: 0.0, model: mgl32.Ident4(), camera: mgl32.Ident4(), projection: mgl32.Ident4(), } return &m }
// Define the vertex attributes for vertex positions and normals. // Make these match your application and vertex shader // You might also want to add colours and texture coordinates func NewTerrainWithSeed(seed int64, frequency, scale float32, colorTone mgl32.Vec4) *Terrain { return &Terrain{ seed, // Seed frequency, // Frequency scale, // NoiseScale colorTone, // Color Tone 0, // XSize: Set to zero because we haven't created the heightField array yet 0, // ZSize 4, // PerlinOctaves 1.0, // HeightScale 0, // VBOVertices 0, // VBOColors 0, // VBONormals 0, // VBOIndices []mgl32.Vec3{}, // Vertices []mgl32.Vec3{}, // Normals []mgl32.Vec3{}, // Colors []uint16{}, // Indices []float32{}, // Noise mgl32.Ident4(), // Model "Terrain", DRAW_POLYGONS, } }
func TestStackPushPopPeek(t *testing.T) { stack := NewTransformStack() if !stack.Peek().ApproxEqual(mgl32.Ident4()) { t.Errorf("Peek not working") } stack.Push(mgl32.HomogRotate3DY(mgl32.DegToRad(90))) if !stack.Peek().ApproxEqual(mgl32.HomogRotate3DY(mgl32.DegToRad(90))) { t.Errorf("Peek not working") } if stack.Len() != 2 { t.Errorf("Peek alters stack length") } pop, err := stack.Pop() if err != nil || !pop.ApproxEqual(mgl32.HomogRotate3DY(mgl32.DegToRad(90))) { t.Errorf("Pop is unsuccessful") } if stack.Len() != 1 { t.Errorf("Pop does not actually shorten stack") } _, err = stack.Pop() if err == nil { t.Errorf("Popping stack with 1 element does not return error as expected") } }
func onPaint(glctx gl.Context, sz size.Event) { glctx.Viewport(0, 0, sz.WidthPx, sz.HeightPx) glctx.ClearColor(0.5, 0.5, 0.5, 1) glctx.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) glctx.UseProgram(program) projectionMtx = mgl32.Perspective(45, float32(width)/float32(height), 0.1, 100) arcBallMtx := arcball.getMtx() glctx.UniformMatrix4fv(projection, projectionMtx[:]) glctx.UniformMatrix4fv(view, arcBallMtx[:]) glctx.BindBuffer(gl.ARRAY_BUFFER, triBuf) glctx.EnableVertexAttribArray(position) glctx.EnableVertexAttribArray(color) glctx.EnableVertexAttribArray(normals) vertSize := 4 * (coordsPerVertex + colorPerVertex + normalsPerVertex) glctx.VertexAttribPointer(position, coordsPerVertex, gl.FLOAT, false, vertSize, 0) glctx.VertexAttribPointer(color, colorPerVertex, gl.FLOAT, false, vertSize, 4*coordsPerVertex) glctx.VertexAttribPointer(normals, normalsPerVertex, gl.FLOAT, false, vertSize, 4*(coordsPerVertex+colorPerVertex)) glctx.DepthMask(true) glctx.Uniform3fv(lightPos, light.Pos[:]) glctx.Uniform3fv(lightIntensity, light.Intensities[:]) for _, k := range piano.Keys { glctx.Uniform4fv(tint, k.Color[:]) mtx := k.GetMtx() normMat := mtx.Mat3().Inv().Transpose() glctx.UniformMatrix3fv(normalMatrix, normMat[:]) glctx.UniformMatrix4fv(model, mtx[:]) glctx.DrawArrays(gl.TRIANGLES, 0, len(triangleData)/vertSize) } modelMtx := mgl32.Ident4() modelMtx = modelMtx.Mul4(mgl32.Translate3D(worldPos.X(), worldPos.Y(), worldPos.Z())) modelMtx = modelMtx.Mul4(mgl32.Scale3D(0.5, 0.5, 0.5)) /* glctx.Uniform4fv(tint, red[:]) // Disable depthmask so we dont get the pixel depth of the cursor cube glctx.DepthMask(false) glctx.UniformMatrix4fv(model, modelMtx[:]) glctx.DepthMask(true) */ glctx.DisableVertexAttribArray(position) glctx.DisableVertexAttribArray(color) glctx.DisableVertexAttribArray(normals) fps.Draw(sz) }
func (s *Scene) Draw(pass string, shader *render.ShaderProgram) { if s.Camera == nil { return } p := s.Camera.Projection v := s.Camera.View m := mgl.Ident4() vp := p.Mul4(v) // mvp := vp * m /* DrawArgs will be copied down recursively into the scene graph. * Each object adds its transformation matrix before passing * it on to their children */ args := render.DrawArgs{ Projection: p, View: v, VP: vp, MVP: vp, Transform: m, Pass: pass, Shader: shader, } s.DrawCall(args) }
func TestStackNew(t *testing.T) { stack := NewTransformStack() if !(*stack)[0].ApproxEqual(mgl32.Ident4()) { t.Errorf("Cannot construct stack correctly") } }
func NewCamera(worldCenter, worldSize mgl32.Vec3, screenSize mgl32.Vec2) (c *Camera, err error) { c = &Camera{ View: mgl32.Ident4(), } c.SetScreenSize(screenSize) err = c.SetWorldBounds(worldCenter, worldSize) return }
func Start(windowName string) error { err := llgl.InitDisplay(windowName) if err != nil { return err } err = llgl.InitGL() if err != nil { return err } glstate.program, err = loadShaders("cube.vert", "cube.frag") if err != nil { return err } glstate.program.Use() glstate.projectionUL = glstate.program.Uniform("projection") glstate.cameraUL = glstate.program.Uniform("camera") glstate.modelUL = glstate.program.Uniform("model") glstate.texUL = glstate.program.Uniform("tex") state.camera = mgl.LookAtV(mgl.Vec3{3, 3, 3}, mgl.Vec3{0, 0, 0}, mgl.Vec3{0, 1, 0}) state.model = mgl.Ident4() glstate.cameraUL.SetMat4(state.camera) glstate.modelUL.SetMat4(state.model) glstate.texUL.SetTextureSlot(0) glstate.program.BindFragDataLocation(0, "outputColor") texturePath, err := assets.Locate("code.png") if err != nil { return err } texture, err := llgl.MakeTexture(0, texturePath) if err != nil { return err } texture.Bind(0) // Configure the vertex data vao := llgl.NewVertexArray() vao.Bind() glstate.vbo = llgl.NewVertexBuffer() glstate.vbo.Bind() val := glstate.program.VertexAttrib("vert") val.Enable() val.PointerFloat32(3, 5, 0) valTC := glstate.program.VertexAttrib("vertTexCoord") valTC.Enable() valTC.PointerFloat32(2, 5, 3) fpsCounter = NewFpsCounter() return nil }
func NewCube(vertexPositions, vertexColours, normals *[]float32) *Cube { return &Cube{ 0, 0, 0, // bufferObject, normals, colours 0, // elementBuffer DRAW_POLYGONS, // drawmode vertexPositions, vertexColours, normals, // vertexPositions, vertexColours, normals mgl32.Ident4(), // model } }
func NewSphere(numLats, numLongs uint32) *Sphere { return &Sphere{ 0, 0, 0, // sphereBufferObject, sphereNormals, sphereColours 0, // elementBuffer DRAW_POLYGONS, // drawmode numLats, numLongs, // numLats, numLongs 0, // numSphereVertices mgl32.Ident4(), // model } }
/* Creates a new 2D transform */ func CreateTransform2D(x, y, z float32) *Transform2D { t := &Transform2D{ Matrix: mgl.Ident4(), Position: mgl.Vec3{x, y, z}, Scale: mgl.Vec2{1, 1}, Rotation: 0.0, } t.Update(0) return t }
/* Creates a new 3D transform */ func CreateTransform(x, y, z float32) *Transform { t := &Transform{ Matrix: mgl.Ident4(), Position: mgl.Vec3{x, y, z}, Rotation: mgl.Vec3{0, 0, 0}, Scale: mgl.Vec3{1, 1, 1}, } t.Update(0) return t }
// NewLimited returns a new instance of a LimitedCamera. func NewLimited(minZoom, maxZoom float32, minPos, maxPos float32) *LimitedCamera { cam := &LimitedCamera{ minZoom: minZoom, maxZoom: maxZoom, minPos: minPos, maxPos: maxPos, viewMatrix: mgl.Ident4()} return cam }
func NewCube(name string, vertexPositions, vertexColours, normals *[]float32, shaderManager *wrapper.ShaderManager) *Cube { return &Cube{ name, // Name 0, 0, 0, // bufferObject, normals, colours 0, // elementBuffer DRAW_POLYGONS, // drawmode vertexPositions, vertexColours, normals, // vertexPositions, vertexColours, normals mgl32.Ident4(), // model shaderManager, // Pointer to the Shader Manager } }
func (sceneGraph *SceneGraph) RenderScene(renderer Renderer, cameraLocation mgl32.Vec3) { //setup buckets sceneGraph.transparentBucket = sceneGraph.transparentBucket[:0] sceneGraph.buildBuckets(sceneGraph.transparentNode) sceneGraph.sortBuckets(renderer, cameraLocation) //render buckets sceneGraph.opaqueNode.Draw(renderer, mgl32.Ident4()) for _, entry := range sceneGraph.transparentBucket { renderEntry(entry, renderer) } }
func (m *Manager) Draw() { /* create draw event args */ p := m.Viewport v := mgl.Ident4() vp := p args := render.DrawArgs{ Projection: p, View: v, VP: vp, MVP: vp, Transform: mgl.Ident4(), } gl.Viewport(0, 0, int32(m.Width), int32(m.Height)) for _, el := range m.Children { el.Draw(args) } }
func NewSphere(name string, numLats, numLongs uint32, shaderManager *wrapper.ShaderManager) *Sphere { return &Sphere{ name, // Name 0, 0, 0, // sphereBufferObject, sphereNormals, sphereColours 0, // elementBuffer DRAW_POLYGONS, // drawmode numLats, numLongs, // numLats, numLongs 0, // numSphereVertices mgl32.Ident4(), // model mgl32.Vec4{}, // Position shaderManager, // Pointer to the Shader Manager } }
func (me *test) Display(c *Core) { me.o1.Draw(c) me.o2.Draw(c) projection := mgl32.Perspective(mgl32.DegToRad(Fov), float32(WindowWidth)/WindowHeight, Near, Far) view := mgl32.LookAtV(mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0}) model := mgl32.Ident4() MVP := projection.Mul4(view).Mul4(model) gl.UniformMatrix4fv(mvpLoc, 1, false, &MVP[0]) gl.Uniform1i(TexLoc, 0) }
func (k PianoKey) GetMtx() mgl32.Mat4 { axis := mgl32.Vec3{1, 0, 0} keyLen := float32(2.0) if !k.white { keyLen = 1.0 } modelMtx := mgl32.Ident4() modelMtx = modelMtx.Mul4(mgl32.Translate3D(k.Pos[0], k.Pos[1], k.Pos[2]-2)) modelMtx = modelMtx.Mul4(mgl32.HomogRotate3D(k.Angle, axis)) modelMtx = modelMtx.Mul4(mgl32.Translate3D(0, 0, keyLen)) modelMtx = modelMtx.Mul4(mgl32.Scale3D(0.5, 0.5, keyLen)) return modelMtx }
func NewCylinder(name string, vertices uint32, height, radius float32, shaderManager *wrapper.ShaderManager) *Cylinder { return &Cylinder{ name, // Name 0, 0, 0, // cylinderBufferObject, cylinderNormals, cylinderColours 0, // elementBuffer DRAW_POLYGONS, // DrawMode vertices, // VerticesPerDisk height, // Height radius, // Radius mgl32.Ident4(), // Model 0, // numCylinderVertices shaderManager, // Pointer to the Shader Manager } }
// NewTransform creates a new Transform struct with defaults. // The given multiplier can be used to invert the matrix, e.g. camera matrix // This value should be 1 or -1 (inverted). // // Position: 0,0,0 // Rotation: 0,0,0 // Scale: 1,1,1 // // Up: 0,1,0 // Right: 1,0,0 // Forward: 0,0,-1 func NewTransform() *Transform { return &Transform{ position: mgl32.Vec3{0, 0, 0}, rotation: mgl32.Vec3{0, 0, 0}, quaternion: mgl32.QuatIdent(), scale: mgl32.Vec3{1, 1, 1}, Up: mgl32.Vec3{0, 1, 0}, Right: mgl32.Vec3{1, 0, 0}, Forward: mgl32.Vec3{0, 0, -1}, matrix: mgl32.Ident4(), } }
// Render renders the bitmap with the center at given position func (renderable *SimpleBitmapRenderable) Render(context *RenderContext, icons []PlacedIcon) { gl := renderable.gl renderable.withShader(func() { renderable.setMatrix(renderable.viewMatrixUniform, context.ViewMatrix()) renderable.setMatrix(renderable.projectionMatrixUniform, context.ProjectionMatrix()) gl.EnableVertexAttribArray(uint32(renderable.vertexPositionAttrib)) gl.BindBuffer(opengl.ARRAY_BUFFER, renderable.vertexPositionBuffer) gl.VertexAttribOffset(uint32(renderable.vertexPositionAttrib), 3, opengl.FLOAT, false, 0, 0) gl.EnableVertexAttribArray(uint32(renderable.uvPositionAttrib)) gl.BindBuffer(opengl.ARRAY_BUFFER, renderable.uvPositionBuffer) gl.VertexAttribOffset(uint32(renderable.uvPositionAttrib), 3, opengl.FLOAT, false, 0, 0) textureUnit := int32(0) gl.ActiveTexture(opengl.TEXTURE0 + uint32(textureUnit)) gl.BindTexture(opengl.TEXTURE_2D, renderable.paletteTexture.Handle()) gl.Uniform1i(renderable.paletteUniform, textureUnit) textureUnit = 1 gl.ActiveTexture(opengl.TEXTURE0 + uint32(textureUnit)) gl.Uniform1i(renderable.bitmapUniform, textureUnit) for _, icon := range icons { x, y := icon.Center() u, v := icon.Icon().UV() width, height := renderable.limitedSize(icon) modelMatrix := mgl.Ident4(). Mul4(mgl.Translate3D(x, y, 0.0)). Mul4(mgl.Scale3D(width, height, 1.0)) renderable.setMatrix(renderable.modelMatrixUniform, &modelMatrix) var uv = []float32{ 0.0, 0.0, 0.0, u, 0.0, 0.0, u, v, 0.0, u, v, 0.0, 0.0, v, 0.0, 0.0, 0.0, 0.0} gl.BindBuffer(opengl.ARRAY_BUFFER, renderable.uvPositionBuffer) gl.BufferData(opengl.ARRAY_BUFFER, len(uv)*4, uv, opengl.STATIC_DRAW) gl.BindTexture(opengl.TEXTURE_2D, icon.Icon().Handle()) gl.DrawArrays(opengl.TRIANGLES, 0, 6) } gl.BindTexture(opengl.TEXTURE_2D, 0) }) }
// NewTextureRenderable returns a new instance of a texture renderable func NewTextureRenderable(gl opengl.OpenGl, positionX, positionY float32, displaySize float32, paletteTexture graphics.Texture, bitmapTexture graphics.Texture) *TextureRenderable { vertexShader, err1 := opengl.CompileNewShader(gl, opengl.VERTEX_SHADER, textureVertexShaderSource) defer gl.DeleteShader(vertexShader) fragmentShader, err2 := opengl.CompileNewShader(gl, opengl.FRAGMENT_SHADER, textureFragmentShaderSource) defer gl.DeleteShader(fragmentShader) program, _ := opengl.LinkNewProgram(gl, vertexShader, fragmentShader) if err1 != nil { fmt.Fprintf(os.Stderr, "Failed to compile shader 1:\n", err1) } if err2 != nil { fmt.Fprintf(os.Stderr, "Failed to compile shader 2:\n", err2) } renderable := &TextureRenderable{ gl: gl, program: program, modelMatrix: mgl.Ident4(). Mul4(mgl.Translate3D(positionX, positionY, 0.0)). Mul4(mgl.Scale3D(displaySize, displaySize, 1.0)), vertexArrayObject: gl.GenVertexArrays(1)[0], vertexPositionBuffer: gl.GenBuffers(1)[0], vertexPositionAttrib: gl.GetAttribLocation(program, "vertexPosition"), modelMatrixUniform: gl.GetUniformLocation(program, "modelMatrix"), viewMatrixUniform: gl.GetUniformLocation(program, "viewMatrix"), projectionMatrixUniform: gl.GetUniformLocation(program, "projectionMatrix"), paletteTexture: paletteTexture, paletteUniform: gl.GetUniformLocation(program, "palette"), bitmapTexture: bitmapTexture, bitmapUniform: gl.GetUniformLocation(program, "bitmap")} renderable.withShader(func() { gl.BindBuffer(opengl.ARRAY_BUFFER, renderable.vertexPositionBuffer) limit := float32(1.0) var vertices = []float32{ 0.0, 0.0, 0.0, limit, 0.0, 0.0, limit, limit, 0.0, limit, limit, 0.0, 0.0, limit, 0.0, 0.0, 0.0, 0.0} gl.BufferData(opengl.ARRAY_BUFFER, len(vertices)*4, vertices, opengl.STATIC_DRAW) }) return renderable }
func NewCog(name string, vertices uint32, height, radius, toothSize float32, shaderManager *wrapper.ShaderManager) *Cog { return &Cog{ name, // Name 0, 0, 0, // cogBufferObject, cogNormals, cogColours 0, // elementBuffer DRAW_POLYGONS, // DrawMode vertices, // VerticesPerDisk height, // Height radius, // Radius toothSize, // ToothSize mgl32.Ident4(), // Model 0, // numcogVertices shaderManager, // Pointer to the Shader Manager } }
func NewModelCollection(parts [][]*ModelVertex, c *ModelCollection) *Model { model := &Model{ c: c, BlockLight: 1.0, SkyLight: 1.0, } model.array = gl.CreateVertexArray() model.array.Bind() modelState.indexBuffer.Bind(gl.ElementArrayBuffer) model.buffer = gl.CreateBuffer() model.buffer.Bind(gl.ArrayBuffer) c.shader.Position.Enable() c.shader.TextureInfo.Enable() c.shader.TextureOffset.Enable() c.shader.Color.Enable() c.shader.ID.Enable() c.shader.Position.Pointer(3, gl.Float, false, 36, 0) c.shader.TextureInfo.Pointer(4, gl.UnsignedShort, false, 36, 12) c.shader.TextureOffset.PointerInt(3, gl.Short, 36, 20) c.shader.Color.Pointer(4, gl.UnsignedByte, true, 36, 28) c.shader.ID.PointerInt(4, gl.UnsignedByte, 36, 32) model.Matrix = make([]mgl32.Mat4, len(parts)) model.Colors = make([][4]float32, len(parts)) model.counts = make([]int32, len(parts)) model.offsets = make([]uintptr, len(parts)) var all []*ModelVertex for i, p := range parts { model.Matrix[i] = mgl32.Ident4() model.Colors[i] = [4]float32{1.0, 1.0, 1.0, 1.0} model.counts[i] = int32((len(p) / 4) * 6) model.offsets[i] = uintptr((len(all) / 4) * 6) for _, pp := range p { pp.id = byte(i) } all = append(all, p...) } model.Verts = all model.data() c.models = append(c.models, model) return model }
// Render writes vertex data of RenderObjects to opengl func (this *Renderer) Render(obj Opengl.RenderObject) { Model := mathgl.Ident4() Model = this.GetParent().transform.GetUpdatedModel() vData := obj.VertexData() for j := 0; j < vData.NumVerts(); j++ { x, y, z := vData.GetVertex(j) transformation := mathgl.Vec4{x, y, z, 1} if this.customTransform != nil { transformation = this.customTransform(transformation) } t := Model.Mul4x1(transformation) vData.SetVertex(j, t[0], t[1], t[2]) // set color if we have one if this.Color != nil { c := this.Color vData.SetColor(j, c.R, c.G, c.B, c.A) } // set normals for both model view and world (bump mapping and lighting) // world normal nX, nY, nZ := vData.GetWNormal(j) normalMat := Model.Mat3().Inv().Transpose() normal := normalMat.Mul3x1(mathgl.Vec3{nX, nY, nZ}).Normalize() vData.SetWNormal(j, normal.X(), normal.Y(), normal.Z()) // fmt.Println("Adding vdata in rend: ", vData) } // fmt.Println("Vertex Data: ", vData) // send OpenGLVertex info to Opengl module Opengl.AddVertexData(vData) }
// MultiMul multiplies every non-nil Mat4 reference and returns the result. If // none are given, then it returns the identity matrix. func MultiMul(matrices ...*mgl.Mat4) mgl.Mat4 { var r mgl.Mat4 ok := false for _, m := range matrices { if m == nil { continue } if !ok { r = *m ok = true continue } r = r.Mul4(*m) } if ok { return r } return mgl.Ident4() }
func CreateMesh(verticies []float32, texturePaths []string, shader *Shader) (*Mesh, error) { modelView := mgl32.Ident4() // // Load the texture textures := make([]uint32, 0) // fmt.Println(texturePaths) for _, texturePath := range texturePaths { // fmt.Println("Paths", texturePath, texturePaths[i]) texture, err := createTexture(texturePath) if err != nil { return nil, err } textures = append(textures, texture) } // // // Configure the vertex data var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) // var vbo uint32 gl.GenBuffers(1, &vbo) gl.BindBuffer(gl.ARRAY_BUFFER, vbo) gl.BufferData(gl.ARRAY_BUFFER, len(verticies)*4, gl.Ptr(verticies), gl.STATIC_DRAW) // gl.EnableVertexAttribArray(shader.attributes["vert"]) gl.VertexAttribPointer(shader.attributes["vert"], 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0)) // gl.EnableVertexAttribArray(shader.attributes["vertTexCoord"]) gl.VertexAttribPointer(shader.attributes["vertTexCoord"], 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4)) gl.BindVertexArray(0) gl.BindBuffer(gl.ARRAY_BUFFER, 0) return &Mesh{ modelView: modelView, textures: textures, verticies: verticies, vao: vao, vbo: vbo, }, nil }
func (objectLoader *WavefrontObject) CreateObject() { for _, object := range objectLoader.Objects { // Sets the Model in the Initial position object.Model = mgl32.Ident4() if wrapper.DEBUG { // Print the object fmt.Println(object) } // Generate the vertex buffer object gl.GenBuffers(1, &object.VertexBufferObjectVertices) gl.BindBuffer(gl.ARRAY_BUFFER, object.VertexBufferObjectVertices) gl.BufferData(gl.ARRAY_BUFFER, int(len(object.Vertex)*4), gl.Ptr(&(object.Vertex[0])), gl.STATIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) // Obj might not have normals if len(object.Normals) != 0 { // Store the normals in a buffer object gl.GenBuffers(1, &object.VertexBufferObjectNormals) gl.BindBuffer(gl.ARRAY_BUFFER, object.VertexBufferObjectNormals) gl.BufferData(gl.ARRAY_BUFFER, int(len(object.Normals)*4), gl.Ptr(&(object.Normals[0])), gl.STATIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) } // Generate a buffer for the indices gl.GenBuffers(1, &object.VertexBufferObjectFaces) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, object.VertexBufferObjectFaces) gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int(len(object.Faces)*3), gl.Ptr(&(object.Faces[0])), gl.STATIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) if len(object.Coordinates) != 0 { // Generate a buffer for the Texture Coordinates gl.GenBuffers(1, &object.VertexBufferObjectTextureCoords) gl.BindBuffer(gl.ARRAY_BUFFER, object.VertexBufferObjectTextureCoords) gl.BufferData(gl.ARRAY_BUFFER, int(len(object.Coordinates)*2)*2, gl.Ptr(&(object.Coordinates[0])), gl.STATIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, 0) } } }
// generateModelMatFromArgs will take in the arguments // x, y, r, sx, sy, ox, oy, kx, ky // and generate a matrix to be applied to the model transformation. func generateModelMatFromArgs(args []float32) *mgl32.Mat4 { x, y, angle, sx, sy, ox, oy, kx, ky := normalizeDrawCallArgs(args) mat := mgl32.Ident4() c := float32(math.Cos(float64(angle))) s := float32(math.Sin(float64(angle))) // matrix multiplication carried out on paper: // |1 x| |c -s | |sx | | 1 ky | |1 -ox| // | 1 y| |s c | | sy | |kx 1 | | 1 -oy| // | 1 | | 1 | | 1 | | 1 | | 1 | // | 1| | 1| | 1| | 1| | 1 | // move rotate scale skew origin mat[10] = 1 mat[15] = 1 mat[0] = c*sx - ky*s*sy // = a mat[1] = s*sx + ky*c*sy // = b mat[4] = kx*c*sx - s*sy // = c mat[5] = kx*s*sx + c*sy // = d mat[12] = x - ox*mat[0] - oy*mat[4] mat[13] = y - ox*mat[1] - oy*mat[5] return &mat }