func triangles(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("pov", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> pov [options] <progs/model.mdl> \n", os.Args[0]) fs.PrintDefaults() } rotate := fs.String("rotate", "0,0,0", "Rotate model.") useSkin := fs.Bool("skin", true, "Use texture.") fs.Parse(args) if fs.NArg() == 0 { log.Fatalf("Need to specify a model name.") } model := fs.Arg(0) h, err := p.Get(model) if err != nil { log.Fatalf("Unable to get %q: %v", model, err) } m, err := mdl.Load(h) if err != nil { log.Fatalf("Unable to load %q: %v", model, err) } for n, _ := range m.Frames { skin := "\"" + path.Join(model, "skin_0.png") + "\"" if !*useSkin { skin = "" } fmt.Printf("#macro %s(pos, rot)\nobject { %s rotate <%s>}\n#end\n", frameName(model, n), m.POVFrameID(n, skin), *rotate) } }
func pov(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("pov", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> pov [options] <maps/eXmX.bsp> \n", os.Args[0]) fs.PrintDefaults() } lights := fs.Bool("lights", true, "Export lights.") flatColor := fs.String("flat_color", "Gray25", "") textures := fs.Bool("textures", false, "Use textures.") //maps := fs.String("maps", ".*", "Regex of maps to convert.") fs.Parse(args) if fs.NArg() == 0 { log.Fatalf("Need to specify a map name.") } maps := fs.Arg(0) res, err := p.Get(maps) if err != nil { log.Fatalf("Finding %q: %v", maps, err) } m, err := bsp.Load(res) if err != nil { log.Fatalf("Loading %q: %v", maps, err) } mesh, err := m.POVTriangleMesh(bsp.ModelMacroPrefix(maps), *textures, *flatColor) if err != nil { log.Fatalf("Error getting mesh: %v", err) } fmt.Println(mesh) if *lights { fmt.Println(m.POVLights()) } }
func info(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("info", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> info [options] <progs/model.mdl> \n", os.Args[0]) fs.PrintDefaults() } fs.Parse(args) if fs.NArg() == 0 { log.Fatalf("Need to specify a model name.") } model := fs.Arg(0) h, err := p.Get(model) if err != nil { log.Fatalf("Unable to get %q: %v", model, err) } m, err := mdl.Load(h) if err != nil { log.Fatalf("Unable to load %q: %v", model, err) } fmt.Printf("Filename: %s\n", model) fmt.Printf(" Triangles: %v\n", len(m.Triangles)) fmt.Printf(" EyePosition: %v\n", m.Header.EyePosition) fmt.Printf("Skins: %v\n", len(m.Skins)) fmt.Printf(" %6s %16s\n", "Frame#", "Name") for n, f := range m.Frames { fmt.Printf(" %6d %16s\n", n, f.Name) } }
func info(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("info", flag.ExitOnError) //outDir := fs.String("out", ".", "Output directory.") //maps := fs.String("maps", ".*", "Regex of maps to convert.") fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> info [options] <maps/eXmX.bsp> \n", os.Args[0]) fs.PrintDefaults() } fs.Parse(args) if fs.NArg() == 0 { log.Fatalf("Need to specify a map name.") } mapName := fs.Arg(0) b, err := p.Get(mapName) if err != nil { log.Fatalf("Finding map %q: %v", mapName, err) } m, err := bsp.Load(b) if err != nil { log.Fatalf("Loading map: %v", err) } fmt.Printf("Vertices: %v\n", len(m.Raw.Vertex)) fmt.Printf("Faces: %v\n", len(m.Raw.Face)) fmt.Printf("Edges: %v\n", len(m.Raw.Edge)) fmt.Printf("LEdges: %v\n", len(m.Raw.LEdge)) fmt.Printf("Vertices: %v\n", len(m.Raw.Entities)) fmt.Printf("MipTexes: %v\n", len(m.Raw.MipTex)) fmt.Printf("TexInfos: %v\n", len(m.Raw.TexInfo)) fmt.Printf("Model Faces\n") for n, mod := range m.Raw.Models { fmt.Printf("%7d %6v\n", n, mod.FaceNum) } }
func info(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("info", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> info [options] <demofile.dem> \n", os.Args[0]) fs.PrintDefaults() } fs.Parse(args) if fs.NArg() == 0 { log.Fatalf("Need to specify a demo name.") } demo := fs.Arg(0) df, err := p.Get(demo) if err != nil { log.Fatalf("Getting %q: %v", demo, err) } d := dem.Open(df) timeUpdates := 0 messages := 0 blockCount := 0 for { block, err := d.ReadBlock() if err == io.EOF { break } if err != nil { log.Fatalf("Demo error: %v", err) } blockCount++ msgs, err := block.Messages() if err != nil { log.Fatalf("Getting messages: %v", err) } timeUpdatesInBlock := 0 for _, msg := range msgs { messages++ if _, ok := msg.(*dem.MsgTime); ok { timeUpdates++ timeUpdatesInBlock++ } } if timeUpdatesInBlock > 1 { fmt.Printf("Block %d had %d time updates\n", blockCount, timeUpdatesInBlock) } } fmt.Printf("Blocks: %d\n", blockCount) fmt.Printf("Messages: %d\n", messages) fmt.Printf("Time updates: %d\n", timeUpdates) }
func convert(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("convert", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> convert [options]\n", os.Args[0]) fs.PrintDefaults() } outDir := fs.String("out", ".", "Output directory.") skins := fs.Bool("skins", true, "Use skins.") fs.Parse(args) errors := []string{} os.Mkdir(*outDir, 0755) for _, mf := range p.List() { if path.Ext(mf) != ".mdl" { continue } func() { o, err := p.Get(mf) if err != nil { log.Fatalf("Getting %q: %v", mf, err) } m, err := mdl.Load(o) if err != nil { log.Printf("Loading %q: %v", mf, err) errors = append(errors, mf) return } var cparts []string for _, part := range strings.Split(mf, "/") { cparts = append(cparts, part) if err := os.Mkdir(path.Join(*outDir, strings.Join(cparts, "/")), 0755); err != nil { //log.Printf("Creating model subdir: %v, continuing...", err) } } fn := fmt.Sprintf(path.Join(mf, "model.inc")) of, err := os.Create(path.Join(*outDir, fn)) if err != nil { log.Fatalf("Model create of %q fail: %v", fn, err) } defer of.Close() for n := range m.Frames { if *skins { fmt.Fprintf(of, "#macro %s(pos, rot, skin)\n%s\n#end\n", frameName(mf, n), m.POVFrameID(n, "skin")) } else { fmt.Fprintf(of, "#macro %s(pos, rot)\n%s\n#end\n", frameName(mf, n), m.POVFrameID(n, "")) } } for n, skin := range m.Skins { of, err := os.Create(path.Join(*outDir, mf, fmt.Sprintf("skin_%d.png", n))) if err != nil { log.Fatalf("Skin create of %q fail: %v", fn, err) } defer of.Close() if err := (&png.Encoder{CompressionLevel: pngCompressionLevel}).Encode(of, skin); err != nil { log.Fatalf("Encoding skin to png: %v", err) } } }() } if len(errors) > 0 { fmt.Printf("Failed to convert %d models:\n %s\n", len(errors), strings.Join(errors, "\n ")) } }
func generateFrame(p pak.MultiPak, outDir string, oldState, newState *dem.State, frameNum int, t float64, cameraLight, radiosity bool, threesixty bool) { if newState.ServerInfo.Models == nil { return } if newState.Level == nil { bl, err := p.Get(newState.ServerInfo.Models[0]) if err != nil { log.Fatalf("Looking up %q: %v", newState.ServerInfo.Models[0], err) } newState.Level, err = bsp.Load(bl) if err != nil { log.Fatalf("Level loading %q: %v", newState.ServerInfo.Models[0], err) } // TODO //log.Printf("Level start pos: %s", newState.Level.StartPos.String()) //d.Pos().X = level.StartPos.X //d.Pos().Y = level.StartPos.Y //d.Pos().Z = level.StartPos.Z } ival := float64(t-oldState.Time) / float64(newState.Time-oldState.Time) curState := newState.Copy() curState.Time = t curState.ViewAngle = interpolateAngle(oldState.ViewAngle, newState.ViewAngle, ival) if tooFast(oldState, newState) { //, float64(newState.Time-oldState.Time)) { if false { fmt.Printf("Frame %d: Moving too fast, snapping.\n", frameNum) } if ival < 0.5 { curState.ViewAngle = oldState.ViewAngle curState.Entities[curState.CameraEnt].Pos = oldState.Entities[curState.CameraEnt].Pos } else { curState.ViewAngle = newState.ViewAngle curState.Entities[curState.CameraEnt].Pos = newState.Entities[curState.CameraEnt].Pos } } for n := range oldState.Entities { if oldState.Entities[n].Model != newState.Entities[n].Model { // If model has changed, choose nearest and stop. if ival < 0.5 { curState.Entities[n] = oldState.Entities[n] } else { curState.Entities[n] = newState.Entities[n] } continue } curState.Entities[n].Model = oldState.Entities[n].Model curState.Entities[n].Pos = interpolate(oldState.Entities[n].Pos, newState.Entities[n].Pos, ival) if false && n == 8 { fmt.Printf("Frame %d, ent %d %v (%v -> %v by %g)\n", frameNum, n, curState.Entities[n].Pos.String(), oldState.Entities[n].Pos.String(), newState.Entities[n].Pos.String(), ival, ) } curState.Entities[n].Angle = interpolateAngle(oldState.Entities[n].Angle, newState.Entities[n].Angle, ival) if ival < 0.5 { curState.Entities[n].Frame = oldState.Entities[n].Frame curState.Entities[n].Skin = oldState.Entities[n].Skin curState.Entities[n].Color = oldState.Entities[n].Color } else { curState.Entities[n].Frame = newState.Entities[n].Frame curState.Entities[n].Skin = newState.Entities[n].Skin curState.Entities[n].Color = newState.Entities[n].Color } } var camera string = "perspective" var angle string = "100" if threesixty { camera = "spherical" angle = "360 180" } if *verbose { fmt.Printf("Frame %d (t=%g): Pos: %v (%v -> %v, %g), viewAngle %v (%v -> %v)\n", frameNum, curState.Time, curState.Entities[curState.CameraEnt].Pos, oldState.Entities[curState.CameraEnt].Pos, newState.Entities[curState.CameraEnt].Pos, ival, curState.ViewAngle, oldState.ViewAngle, newState.ViewAngle, ) } writePOV(path.Join(outDir, fmt.Sprintf("frame-%08d.pov", frameNum)), newState.ServerInfo.Models[0], curState, cameraLight, radiosity, camera, angle) }
func convert(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("convert", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak <pak0,pak1,...> convert [options] <demofile.dem> \n", os.Args[0]) fs.PrintDefaults() } radiosity := fs.Bool("radiosity", false, "Use radiosity lighting.") fps := fs.Float64("fps", 30.0, "Frames per second.") outDir := fs.String("out", "render", "Output directory.") cameraLight := fs.Bool("camera_light", false, "Add camera light.") threesixty := fs.Bool("threesixty", false, "360 degree view mode.") fs.Parse(args) if fs.NArg() == 0 { log.Fatalf("Need to specify a demo name.") } demo := fs.Arg(0) df, err := p.Get(demo) if err != nil { log.Fatalf("Getting %q: %v", demo, err) } d := dem.Open(df) var oldState *dem.State newState := dem.NewState() frameNum := 0 for { block, err := d.ReadBlock() if err == io.EOF { break } if err != nil { log.Fatalf("Demo error: %v", err) } if !newState.CameraSetViewAngle { newState.ViewAngle = block.Header.ViewAngle } seenTime := false msgs, err := block.Messages() if err != nil { log.Fatalf("Getting messages: %v", err) } for _, msg := range msgs { msg.Apply(newState) if _, ok := msg.(*dem.MsgTime); ok { seenTime = true } else if m, ok := msg.(*dem.MsgCameraPos); ok { if *verbose { fmt.Printf("Camera set to %d\n", m.Entity) } } else if m, ok := msg.(*dem.MsgIntermission); ok { if *verbose { fmt.Printf("Intermission: %q\n", m.Text) } } else if m, ok := msg.(*dem.MsgFinale); ok { if *verbose { fmt.Printf("Finale: %q\n", m.Text) } } else if m, ok := msg.(*dem.MsgCameraOrientation); ok { if *verbose { fmt.Printf("Camera angle set to <%g,%g,%g>\n", m.X, m.Y, m.Z) } } else if m, ok := msg.(*dem.MsgSpawnBaseline); ok { if false { fmt.Printf("Spawning %d: %+v\n", m.Entity, newState.ServerInfo.Models[m.Model]) } } else if m, ok := msg.(*dem.MsgUpdate); ok { if false { debugEnt := uint16(1) if m.Entity == debugEnt { fmt.Printf("MOVE Frame %d Ent %d moved from %v %v to %v %v\n", frameNum, m.Entity, oldState.Entities[m.Entity].Pos, oldState.Entities[m.Entity].Angle, newState.Entities[m.Entity].Pos, newState.Entities[m.Entity].Angle, ) } } } } if seenTime { anyFrame := false for n := range newState.Entities { newState.Entities[n].Visible = newState.SeenEntity[uint16(n)] } newState.Entities[0].Visible = true // World. if oldState != nil { if *verbose { fmt.Printf("Saw time, outputting frames between %g and %g\n", oldState.Time, newState.Time, ) } for _, t := range genTimeFrames(float64(oldState.Time), float64(newState.Time), *fps) { // TODO: Only generate frames if client state is 2. if *verbose { log.Printf("Generating frame %d", frameNum) } generateFrame(p, *outDir, oldState, newState, frameNum, t, *cameraLight, *radiosity, *threesixty) anyFrame = true frameNum++ } } // Only wipe old state if we generate any frame at all. if oldState == nil || anyFrame { oldState = newState.Copy() newState.SeenEntity = make(map[uint16]bool) } } } }
func convert(p pak.MultiPak, args ...string) { fs := flag.NewFlagSet("convert", flag.ExitOnError) fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s -pak pak0,pak1,... convert [options]\n", os.Args[0]) fs.PrintDefaults() } outDir := fs.String("out", ".", "Output directory.") retexturePack := fs.String("retexture", "", "Path to retexture pack.") flatColor := fs.String("flat_color", "<0.25,0.25,0.25>", "") textures := fs.Bool("textures", true, "Use textures.") lights := fs.Bool("lights", false, "Export lights.") maps := fs.String("maps", ".*", "Maps regex.") fs.Parse(args) re, err := regexp.Compile(*maps) if err != nil { log.Fatalf("Maps regex %q invalid: %v", *maps, err) } //errors := []string{} os.Mkdir(*outDir, 0755) for _, mf := range p.List() { if path.Ext(mf) != ".bsp" { continue } if !re.MatchString(mf) { continue } func() { o, err := p.Get(mf) if err != nil { log.Fatalf("Getting %q: %v", mf, err) } b, err := bsp.Load(o) if err != nil { log.Fatalf("Loading %q: %v", mf, err) } mkdirP(*outDir, mf) fn := fmt.Sprintf(path.Join(mf, "level.inc")) of, err := os.Create(path.Join(*outDir, fn)) if err != nil { log.Fatalf("Model create of %q fail: %v", fn, err) } defer of.Close() m, err := b.POVTriangleMesh(bsp.ModelMacroPrefix(mf), *textures, *flatColor) if err != nil { log.Fatalf("Making mesh of %q: %v", mf, err) } fmt.Fprintln(of, m) if *lights { fmt.Fprintln(of, b.POVLights()) } if *textures { for n, texture := range b.Raw.MipTexData { fn := path.Join(*outDir, mf, fmt.Sprintf("texture_%d.png", n)) retexFn, retex := retexture(*retexturePack, mf, b.Raw.MipTex[n], texture) if retex { if err := os.Symlink(retexFn, fn); err != nil { log.Fatalf("Failed to symlink %q to %q for texture pack: %v", fn, retexFn, err) } continue } func() { of, err := os.Create(fn) if err != nil { log.Fatalf("Texture create of %q fail: %v", fn, err) } defer of.Close() if err := (&png.Encoder{CompressionLevel: pngCompressionLevel}).Encode(of, texture); err != nil { log.Fatalf("Encoding texture to png: %v", err) } }() } } }() } }