Beispiel #1
0
// objTriangleLists produces a map of strings that can be used to write the
// triangle lists for all frames of an MD3's surface. Special variation on the
// forAllSurfaces function that handles base vertices (i.e., sequence is
// much more important).
func objTriangleLists(model *md3.Model) map[*md3.Surface]string {
	numSurfs := model.NumSurfaces()

	triStrings := make(map[*md3.Surface]string, numSurfs)
	builtPairs := make(chan surfaceStringPair)
	waitSignal := make(chan bool)

	baseVertex := 1
	for surfaceIndex := 0; surfaceIndex < numSurfs; surfaceIndex++ {
		surf := model.Surface(surfaceIndex)
		go surfaceTriangleList(surf, baseVertex, builtPairs)
		baseVertex += surf.NumVertices()
	}

	go func(count int, builtPairs <-chan surfaceStringPair, waitSignal chan<- bool) {
		for ; count > 0; count-- {
			pair := <-builtPairs
			triStrings[pair.surface] = pair.value
		}
		waitSignal <- true
	}(numSurfs, builtPairs, waitSignal)

	<-waitSignal

	return triStrings
}
Beispiel #2
0
func performConvertModel(modelPath string, model *md3.Model, signal chan<- bool, writeQueue chan<- func()) {

	waitSignal := make(chan bool)
	triLists := objTriangleLists(model)
	tcLists := objTexCoordLists(model)

	var _ = triLists
	var _ = tcLists

	name := path.Base(modelPath)
	name = name[:len(name)-len(path.Ext(name))]
	dir := path.Clean(*outputPath)
	os.MkdirAll(dir, 0755)

	numFrames := model.NumFrames()

	for frame := 0; frame < numFrames; frame++ {
		go func(frame int) {
			writeQueue <- func() {
				defer func(waitSignal chan<- bool) {
					go func() { waitSignal <- true }()
				}(waitSignal)

				var err error
				var file *os.File
				outName := fmt.Sprintf("%s+%d.obj", name, frame)
				outPath := path.Join(dir, outName)

				file, err = os.Create(outPath)
				if err != nil {
					log.Println("Error creating", outPath, "from", modelPath, "->", err)
					return
				}
				defer file.Close()

				_, err = fmt.Fprintf(file, "o %s\n", model.Name())
				if err != nil {
					log.Println("Error writing header for", outPath, "from", modelPath, "->", err)
				}

				numSurfaces := model.NumSurfaces()
				posNorms := objPosNormLists(model, frame)
				for surfIndex := 0; surfIndex < numSurfaces; surfIndex++ {
					surf := model.Surface(surfIndex)
					err = writeOBJSurface(file, surf, posNorms, tcLists, triLists)
					if err != nil {
						log.Println("Error writing surface for", outPath, "from", modelPath, "->", err)
						return
					}
				}
			}
		}(frame)
	}

	for frame := 0; frame < numFrames; frame++ {
		<-waitSignal
	}

	signal <- true
}
Beispiel #3
0
// forAllSurfaces loops over all surfaces of the given model and concurrently
// launches functions mapping the surfaces to string values. The results of the
// mapping operation are handled by a single goroutine to prevent writes from
// potentially parallel sources.
func forAllSurfaces(model *md3.Model, fn surfaceMappingFunc) map[*md3.Surface]string {

	numSurfs := model.NumSurfaces()

	pairs := make(map[*md3.Surface]string, numSurfs)
	builtPairs := make(chan surfaceStringPair)
	waitSignal := make(chan bool)

	for surfaceIndex := 0; surfaceIndex < numSurfs; surfaceIndex++ {
		surf := model.Surface(surfaceIndex)
		go fn(surf, builtPairs)
	}

	go func(count int, builtPairs <-chan surfaceStringPair, waitSignal chan<- bool) {
		for ; count > 0; count-- {
			pair := <-builtPairs
			pairs[pair.surface] = pair.value
		}
		waitSignal <- true
	}(numSurfs, builtPairs, waitSignal)

	<-waitSignal

	return pairs
}