Example #1
0
func appendBoxExtra(verts []*render.StaticVertex, x, y, z, w, h, d float32, textures [6]render.TextureInfo, extra [6][2]float64) []*render.StaticVertex {
	for i, face := range faceVertices {
		tex := textures[i]
		if tex == nil {
			continue
		}
		for _, v := range face.verts {
			var rr, gg, bb byte = 255, 255, 255
			if direction.Type(i) == direction.West || direction.Type(i) == direction.East {
				rr = byte(255 * 0.8)
				gg = byte(255 * 0.8)
				bb = byte(255 * 0.8)
			}
			vert := &render.StaticVertex{
				X:        float32(v.X)*w + x,
				Y:        float32(v.Y)*h + y,
				Z:        float32(v.Z)*d + z,
				Texture:  tex,
				TextureX: float64(v.TOffsetX) * extra[i][0],
				TextureY: float64(v.TOffsetY) * extra[i][1],
				R:        rr,
				G:        gg,
				B:        bb,
				A:        255,
			}
			verts = append(verts, vert)
		}
	}
	return verts
}
Example #2
0
func genStaticModelFromItem(mdl *model, block Block, mode string) (out []*render.StaticVertex, mat mgl32.Mat4) {
	mat = mgl32.Rotate3DZ(math.Pi).Mat4().
		Mul4(mgl32.Rotate3DY(math.Pi / 2).Mat4()).
		Mul4(mgl32.Rotate3DZ(-math.Pi / 2).Mat4())

	if gui, ok := mdl.display[mode]; ok {
		if gui.Scale != nil {
			mat = mat.Mul4(mgl32.Scale3D(
				float32(gui.Scale[0]),
				float32(gui.Scale[1]),
				float32(gui.Scale[2]),
			))
		}
		if gui.Translation != nil {
			mat = mat.Mul4(mgl32.Translate3D(
				float32(gui.Translation[0]/32),
				float32(gui.Translation[1]/32),
				float32(gui.Translation[2]/32),
			))
		}
		if gui.Rotation != nil {
			mat = mat.Mul4(mgl32.Rotate3DX(math.Pi + float32(gui.Rotation[0]/180)*math.Pi).Mat4())
			mat = mat.Mul4(mgl32.Rotate3DZ(math.Pi + float32(gui.Rotation[2]/180)*math.Pi).Mat4())
			mat = mat.Mul4(mgl32.Rotate3DY(float32(gui.Rotation[1]/180) * math.Pi).Mat4())
		}
	}
	mat = mat.Mul4(mgl32.Rotate3DY(math.Pi / 2).Mat4())
	mat = mat.Mul4(mgl32.Translate3D(-1/16.0, 0, 0))

	tex := render.GetTexture("solid")
	rect := tex.Rect()

	tName, plugin := mdl.textureVars["layer0"], "minecraft"
	if pos := strings.IndexRune(tName, ':'); pos != -1 {
		plugin = tName[:pos]
		tName = tName[pos:]
	}
	f, err := resource.Open(plugin, "textures/"+tName+".png")
	if err != nil {
		return
	}
	defer f.Close()
	img, err := png.Decode(f)
	if err != nil {
		panic(err)
	}

	w, h := img.Bounds().Dx(), img.Bounds().Dy()
	sx := 1 / float32(w)
	sy := 1 / float32(h)

	isSolid := func(x, y int) bool {
		col := img.At(x, y)
		_, _, _, aa := col.RGBA()
		if aa == 0 {
			return false
		}
		return true
	}

	for x := 0; x < w; x++ {
		for y := 0; y < h; y++ {
			col := img.At(x, y)
			rr, gg, bb, aa := col.RGBA()
			if aa == 0 {
				continue
			}

			for i, f := range faceVertices {
				facing := direction.Type(i)
				if facing != direction.North && facing != direction.South {
					xx, yy, _ := facing.Offset()
					if isSolid(x+xx, y+yy) {
						continue
					}
				}

				var cr, cg, cb byte
				cr = byte(rr >> 8)
				cg = byte(gg >> 8)
				cb = byte(bb >> 8)
				if facing == direction.East || facing == direction.West {
					cr = byte(float64(cr) * 0.8)
					cg = byte(float64(cg) * 0.8)
					cb = byte(float64(cb) * 0.8)
				}
				if facing == direction.North || facing == direction.South {
					cr = byte(float64(cr) * 0.6)
					cg = byte(float64(cg) * 0.6)
					cb = byte(float64(cb) * 0.6)
				}

				for _, vert := range f.verts {
					vX, vY, vZ := float32(vert.X), float32(vert.Y), float32(vert.Z)
					vert := &render.StaticVertex{
						Y:        vY*sy - 0.5 + sy*float32(y),
						X:        vX*sx - 0.5 + sx*float32(x),
						Z:        (vZ - 0.5) * (1.0 / 16.0),
						Texture:  tex,
						TextureX: float64(vert.TOffsetX) / float64(16*rect.Width),
						TextureY: float64(vert.TOffsetY) / float64(16*rect.Height),
						R:        cr,
						G:        cg,
						B:        cb,
						A:        byte(aa >> 8),
					}
					out = append(out, vert)
				}
			}
		}
	}
	return
}
Example #3
0
func precomputeModel(bm *model) *processedModel {
	p := &processedModel{}
	p.ambientOcclusion = bm.ambientOcclusion
	p.weight = bm.weight
	for _, el := range bm.elements {
		for i, face := range el.faces {
			faceID := direction.Type(i)
			if face == nil {
				continue
			}
			pFace := processedFace{}
			cullFace := face.cullFace
			if bm.x > 0 {
				o := int(bm.x) / 90
				cullFace = rotateDirection(cullFace, o, faceRotationX, direction.East, direction.West, direction.Invalid)
				faceID = rotateDirection(faceID, o, faceRotationX, direction.East, direction.West, direction.Invalid)
			}
			if bm.y > 0 {
				o := int(bm.y) / 90
				cullFace = rotateDirection(cullFace, o, faceRotation, direction.Up, direction.Down, direction.Invalid)
				faceID = rotateDirection(faceID, o, faceRotation, direction.Up, direction.Down, direction.Invalid)
			}
			pFace.cullFace = cullFace
			pFace.facing = direction.Type(faceID)
			pFace.tintIndex = face.tintIndex
			pFace.shade = el.shade

			vert := faceVertices[i]
			tex := bm.lookupTexture(face.texture)
			rect := tex.Rect()

			ux1 := int16(face.uv[0] * float64(rect.Width))
			ux2 := int16(face.uv[2] * float64(rect.Width))
			uy1 := int16(face.uv[1] * float64(rect.Height))
			uy2 := int16(face.uv[3] * float64(rect.Height))

			tw, th := int16(rect.Width), int16(rect.Height)
			if face.rotation > 0 {
				x := ux1
				y := uy1
				w := ux2 - ux1
				h := uy2 - uy1
				switch face.rotation {
				case 90:
					uy2 = x + w
					ux1 = tw*16 - (y + h)
					ux2 = tw*16 - y
					uy1 = x
				case 180:
					uy1 = th*16 - (y + h)
					uy2 = th*16 - y
					ux1 = x + w
					ux2 = x
				case 270:
					uy2 = x
					uy1 = x + w
					ux2 = y + h
					ux1 = y
				}
			}

			var minX, minY, minZ = float32(math.Inf(1)), float32(math.Inf(1)), float32(math.Inf(1))
			var maxX, maxY, maxZ = float32(math.Inf(-1)), float32(math.Inf(-1)), float32(math.Inf(-1))

			for v := range vert.verts {
				pFace.verticesTexture = append(pFace.verticesTexture, tex)
				vert.verts[v].TX = uint16(rect.X)
				vert.verts[v].TY = uint16(rect.Y)
				vert.verts[v].TW = uint16(rect.Width)
				vert.verts[v].TH = uint16(rect.Height)
				vert.verts[v].TAtlas = int16(tex.Atlas())

				if vert.verts[v].X == 0 {
					vert.verts[v].X = float32(el.from[0] / 16.0)
				} else {
					vert.verts[v].X = float32(el.to[0] / 16.0)
				}
				if vert.verts[v].Y == 0 {
					vert.verts[v].Y = float32(el.from[1] / 16.0)
				} else {
					vert.verts[v].Y = float32(el.to[1] / 16.0)
				}
				if vert.verts[v].Z == 0 {
					vert.verts[v].Z = float32(el.from[2] / 16.0)
				} else {
					vert.verts[v].Z = float32(el.to[2] / 16.0)
				}

				if el.rotation != nil {
					r := el.rotation
					switch r.axis {
					case "y":
						rotY := -r.angle * (math.Pi / 180)
						c := math.Cos(rotY)
						s := math.Sin(rotY)
						x := float64(vert.verts[v].X) - (r.origin[0] / 16.0)
						z := float64(vert.verts[v].Z) - (r.origin[2] / 16.0)
						vert.verts[v].X = float32(r.origin[0]/16.0 + (x*c - z*s))
						vert.verts[v].Z = float32(r.origin[2]/16.0 + (z*c + x*s))
					case "x":
						rotX := r.angle * (math.Pi / 180)
						c := math.Cos(-rotX)
						s := math.Sin(-rotX)
						z := float64(vert.verts[v].Z) - (r.origin[2] / 16.0)
						y := float64(vert.verts[v].Y) - (r.origin[1] / 16.0)
						vert.verts[v].Z = float32(r.origin[2]/16.0 + (z*c - y*s))
						vert.verts[v].Y = float32(r.origin[1]/16.0 + (y*c + z*s))
					case "z":
						rotZ := -r.angle * (math.Pi / 180)
						c := math.Cos(-rotZ)
						s := math.Sin(-rotZ)
						x := float64(vert.verts[v].X) - (r.origin[0] / 16.0)
						y := float64(vert.verts[v].Y) - (r.origin[1] / 16.0)
						vert.verts[v].X = float32(r.origin[0]/16.0 + (x*c - y*s))
						vert.verts[v].Y = float32(r.origin[1]/16.0 + (y*c + x*s))
					}
				}

				if bm.x > 0 {
					rotX := bm.x * (math.Pi / 180)
					c := float32(math.Cos(rotX))
					s := float32(math.Sin(rotX))
					z := vert.verts[v].Z - 0.5
					y := vert.verts[v].Y - 0.5
					vert.verts[v].Z = 0.5 + (z*c - y*s)
					vert.verts[v].Y = 0.5 + (y*c + z*s)
				}

				if bm.y > 0 {
					rotY := bm.y * (math.Pi / 180)
					c := float32(math.Cos(rotY))
					s := float32(math.Sin(rotY))
					x := vert.verts[v].X - 0.5
					z := vert.verts[v].Z - 0.5
					vert.verts[v].X = 0.5 + (x*c - z*s)
					vert.verts[v].Z = 0.5 + (z*c + x*s)
				}

				if vert.verts[v].TOffsetX == 0 {
					vert.verts[v].TOffsetX = int16(ux1)
				} else {
					vert.verts[v].TOffsetX = int16(ux2)
				}
				if vert.verts[v].TOffsetY == 0 {
					vert.verts[v].TOffsetY = int16(uy1)
				} else {
					vert.verts[v].TOffsetY = int16(uy2)
				}

				if face.rotation > 0 {
					rotY := -float64(face.rotation) * (math.Pi / 180)
					c := int16(math.Cos(rotY))
					s := int16(math.Sin(rotY))
					x := vert.verts[v].TOffsetX - 8*tw
					y := vert.verts[v].TOffsetY - 8*th
					vert.verts[v].TOffsetX = 8*tw + int16(x*c-y*s)
					vert.verts[v].TOffsetY = 8*th + int16(y*c+x*s)
				}

				if bm.uvLock && bm.y > 0 &&
					(pFace.facing == direction.Up || pFace.facing == direction.Down) {
					rotY := float64(-bm.y) * (math.Pi / 180)
					c := int16(math.Cos(rotY))
					s := int16(math.Sin(rotY))
					x := vert.verts[v].TOffsetX - 8*16
					y := vert.verts[v].TOffsetY - 8*16
					vert.verts[v].TOffsetX = 8*16 + int16(x*c+y*s)
					vert.verts[v].TOffsetY = 8*16 + int16(y*c-x*s)
				}

				if bm.uvLock && bm.x > 0 &&
					(pFace.facing != direction.Up && pFace.facing != direction.Down) {
					rotY := float64(bm.x) * (math.Pi / 180)
					c := int16(math.Cos(rotY))
					s := int16(math.Sin(rotY))
					x := vert.verts[v].TOffsetX - 8*16
					y := vert.verts[v].TOffsetY - 8*16
					vert.verts[v].TOffsetX = 8*16 + int16(x*c+y*s)
					vert.verts[v].TOffsetY = 8*16 + int16(y*c-x*s)
				}

				if el.rotation != nil && el.rotation.rescale {
					if vert.verts[v].X < minX {
						minX = vert.verts[v].X
					} else if vert.verts[v].X > maxX {
						maxX = vert.verts[v].X
					}
					if vert.verts[v].Y < minY {
						minY = vert.verts[v].Y
					} else if vert.verts[v].Y > maxY {
						maxY = vert.verts[v].Y
					}
					if vert.verts[v].Z < minZ {
						minZ = vert.verts[v].Z
					} else if vert.verts[v].Z > maxZ {
						maxZ = vert.verts[v].Z
					}
				}
			}

			if el.rotation != nil && el.rotation.rescale {
				diffX := maxX - minX
				diffY := maxY - minY
				diffZ := maxZ - minZ
				for v := range vert.verts {
					vert.verts[v].X = (vert.verts[v].X - minX) / diffX
					vert.verts[v].Y = (vert.verts[v].Y - minY) / diffY
					vert.verts[v].Z = (vert.verts[v].Z - minZ) / diffZ
				}
			}

			pFace.vertices = vert.verts[:]
			pFace.indices = vert.indices[:]

			p.faces = append(p.faces, pFace)
		}
	}
	return p
}