Ejemplo n.º 1
0
func tween(a, b mgl32.Vec2) (x, y float32) {
	v := b.Sub(a)
	v = v.Mul(0.5)
	v = a.Add(v)

	return v.Elem()
}
Ejemplo n.º 2
0
/** Calculate line boundary points.
 *
 * Sketch:
 *
 *     uh1___uh2
 *      .'   '.
 *    .'   q   '.
 *  .'   '   '   '.
 *.'   '  .'.  '   '.
 *   '  .' ul'.  '
 * p  .'       '.  r
 *
 *
 * ul can be found as above, uh1 and uh2 are much simpler:
 *
 * uh1 = q + ns * w/2, uh2 = q + nt * w/2
 */
func (polyline *polyLine) renderBevelEdge(sleeve, current, next mgl32.Vec2) {
	t := next.Sub(current)
	len_t := t.Len()

	det := determinant(sleeve, t)
	if mgl32.Abs(det)/(sleeve.Len()*len_t) < LINES_PARALLEL_EPS && sleeve.Dot(t) > 0 {
		// lines parallel, compute as u1 = q + ns * w/2, u2 = q - ns * w/2
		n := getNormal(t, polyline.halfwidth/len_t)
		polyline.normals = append(polyline.normals, n)
		polyline.normals = append(polyline.normals, n.Mul(-1))
		polyline.generateEdges(current, 2)
		return // early out
	}

	// cramers rule
	sleeve_normal := getNormal(sleeve, polyline.halfwidth/sleeve.Len())
	nt := getNormal(t, polyline.halfwidth/len_t)
	lambda := determinant(nt.Sub(sleeve_normal), t) / det
	d := sleeve_normal.Add(sleeve.Mul(lambda))

	if det > 0 { // 'left' turn -> intersection on the top
		polyline.normals = append(polyline.normals, d)
		polyline.normals = append(polyline.normals, sleeve_normal.Mul(-1))
		polyline.normals = append(polyline.normals, d)
		polyline.normals = append(polyline.normals, nt.Mul(-1))
	} else {
		polyline.normals = append(polyline.normals, sleeve_normal)
		polyline.normals = append(polyline.normals, d.Mul(-1))
		polyline.normals = append(polyline.normals, nt)
		polyline.normals = append(polyline.normals, d.Mul(-1))
	}
	polyline.generateEdges(current, 4)
}
Ejemplo n.º 3
0
func (c *Container) mouseClick(button int, release bool, position mgl32.Vec2) {
	offsetPos := position.Sub(c.offset)
	c.Hitbox.MouseClick(button, release, offsetPos.Sub(c.backgroundOffset))
	for _, child := range c.children {
		child.mouseClick(button, release, offsetPos.Sub(c.elementsOffset))
	}
}
Ejemplo n.º 4
0
func (c *Container) mouseMove(position mgl32.Vec2) {
	offsetPos := position.Sub(c.offset)
	c.Hitbox.MouseMove(offsetPos.Sub(c.backgroundOffset))
	for _, child := range c.children {
		child.mouseMove(offsetPos.Sub(c.elementsOffset))
	}
}
Ejemplo n.º 5
0
func SegmentCircleIntersect(radius float32, center, start, finish mgl32.Vec2) (mgl32.Vec2, error) {
	d := finish.Sub(start)
	f := start.Sub(center)

	a := d.Dot(d)
	b := f.Mul(2).Dot(d)
	c := f.Dot(f) - radius*radius
	discriminant := b*b - 4*a*c

	if discriminant < 0 {
		return mgl32.Vec2{}, fmt.Errorf("No intersection")
	} else {
		discriminant = float32(math.Sqrt(float64(discriminant)))

		t1 := (-b - discriminant) / (2 * a)
		t2 := (-b + discriminant) / (2 * a)

		if t1 >= 0 && t1 <= 1 {
			return mgl32.Vec2{start.X() + t1*d.X(), start.Y() + t1*d.Y()}, nil
		}
		if t2 >= 0 && t2 <= 1 {
			return mgl32.Vec2{start.X() + t2*d.X(), start.Y() + t2*d.Y()}, nil
		}
	}

	return mgl32.Vec2{}, fmt.Errorf("No intersections")
}
Ejemplo n.º 6
0
func (polyline *polyLine) render(coords []float32) {
	var sleeve, current, next mgl32.Vec2
	polyline.vertices = []mgl32.Vec2{}
	polyline.normals = []mgl32.Vec2{}

	coords_count := len(coords)
	is_looping := (coords[0] == coords[coords_count-2]) && (coords[1] == coords[coords_count-1])
	if !is_looping { // virtual starting point at second point mirrored on first point
		sleeve = mgl32.Vec2{coords[2] - coords[0], coords[3] - coords[1]}
	} else { // virtual starting point at last vertex
		sleeve = mgl32.Vec2{coords[0] - coords[coords_count-4], coords[1] - coords[coords_count-3]}
	}

	for i := 0; i+3 < coords_count; i += 2 {
		current = mgl32.Vec2{coords[i], coords[i+1]}
		next = mgl32.Vec2{coords[i+2], coords[i+3]}
		polyline.renderEdge(sleeve, current, next)
		sleeve = next.Sub(current)
	}

	if is_looping {
		polyline.renderEdge(sleeve, next, mgl32.Vec2{coords[2], coords[3]})
	} else {
		polyline.renderEdge(sleeve, next, next.Add(sleeve))
	}

	if polyline.join == LINE_JOIN_NONE {
		polyline.vertices = polyline.vertices[2 : len(polyline.vertices)-2]
	}

	polyline.draw(is_looping)
}
Ejemplo n.º 7
0
func (polyline *polyLine) renderNoEdge(sleeve, current, next mgl32.Vec2) {
	sleeve_normal := getNormal(sleeve, polyline.halfwidth/sleeve.Len())

	polyline.normals = append(polyline.normals, sleeve_normal)
	polyline.normals = append(polyline.normals, sleeve_normal.Mul(-1))

	sleeve = next.Sub(current)
	sleeve_normal = getNormal(sleeve, polyline.halfwidth/sleeve.Len())

	polyline.normals = append(polyline.normals, sleeve_normal.Mul(-1))
	polyline.normals = append(polyline.normals, sleeve_normal)

	polyline.generateEdges(current, 4)
}
Ejemplo n.º 8
0
// TwoSegmentIntersect - find the intersection point of two line segments <p11-p12> and <p21-p22>
func TwoSegmentIntersect(p11, p12, p21, p22 mgl32.Vec2) (mgl32.Vec2, error) {
	p := p11
	q := p21
	r := p12.Sub(p11)
	s := p22.Sub(p21)
	if math.Abs(float64(Vec2Cross(r, s))) < 0.0000001 {
		return mgl32.Vec2{}, fmt.Errorf("No intersections: lines parallel")
	}
	t := Vec2Cross(q.Sub(p), s) / Vec2Cross(r, s)
	u := Vec2Cross(p.Sub(q), r) / Vec2Cross(s, r)
	if t >= 0 && t <= 1 && u >= 0 && u <= 1 {
		return p.Add(r.Mul(t)), nil
	}
	return mgl32.Vec2{}, fmt.Errorf("No intersections")
}
Ejemplo n.º 9
0
func ClickAndDragWindow(window *Window, hitbox Hitbox, c controller.Controller) {
	grabbed := false
	grabOffset := mgl32.Vec2{}
	hitbox.AddOnClick(func(button int, release bool, position mgl32.Vec2) {
		grabOffset = position
		grabbed = !release
	})
	c.BindMouseAction(func() {
		grabbed = false
	}, controller.MouseButton1, controller.Release)
	c.BindAxisAction(func(xpos, ypos float32) {
		if grabbed {
			position := mgl32.Vec2{xpos, ypos}
			window.SetTranslation(position.Sub(grabOffset).Vec3(0))
		}
	})
}
Ejemplo n.º 10
0
func (c *Container) Render(size, offset mgl32.Vec2) mgl32.Vec2 {
	c.size, c.offset = size, offset
	padding := convertMargin(c.padding, c.paddingPercent, size.X())
	margin := convertMargin(c.margin, c.marginPercent, size.X())
	sizeMinusMargins := size.Sub(mgl32.Vec2{
		margin.Left + margin.Right + padding.Left + padding.Right,
		margin.Top + margin.Bottom + padding.Top + padding.Bottom,
	})
	containerSize := sizeMinusMargins
	if c.width > 0 {
		containerSize[0] = c.getWidth(size.X()) - padding.Left - padding.Right
	}
	if c.height > 0 {
		containerSize[1] = c.getHeight(size.X()) - padding.Top - padding.Bottom
	}
	var width, height, highest float32 = 0, 0, 0
	for _, child := range c.children {
		childSize := child.Render(containerSize, mgl32.Vec2{width, height})
		width += childSize.X()
		if width > containerSize.X() {
			height += highest
			highest = 0
			childSize = child.Render(containerSize, mgl32.Vec2{0, height})
			width = childSize.X()
		}
		if childSize.Y() > highest {
			highest = childSize.Y()
		}
	}
	height += highest
	if mgl32.FloatEqual(c.height, 0) {
		containerSize[1] = height
	}
	//offsets and sizes
	c.backgroundOffset = mgl32.Vec2{margin.Left, margin.Top}
	c.elementsOffset = mgl32.Vec2{margin.Left + padding.Left, margin.Top + padding.Top}
	backgroundSize := containerSize.Add(mgl32.Vec2{padding.Left + padding.Right, padding.Top + padding.Bottom})
	totalSize := backgroundSize.Add(mgl32.Vec2{margin.Left + margin.Right, margin.Top + margin.Bottom})

	c.background.SetScale(backgroundSize.Vec3(0))
	c.background.SetTranslation(c.backgroundOffset.Vec3(0))
	c.elementsNode.SetTranslation(c.elementsOffset.Vec3(0))
	c.node.SetTranslation(c.offset.Vec3(0))
	c.Hitbox.SetSize(backgroundSize)
	return totalSize
}
Ejemplo n.º 11
0
/** Calculate line boundary points.
 *
 * Sketch:
 *
 *              u1
 * -------------+---...___
 *              |         ```'''--  ---
 * p- - - - - - q- - . _ _           | w/2
 *              |          ` ' ' r   +
 * -------------+---...___           | w/2
 *              u2         ```'''-- ---
 *
 * u1 and u2 depend on four things:
 *   - the half line width w/2
 *   - the previous line vertex p
 *   - the current line vertex q
 *   - the next line vertex r
 *
 * u1/u2 are the intersection points of the parallel lines to p-q and q-r,
 * i.e. the point where
 *
 *    (q + w/2 * ns) + lambda * (q - p) = (q + w/2 * nt) + mu * (r - q)   (u1)
 *    (q - w/2 * ns) + lambda * (q - p) = (q - w/2 * nt) + mu * (r - q)   (u2)
 *
 * with nt,nt being the normals on the segments s = p-q and t = q-r,
 *
 *    ns = perp(s) / |s|
 *    nt = perp(t) / |t|.
 *
 * Using the linear equation system (similar for u2)
 *
 *         q + w/2 * ns + lambda * s - (q + w/2 * nt + mu * t) = 0                 (u1)
 *    <=>  q-q + lambda * s - mu * t                          = (nt - ns) * w/2
 *    <=>  lambda * s   - mu * t                              = (nt - ns) * w/2
 *
 * the intersection points can be efficiently calculated using Cramer's rule.
 */
