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()
}
Exemple #3
0
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
}