Beispiel #1
0
func (r *Gopher) Paint(p *qml.Painter) {
	width := gl.Float(r.Int("width"))

	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

	gl.ShadeModel(gl.SMOOTH)
	gl.Enable(gl.DEPTH_TEST)
	gl.DepthMask(gl.TRUE)
	gl.Enable(gl.NORMALIZE)

	gl.Clear(gl.DEPTH_BUFFER_BIT)

	gl.Scalef(width/3, width/3, width/3)

	lka := []gl.Float{0.3, 0.3, 0.3, 1.0}
	lkd := []gl.Float{1.0, 1.0, 1.0, 0.0}
	lks := []gl.Float{1.0, 1.0, 1.0, 1.0}
	lpos := []gl.Float{-2, 6, 3, 1.0}

	gl.Enable(gl.LIGHTING)
	gl.Lightfv(gl.LIGHT0, gl.AMBIENT, lka)
	gl.Lightfv(gl.LIGHT0, gl.DIFFUSE, lkd)
	gl.Lightfv(gl.LIGHT0, gl.SPECULAR, lks)
	gl.Lightfv(gl.LIGHT0, gl.POSITION, lpos)
	gl.Enable(gl.LIGHT0)

	gl.EnableClientState(gl.NORMAL_ARRAY)
	gl.EnableClientState(gl.VERTEX_ARRAY)

	gl.Translatef(1.5, 1.5, 0)
	gl.Rotatef(-90, 0, 0, 1)
	gl.Rotatef(gl.Float(90+((36000+r.Rotation)%360)), 1, 0, 0)

	gl.Disable(gl.COLOR_MATERIAL)

	for _, obj := range r.model {
		for _, group := range obj.Groups {
			gl.Materialfv(gl.FRONT, gl.AMBIENT, group.Material.Ambient)
			gl.Materialfv(gl.FRONT, gl.DIFFUSE, group.Material.Diffuse)
			gl.Materialfv(gl.FRONT, gl.SPECULAR, group.Material.Specular)
			gl.Materialf(gl.FRONT, gl.SHININESS, group.Material.Shininess)
			gl.VertexPointer(3, gl.FLOAT, 0, group.Vertexes)
			gl.NormalPointer(gl.FLOAT, 0, group.Normals)
			gl.DrawArrays(gl.TRIANGLES, 0, gl.Sizei(len(group.Vertexes)/3))
		}
	}

	gl.Enable(gl.COLOR_MATERIAL)

	gl.DisableClientState(gl.NORMAL_ARRAY)
	gl.DisableClientState(gl.VERTEX_ARRAY)
}
Beispiel #2
0
func (r *GoRect) Paint(p *qml.Painter) {
	r.PaintCount++

	obj := p.Object()

	width := gl.Float(obj.Int("width"))
	height := gl.Float(obj.Int("height"))

	gl.Color3f(1.0, 0.0, 0.0)
	gl.Begin(gl.QUADS)
	gl.Vertex2f(0, 0)
	gl.Vertex2f(width, 0)
	gl.Vertex2f(width, height)
	gl.Vertex2f(0, height)
	gl.End()
}
Beispiel #3
0
func (r *GoRect) Paint(p *qml.Painter) {
	width := gl.Float(r.Int("width"))
	height := gl.Float(r.Int("height"))

	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.Color4f(1.0, 1.0, 1.0, 0.8)
	gl.Begin(gl.QUADS)
	gl.Vertex2f(0, 0)
	gl.Vertex2f(width, 0)
	gl.Vertex2f(width, height)
	gl.Vertex2f(0, height)
	gl.End()

	gl.LineWidth(2.5)
	gl.Color4f(0.0, 0.0, 0.0, 1.0)
	gl.Begin(gl.LINES)
	gl.Vertex2f(0, 0)
	gl.Vertex2f(width, height)
	gl.Vertex2f(width, 0)
	gl.Vertex2f(0, height)
	gl.End()
}
Beispiel #4
0
func Read(filename string) (map[string]*Object, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var materials map[string]*Material
	var objects = make(map[string]*Object)
	var object *Object
	var group *Group
	var vertex []gl.Float
	var normal []gl.Float

	lno := 0
	line := ""
	scanner := bufio.NewScanner(file)

	fail := func(msg string) error {
		return fmt.Errorf(msg+" at %s:%d: %s", filename, lno, line)
	}

	for scanner.Scan() {
		lno++
		line = scanner.Text()
		if strings.HasPrefix(line, "#") {
			continue
		}

		fields := strings.Fields(line)
		if len(fields) == 0 {
			continue
		}

		if fields[0] == "mtllib" {
			if len(fields) != 2 {
				return nil, fail("unsupported materials library line")
			}
			materials, err = readMaterials(filepath.Join(filepath.Dir(filename), fields[1]))
			if err != nil {
				return nil, err
			}
			continue
		}

		if fields[0] == "o" {
			if len(fields) != 2 {
				return nil, fail("unsupported object line")
			}
			object = &Object{Name: fields[1]}
			objects[object.Name] = object
			group = nil
			continue
		}

		if object == nil {
			return nil, fail("found data before object")
		}

		if fields[0] == "usemtl" {
			group = &Group{}
			object.Groups = append(object.Groups, group)
		}

		switch fields[0] {
		case "usemtl":
			if len(fields) != 2 {
				return nil, fail("unsupported material usage line")
			}
			group.Material = materials[fields[1]]
			if group.Material == nil {
				return nil, fmt.Errorf("material %q not defined", fields[1])
			}
		case "v":
			if len(fields) != 4 {
				return nil, fail("unsupported vertex line")
			}
			for i := 0; i < 3; i++ {
				f, err := strconv.ParseFloat(fields[i+1], 32)
				if err != nil {
					return nil, fail("cannot parse float")
				}
				vertex = append(vertex, gl.Float(f))
			}
		case "vn":
			if len(fields) != 4 {
				return nil, fail("unsupported vertex normal line")
			}
			for i := 0; i < 3; i++ {
				f, err := strconv.ParseFloat(fields[i+1], 32)
				if err != nil {
					return nil, fail("cannot parse float")
				}
				normal = append(normal, gl.Float(f))
			}
		case "f":
			if len(fields) != 4 {
				return nil, fail("unsupported face line")
			}
			for i := 0; i < 3; i++ {
				face := strings.Split(fields[i+1], "/")
				if len(face) != 3 {
					return nil, fail("unsupported face shape (not a triangle)")
				}
				vi, err := strconv.Atoi(face[0])
				if err != nil {
					return nil, fail("unsupported face vertex index")
				}
				ni, err := strconv.Atoi(face[2])
				if err != nil {
					return nil, fail("unsupported face normal index")
				}
				vi = (vi - 1) * 3
				ni = (ni - 1) * 3
				group.Vertexes = append(group.Vertexes, vertex[vi], vertex[vi+1], vertex[vi+2])
				group.Normals = append(group.Normals, normal[ni], normal[ni+1], normal[ni+2])
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}
	return objects, nil
}
Beispiel #5
0
func readMaterials(filename string) (map[string]*Material, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, fmt.Errorf("cannot read referenced material library: %v", err)
	}
	defer file.Close()

	var materials = make(map[string]*Material)
	var material *Material

	lno := 0
	line := ""
	scanner := bufio.NewScanner(file)

	fail := func(msg string) error {
		return fmt.Errorf(msg+" at %s:%d: %s", filename, lno, line)
	}

	for scanner.Scan() {
		lno++
		line = scanner.Text()
		if strings.HasPrefix(line, "#") {
			continue
		}

		fields := strings.Fields(line)
		if len(fields) == 0 {
			continue
		}

		if fields[0] == "newmtl" {
			if len(fields) != 2 {
				return nil, fail("unsupported material definition")
			}
			material = &Material{Name: fields[1]}
			material.Ambient = []gl.Float{0.2, 0.2, 0.2, 1.0}
			material.Diffuse = []gl.Float{0.8, 0.8, 0.8, 1.0}
			material.Specular = []gl.Float{0.0, 0.0, 0.0, 1.0}
			materials[material.Name] = material
			continue
		}

		if material == nil {
			return nil, fail("found data before material")
		}

		switch fields[0] {
		case "Ka":
			if len(fields) != 4 {
				return nil, fail("unsupported ambient color line")
			}
			for i := 0; i < 3; i++ {
				f, err := strconv.ParseFloat(fields[i+1], 32)
				if err != nil {
					return nil, fail("cannot parse float")
				}
				material.Ambient[i] = gl.Float(f)
			}
		case "Kd":
			if len(fields) != 4 {
				return nil, fail("unsupported diffuse color line")
			}
			for i := 0; i < 3; i++ {
				f, err := strconv.ParseFloat(fields[i+1], 32)
				if err != nil {
					return nil, fail("cannot parse float")
				}
				material.Diffuse[i] = gl.Float(f)
			}
		case "Ks":
			if len(fields) != 4 {
				return nil, fail("unsupported specular color line")
			}
			for i := 0; i < 3; i++ {
				f, err := strconv.ParseFloat(fields[i+1], 32)
				if err != nil {
					return nil, fail("cannot parse float")
				}
				material.Specular[i] = gl.Float(f)
			}
		case "Ns":
			if len(fields) != 2 {
				return nil, fail("unsupported shininess line")
			}
			f, err := strconv.ParseFloat(fields[1], 32)
			if err != nil {
				return nil, fail("cannot parse float")
			}
			material.Shininess = gl.Float(f / 1000 * 128)
		case "d":
			if len(fields) != 2 {
				return nil, fail("unsupported transparency line")
			}
			f, err := strconv.ParseFloat(fields[1], 32)
			if err != nil {
				return nil, fail("cannot parse float")
			}
			material.Ambient[3] = gl.Float(f)
			material.Diffuse[3] = gl.Float(f)
			material.Specular[3] = gl.Float(f)
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	// Exporting from blender seems to show everything too dark in
	// practice, so hack colors to look closer to what we see there.
	// TODO This needs more real world checking.
	for _, material := range materials {
		if material.Ambient[0] == 0 && material.Ambient[1] == 0 && material.Ambient[2] == 0 && material.Ambient[3] == 1 {
			material.Ambient[0] = material.Diffuse[0] * 0.7
			material.Ambient[1] = material.Diffuse[1] * 0.7
			material.Ambient[2] = material.Diffuse[2] * 0.7
		}
		for i := 0; i < 3; i++ {
			material.Diffuse[i] *= 1.3
			if material.Diffuse[i] > 1 {
				material.Diffuse[i] = 1
			}
		}
	}

	return materials, nil
}