func (polyline *polyLine) renderMiterEdge(sleeve, current, next mgl32.Vec2) {
	sleeve_normal := getNormal(sleeve, polyline.halfwidth/sleeve.Len())
	t := next.Sub(current)
	len_t := t.Len()

	det := determinant(sleeve, t)
	// lines parallel, compute as u1 = q + ns * w/2, u2 = q - ns * w/2
	if mgl32.Abs(det)/(sleeve.Len()*len_t) < LINES_PARALLEL_EPS && sleeve.Dot(t) > 0 {
		polyline.normals = append(polyline.normals, sleeve_normal)
		polyline.normals = append(polyline.normals, sleeve_normal.Mul(-1))
	} else {
		// cramers rule
		nt := getNormal(t, polyline.halfwidth/len_t)
		lambda := determinant(nt.Sub(sleeve_normal), t) / det
		d := sleeve_normal.Add(sleeve.Mul(lambda))

		polyline.normals = append(polyline.normals, d)
		polyline.normals = append(polyline.normals, d.Mul(-1))
	}
	polyline.generateEdges(current, 2)
}
Ejemplo n.º 12
0
func (m *Mob) moveTowardExit(elapsed time.Duration, level *Level) {
	var (
		dest     mgl32.Vec2
		ok       bool
		pct      = float32(elapsed) / float32(time.Second)
		gridDist mgl32.Vec2
		goalDist int32
		stepDist = pct * m.Speed
	)
	if dest, goalDist, ok = level.Grid.GetNextStepToSink(m.Pos); !ok {
		return
	}
	gridDist = dest.Sub(m.Pos)
	if goalDist == 1 && gridDist.Len() < stepDist+0.5 {
		m.PendingDisable = true
	}
	if gridDist.X() > 0 {
		m.swapState(Left, Right)
	} else {
		m.swapState(Right, Left)
	}
	m.Pos = m.Pos.Add(gridDist.Normalize().Mul(stepDist))
}
Ejemplo n.º 13
0
func moveC(v mgl32.Vec2) {
	d := v.Sub(lstPnt) // calculate delta vec
	lstPnt = v

	switch slctdC {

	case 0:
		c0dy += d[1]

	case 1:
		c1dy += d[1]

	case 2:
		c2dy += d[1]

	case 4:
		c4dx += d[0]

	case 5:
		c5dx += d[0]
		c5dy += d[1]
	}
}
Ejemplo n.º 14
0
func (w *Window) mouseMove(position mgl32.Vec2) {
	w.mousePos = position.Sub(w.position)
	if w.element != nil {
		w.element.mouseMove(w.mousePos)
	}
}
Ejemplo n.º 15
0
func (ie *ImageElement) mouseClick(button int, release bool, position mgl32.Vec2) {
	offsetPos := position.Sub(ie.offset)
	ie.Hitbox.MouseClick(button, release, offsetPos)
}
Ejemplo n.º 16
0
func (ie *ImageElement) mouseMove(position mgl32.Vec2) {
	offsetPos := position.Sub(ie.offset)
	ie.Hitbox.MouseMove(offsetPos)
}
Ejemplo n.º 17
0
func direction(a, b mgl32.Vec2) mgl32.Vec2 {
	return a.Sub(b).Normalize()
}
Ejemplo n.º 18
0
func dist2(a, b mgl32.Vec2) float32 {
	diff := b.Sub(a)

	return square(diff.X()) + square(diff.Y())
}