Example #1
0
// Evaluates the rules in the given XML stream and returns a list of curves
func Evaluate(stream io.Reader) Curve {

	var curve Curve
	var lsys LSystem

	bytes, _ := ioutil.ReadAll(stream)

	if err := xml.Unmarshal(bytes, &lsys); err != nil {
		fmt.Println("Error parsing XML file:", err)
		return curve
	}

	// Parse the transform strings
	lsys.Matrices = make(MatrixCache)
	for _, rule := range lsys.Rules {
		for _, call := range rule.Calls {
			lsys.Matrices.ParseString(call.Transforms)
		}
		for _, inst := range rule.Instances {
			lsys.Matrices.ParseString(inst.Transforms)
		}
	}
	lsys.Matrices[""] = *vmath.M4Identity()

	// Provide defaults
	for i := range lsys.Rules {
		r := &lsys.Rules[i]
		if r.Weight == 0 {
			r.Weight = 1
		}
	}

	// Seed the random-number generator and pick the entry rule
	random := rand.New(rand.NewSource(42))
	start := StackNode{
		RuleIndex: lsys.PickRule("entry", random),
		Transform: vmath.M4Identity(),
	}

	lsys.ProcessRule(start, &curve, random)
	return curve
}
Example #2
0
// Parse a string in the xform language and add the resulting matrix to the lookup table.
// Examples:
//   "rx -2 tx 0.1 sa 0.996"
//   "s 0.55 2.0 1.25"
func (cache *MatrixCache) ParseString(s string) {
	if len(s) == 0 {
		return
	}
	reader := bufio.NewReader(strings.NewReader(s))

	xform := vmath.M4Identity()

	readFloat := func() float32 {
		sx, _ := reader.ReadString(' ')
		fx, _ := strconv.ParseFloat(strings.TrimSpace(sx), 32)
		return float32(fx)
	}

	for {
		token, err := reader.ReadString(' ')
		token = strings.TrimSpace(token)
		switch token {
		case "s":
			x := readFloat()
			y := readFloat()
			z := readFloat()
			m := vmath.M4Scale(x, y, z)
			xform = m.Compose(xform)
		case "sa":
			a := readFloat()
			m := vmath.M4Scale(a, a, a)
			xform = m.Compose(xform)
		case "t":
			x := readFloat()
			y := readFloat()
			z := readFloat()
			m := vmath.M4Translate(x, y, z)
			xform = m.Compose(xform)
		case "tx":
			x := readFloat()
			m := vmath.M4Translate(x, 0, 0)
			xform = m.Compose(xform)
		case "ty":
			y := readFloat()
			m := vmath.M4Translate(0, y, 0)
			xform = m.Compose(xform)
		case "tz":
			z := readFloat()
			m := vmath.M4Translate(0, 0, z)
			xform = m.Compose(xform)
		case "rx":
			x := radians(readFloat())
			m := vmath.M4RotateX(-x)
			xform = m.Compose(xform)
		case "ry":
			y := radians(readFloat())
			m := vmath.M4RotateY(-y)
			xform = m.Compose(xform)
		case "rz":
			z := radians(readFloat())
			m := vmath.M4RotateZ(-z)
			xform = m.Compose(xform)
		case "":
		default:
			fmt.Println("Unknown token: ", token)
		}
		if err != nil {
			break
		}
	}
	(*cache)[s] = *xform
	return
}