func (ps *ParticleSystem) SetUniforms() { ps.TransformLoc.Origin.Uniform3f(ps.Origin[0], ps.Origin[1], ps.Origin[2]) ps.TransformLoc.Gravity.Uniform1f(ps.Gravity) ps.TransformLoc.MaxLifetime.Uniform1f(ps.MaxLifetime) dirs := make([]float32, 64*3) for i := 0; i < 64; i++ { dir := mgl.Vec3{rand.Float32()*2 - 1, rand.Float32()*2 - 1, rand.Float32()*2 - 1} for dir.Len() > 1 { dir = mgl.Vec3{rand.Float32()*2 - 1, rand.Float32()*2 - 1, rand.Float32()*2 - 1} } dirs[i*3+0] = dir[0] dirs[i*3+1] = dir[1] dirs[i*3+2] = dir[2] } ps.TransformLoc.RandomDirs.Uniform3fv(64, dirs) }
func (m *HeightMap) Normal(x int, y int) mgl.Vec3 { l := x - 1 r := x + 1 b := y - 1 t := y + 1 hi := m.Get(x, y) lh := m.Get(l, y) - hi rh := m.Get(r, y) - hi bh := m.Get(x, b) - hi th := m.Get(x, t) - hi v1 := mgl.Vec3{1, 0, rh}.Normalize() v2 := mgl.Vec3{0, 1, th}.Normalize() v3 := mgl.Vec3{-1, 0, lh}.Normalize() v4 := mgl.Vec3{0, -1, bh}.Normalize() n1 := v1.Cross(v2).Normalize() n2 := v2.Cross(v3).Normalize() n3 := v3.Cross(v4).Normalize() n4 := v4.Cross(v1).Normalize() return n1.Add(n2).Add(n3).Add(n4).Normalize() }
func TriangleIntersection(V1, V2, V3, O, D mgl.Vec3) (out float32, hit bool) { const EPSILON = 0.000001 var e1, e2 mgl.Vec3 //Edge1, Edge2 var P, Q, T mgl.Vec3 var det, inv_det, u, v, t float32 //Find vectors for two edges sharing V1 e1 = V2.Sub(V1) e2 = V3.Sub(V1) //Begin calculating determinant - also used to calculate u parameter P = D.Cross(e2) //if determinant is near zero, ray lies in plane of triangle det = e1.Dot(P) //NOT CULLING if det > -EPSILON && det < EPSILON { return 0, false } inv_det = 1 / det //calculate distance from V1 to ray origin T = O.Sub(V1) //Calculate u parameter and test bound u = T.Dot(P) * inv_det //The intersection lies outside of the triangle if u < 0 || u > 1 { return 0, false } //Prepare to test v parameter Q = T.Cross(e1) //Calculate V parameter and test bound v = D.Dot(Q) * inv_det //The intersection lies outside of the triangle if v < 0 || u+v > 1 { return 0, false } t = e2.Dot(Q) * inv_det if t > EPSILON { //ray intersection return t, true } // No hit, no win return 0, false }
func NewParticleSystem(w *gamestate.World, numParticles int, Origin mgl.Vec3, initialSpeed, MaxLifetime float32) *ParticleSystem { vertices := make([]ParticleVertex, numParticles) directions := make([]NonTransformBuffer, numParticles) for i := range vertices { dir := mgl.Vec3{rand.Float32()*2 - 1, rand.Float32()*2 - 1, rand.Float32()*2 - 1} for dir.Len() > 1 { dir = mgl.Vec3{rand.Float32()*2 - 1, rand.Float32()*2 - 1, rand.Float32()*2 - 1} } dir = dir.Mul(initialSpeed) vertices[i] = ParticleVertex{ Pos1: Origin, Pos2: Origin.Sub(dir), Lifetime: rand.Float32() * MaxLifetime, } directions[i] = NonTransformBuffer{dir} } buffer1, buffer2, nonTransformBuffer := gl.GenBuffer(), gl.GenBuffer(), gl.GenBuffer() nonTransformBuffer.Bind(gl.ARRAY_BUFFER) gl.BufferData(gl.ARRAY_BUFFER, helpers.ByteSizeOfSlice(directions), directions, gl.STATIC_DRAW) buffer1.Bind(gl.ARRAY_BUFFER) gl.BufferData(gl.ARRAY_BUFFER, helpers.ByteSizeOfSlice(vertices), vertices, gl.STREAM_DRAW) buffer2.Bind(gl.ARRAY_BUFFER) gl.BufferData(gl.ARRAY_BUFFER, helpers.ByteSizeOfSlice(vertices), uintptr(0), gl.STREAM_DRAW) shapeData := CreateShapeDataBuffer() TransformProg := gl.CreateProgram() shader := helpers.MakeShader(gl.VERTEX_SHADER, "ParticleTFF.vs") TransformProg.AttachShader(shader) TransformProg.TransformFeedbackVaryings([]string{"v_Pos1", "v_Pos2", "v_Lifetime"}, gl.INTERLEAVED_ATTRIBS) TransformProg.Link() shader.Delete() TransformProg.Use() TransformLoc := ProgramLocations{} helpers.BindLocations("particle transform", TransformProg, &TransformLoc) renderProgram := helpers.MakeProgram("Particle.vs", "Particle.fs") renderProgram.Use() RenderLoc := RenderProgramLocations{} helpers.BindLocations("particle render", renderProgram, &RenderLoc) vaoTff1 := gl.GenVertexArray() vaoTff2 := gl.GenVertexArray() vaoRender1 := gl.GenVertexArray() vaoRender2 := gl.GenVertexArray() ps := ParticleSystem{ TransformProg: TransformProg, TransformLoc: TransformLoc, RenderProg: renderProgram, RenderLoc: RenderLoc, VaoTff1: vaoTff1, VaoTff2: vaoTff2, VaoRender1: vaoRender1, VaoRender2: vaoRender2, Data1: buffer1, Data2: buffer2, ShapeData: shapeData, NonTransformBuffer: nonTransformBuffer, NumParticles: numParticles, Origin: Origin, Gravity: -9.81 / 200, InitialSpeed: initialSpeed, MaxLifetime: MaxLifetime, } min_h, max_h := w.HeightMap.Bounds() W := float32(w.HeightMap.W) H := float32(w.HeightMap.H) TransformProg.Use() ps.SetUniforms() ps.SetVaos() TransformProg.Use() ps.TransformLoc.HeightMap.Uniform1i(constants.TextureHeightMap) ps.TransformLoc.LowerBound.Uniform3f(0, 0, min_h) ps.TransformLoc.UpperBound.Uniform3f(W, H, max_h) return &ps }