public bool ConnectHair(SharedWorld world, Scene scene) { Skeleton hairskel = null; Skeleton bodyskel = null; Scene displayScene = world.GetScene(); try { bodyskel = currentAvatar.BodyPoser; if (bodyskel == null) { SharedWorld.LogError("MagicMirror: Cannot connect hair - avatar skeleton missing"); return(false); } hairskel = currentAvatar.ConnectHair(displayScene.Engines); if (hairskel == null) { SharedWorld.LogError("MagicMirror: could not connect hair " + scene.Name); return(false); } } catch (Exception ex) { SharedWorld.LogError("MagicMirror: exception connecting hair " + ex.Message); return(false); } return(true); }
/*! * Plays the named animation on the current avatar. * The animation will not be played if it has not already been loaded. * @param name name of animation to play * @param blend time in seconds to blend to this animation (0 = no blending) * * @see LoadAnimation PauseAnimation */ public virtual void PlayAnimation(String name, float blend) { SharedWorld world = SharedWorld.Get(); if (nowPlaying != null) { return; } try { Group g = scriptor.Find(name + '.', Group.FIND_START | Group.FIND_CHILD); world.SuspendScene(); if (g != null) { scriptor.End(); nowPlaying = g as Engine; scriptor.Begin(g.Name); } else { nowPlaying = null; } } catch (Exception ex) { SharedWorld.LogError("PlayAnimation EXCEPTION " + ex.Message); nowPlaying = null; } world.ResumeScene(); }
protected override void OnStartup(StartupEventArgs e) { Canvas3D.UsePhysics = true; Canvas3D.Debug = 1; VixWorld = new SharedWorld(); base.OnStartup(e); }
public bool SaveCloth() { Model parent; Model tmproot; Model clothroot = (Model)_root.Find(BaseName + "." + BaseName, Group.FIND_EXACT | Group.FIND_DESCEND); bool rc; if (clothroot == null) { SharedWorld.LogError("Cannot find cloth model " + BaseName + "." + BaseName); return(false); } parent = clothroot.Parent(); clothroot.Remove(false); tmproot = new Model(); tmproot.Name = BaseName + ".root"; tmproot.Append(clothroot); rc = SharedWorld.Get().SaveAsVix(tmproot, BaseName + ".vix"); if (!rc) { SharedWorld.LogError("Cannot save cloth meshes " + BaseName + ".vix"); } clothroot.Remove(false); parent.Append(clothroot); return(rc); }
public bool SaveAnimation(MeshAnimator meshanim) { String name = AnimName; bool rc; Engine simroot; Engine oldroot; if (meshanim == null) { return(false); } if (BaseName != null) { name += "_" + BaseName; } oldroot = meshanim.Parent(); meshanim.Remove(false); simroot = new Engine(); simroot.Name = name + ".simroot"; meshanim.Stop(); meshanim.Disable(MeshAnimator.RECORD, Engine.CONTROL_CHILDREN); simroot.Append(meshanim); rc = SharedWorld.Get().SaveAsVix(simroot, name + ".vix"); if (!rc) { SharedWorld.LogError("Cannot save cloth animations " + name + ".vix"); } meshanim.Remove(false); oldroot.Append(meshanim); return(rc); }
/* * Vixen event handler. Responds to selection events: * Event.SELECT shape picked in 3D scene * Event.DESELECT nothing picked in 3D scene * Event.ENTER 3D object enters trigger area * Calls the OnPick function to handle the selection. */ public override void OnVixen(Event ev, SharedWorld world) { int code = ev.Code; if (code == Event.SELECT) { try { PickEvent pe = ev as PickEvent; Shape picked = pe.Target as Shape; OnPick(picked); } catch (Exception) { } } else if (code == Event.ENTER) { try { TriggerEvent te = ev as TriggerEvent; Shape picked = te.Target as Shape; OnPick(picked); } catch (Exception) { } } else if (code == Event.DESELECT) { OnPick(null); } base.OnVixen(ev, world); }
public override void OnSceneLoad(SharedWorld world, Scene scene, String scenefile) { if (!sceneLoaded && (cameraOutput == null) && (scenefile == interiorRoot.FileName)) { if (masterKinect != null) { cameraOutput = MakeCameraOutputShape(scene.Camera, true); sceneRoot.Append(cameraOutput); cameraOutput.Active = true; SharedWorld.Trace("Scene: " + sceneRoot.Name + " -> child " + cameraOutput.Name + "\n"); } if (frontAnimTrigger != null) { Box3 b = new Box3(-2.0f, 0.0f, -0.05f, 2.0f, 3.0f, 2.0f); frontAnimTrigger.SetGeoBox(b); frontAnimTrigger.Options = Trigger.BOX; frontAnimTrigger.SetFlags((uint)SharedObj.DOEVENTS); frontAnimTrigger.Active = true; } } base.OnSceneLoad(world, scene, scenefile); }
protected override void OnInitialized(System.EventArgs e) { SharedWorld world; string fname; if (scene == null) { scene = new AvatarScene(); } base.OnInitialized(e); world = SharedWorld.Get(); if (MediaDir == null) { MediaDir = world.GetMediaDir(); } fname = world.FileName; if ((fname != null) && fname.ToLower().EndsWith(".json")) { ConfigOpts = LoadConfig(fname); } else if (ConfigFile != null) { ConfigOpts = LoadConfig(ConfigFile); } if (ConfigOpts.mediadir != null) { MediaDir = ConfigOpts.mediadir; } Scene.RenderOptions = ConfigOpts.render; }
/*! * @param world current world * @param scene avatar which finished loading * * Called when an avatar has finished loading. * This function always invokes the LoadAvatarEvent handler. */ public virtual void OnAvatarLoad(SharedWorld world, Scene scene) { Skeleton skel = ConnectAvatar(world, scene); if (skel == null) { return; } SharedWorld.Trace("Loaded avatar, creating closet"); if (closet == null) { closet = new Closet(garmentRoot, skel); closet.scriptor = scriptor; } if (config.interior != null) { LoadScene(Path.Combine(config.mediadir, config.interior)); } if (config.closet != null) { LoadCloset(Path.Combine(config.mediadir, config.closet)); } if (config.hair != null) { LoadHair(Path.Combine(config.mediadir, config.hair)); } if (LoadAvatarEvent != null) { LoadAvatarEvent(currentAvatar.Name); } }
protected override void OnStartup(StartupEventArgs e) { VixWorld = new SharedWorld(); Canvas3D.UsePhysics = true; Canvas3D.StartVixen(VixWorld); base.OnStartup(e); }
protected override void OnSceneChange(SharedWorld world, Scene scene) { bool firstTime = !sceneLoaded; base.OnSceneChange(world, scene); if (firstTime && (masterKinect != null)) { masterKinect.SetFlags((uint)SharedObj.DOEVENTS); masterKinect.Options = (int)BodyTracker.TRACK_FRONT_ONLY | (int)BodyTracker.TRACK_SKELETON; world.Observe(Event.TRACK); } }
/*! * Hides the named garment if it is currently draped on the avatar. * * @see ShowGarment LoadGarment */ public virtual void HideGarment(String name) { Garment g = closet.Find(name); if (g != null) { g.Hide(); } else { SharedWorld.LogError("Cannot find garment " + name); } }
/* * void LoadAnimations(dynamic avatarconfig) * Load the mesh animations associated with this garment. * @param avatarconfig "avatar" section of the config file * */ public void LoadAnimations(dynamic avatarconfig) { dynamic anims = (this as dynamic).animation; char[] delims = { (char)'/', (char)'\\', (char)'.' }; dynamic g = this; String garment_name = g.name; if (anims == null) { return; } String avatar_name = avatarconfig.rig + ".skeleton.anim"; foreach (string s in anims) { String base_name = Path.GetFileNameWithoutExtension(s); String script = ""; if (s.IndexOfAny(delims) < 0) { continue; } if (!base_name.EndsWith("_" + garment_name)) { throw new FileLoadException("Incorrect animation naming in closet file, animation names must end with garment name suffix", s); } String anim_name = base_name.Substring(0, base_name.Length - garment_name.Length - 1); String meshanim_name = g.name + ".meshanim"; String anim_eng_name = base_name + '.' + meshanim_name + ".anim"; enableAnims += "enable " + anim_eng_name + "\n"; disableAnims += "disable " + anim_eng_name + "\n"; if (s.EndsWith("xml")) { Animator anim = scriptor.MakeAnim(anim_eng_name, clothMesh, false); anim.SetEngineName(meshanim_name); anim.SetFileName(s); SharedWorld.Get().Observe(Event.LOAD_SCENE, anim); AvatarScene.LoadMayaCache(g, s, null, scriptor); } else { script += "load " + s + " " + meshanim_name + " -s -t " + garment_name + "." + garment_name + "\n"; } script += "onevent loadscene " + anim_eng_name + ", begin " + anim_eng_name + " -with " + anim_name + "." + avatar_name; scriptor.Exec(script); Console.WriteLine("LoadAnimations: " + script); } }
protected override Skeleton ConnectAvatar(SharedWorld world, Scene scene) { Skeleton skeleton = base.ConnectAvatar(world, scene); if ((skeleton != null) && (outfitSelector != null) && (typeof(TriggerSelector).IsAssignableFrom(outfitSelector.GetType()))) { TriggerSelector tmp = outfitSelector as TriggerSelector; tmp.AddCollider(currentAvatar.RightHand); tmp.AddCollider(currentAvatar.LeftHand); } return(skeleton); }
/*! * @param ev Vixen event to handle. * @param world current world * Handles vixen events which come from the body tracker. * This function also calls event handlers for BodyTrackEvents. */ public override void OnVixen(Event ev, SharedWorld world) { int code = ev.Code; if (code == Event.TRACK) { TrackEvent kev = (TrackEvent)ev; if (kev.Type == TrackEvent.NEW_USER) { OnNewUser(kev.UserID); } else if (kev.Type == TrackEvent.START_BODY_TRACK) { OnStartTrack(kev.UserID); } else if (kev.Type == TrackEvent.PAUSE_BODY_TRACK) { OnPauseTrack(kev.UserID); } else if (kev.Type == TrackEvent.STOP_BODY_TRACK) { OnStopTrack(kev.UserID); } else if (kev.Type == TrackEvent.INIT_DONE) { OnSensorInit(); } else if (kev.Type == TrackEvent.USER_TURN) { OnUserTurn(kev.UserID, kev.Position); } } else if (code == Event.ENTER && enableAnimation) { try { TriggerEvent te = ev as TriggerEvent; if (te.Sender.SameAs(frontAnimTrigger)) { RandomAnimation("front", blendtime); } } catch (Exception) { } } base.OnVixen(ev, world); }
protected void AddMeshAnimators(Model root, Engine simroot) { try { if (root.IsClass((uint)SerialID.VX_Shape)) { Vixen.Shape shape = root as Vixen.Shape; Vixen.Geometry geo = shape.Geometry; if ((geo != null) && (geo.GetNumVtx() > 0)) { MeshAnimator meshanim; if (simroot.IsClass((uint)SerialID.VX_MeshAnimator)) { meshanim = simroot as MeshAnimator; } else { meshanim = new MeshAnimator(); meshanim.Name = root.Name + ".meshanim"; } meshanim.Target = geo; meshanim.Control = Engine.CONTROL_CHILDREN; meshanim.TimeInc = TimeInc; meshanim.Active = false; SharedWorld.Trace(meshanim.Name + " -> " + shape.Name); if (simroot != meshanim) { simroot.Append(meshanim); simroot = meshanim; } } } } catch (Exception ex) { SharedWorld.LogError(ex.Message); } root = root.First(); while (root != null) { AddMeshAnimators(root, simroot); root = root.Next(); } }
public bool SaveAnimation() { String name = AnimName; MeshAnimator tmp; bool rc; if (_simroot == null) { return(false); } if (BaseName != null) { if (name != null) { name += "_" + BaseName; } else { name = BaseName; } } if (name == null) { name = "default"; } tmp = _simroot.First() as MeshAnimator; if (tmp == null) { return(false); } _simroot.Name = name + ".simroot"; tmp.Name = name + "." + BaseName + ".meshanim"; tmp.Stop(); tmp.Disable(MeshAnimator.RECORD, Engine.CONTROL_CHILDREN); SetTarget(null); rc = SharedWorld.Get().SaveAsVix(_simroot, name + ".vix"); if (!rc) { SharedWorld.LogError("Cannot save cloth animations " + name + ".vix"); } SetTarget(_root); Clear(); return(rc); }
/*! * Pauses the currently playing animation. * * @see LoadAnimation PlayAnimation */ public virtual void PauseAnimation(String name) { try { if (name == null) { scriptor.End(); } else { scriptor.End(name); } nowPlaying = null; } catch (Exception ex) { SharedWorld.LogError("PauseAnimation EXCEPTION " + ex.Message); } }
/* * Event.LOADSCENE handler - comes here when 3D scene loaded. * If a user interface scene is loaded (name contains "ui_") * bind the UI scene to the Selector for picking outfits. */ public override void OnSceneLoad(SharedWorld world, Scene scene, String scenefile) { System.String name = scene.Name.ToLower(); if (name.Contains("ui_")) { Model iconRoot = uiRoot.Find(".selectable", Group.FIND_DESCEND | Group.FIND_END) as Model; SharedWorld.Trace("Loaded " + name); if (iconRoot != null) { RaiseSceneLoadEvent(name, scenefile); if (outfitSelector != null) { outfitSelector.SetTarget(iconRoot); } return; } } base.OnSceneLoad(world, scene, scenefile); }
/*! * @param world current world * @param scene new scene which has replaced current 3D scene * * Called when the 3D scene is replaced with completely new content. * If this is the first scene change, the event was generated during * initialization and the InitSceneEvent handler is invoked. * For any scene change the SetSceneEvent handler is invoked (not * just the first one). */ protected virtual void OnSceneChange(SharedWorld world, Scene scene) { if (scene.SameAs(mainScene)) { world.Observe(Event.ENTER); world.Observe(Event.LEAVE); world.Observe(Event.STOP); world.Observe(Event.SELECT); world.Observe(Event.DESELECT); world.Observe(Event.LOAD_TEXT); if (cameraController != null) { world.Observe(Event.NAVINPUT, cameraController); world.Observe(Event.NAVIGATE, cameraController); cameraController.Target = scene.Camera; SharedWorld.Trace("MagicMirror: " + cameraController.Name + " -> target " + scene.Camera.Name + "\n"); } if (navigator != null) { world.Observe(Event.MOUSE, navigator); world.Observe(Event.NAVINPUT, navigator); } var a = config.avatar; if (a != null) { if ((a.name != null) && (a.filename != null)) { LoadAvatar(a.name, a.filename); } } if (InitSceneEvent != null) { InitSceneEvent(); } return; } if (SetSceneEvent != null) { SetSceneEvent(scene.Name); } }
/*! * Display the named garment on the avatar. This function will only display the clothing * if it has already been loaded. * * @see LoadGarment HideGarment */ public virtual void ShowGarment(String name) { Garment g = closet.Find(name); if (g != null) { if (!g.IsLoaded) { g.Load(null); } else { g.Show(); } currentGarment = g; } else { SharedWorld.LogError("Cannot find garment " + name); } }
protected void AddMeshSource(Model srcroot, Engine dstroot) { if (srcroot == null) { return; } if (dstroot.IsClass((uint)SerialID.VX_MeshAnimator)) { try { MeshAnimator meshanim = dstroot as MeshAnimator; Shape dstshape = meshanim.Target as Shape; String name = dstshape.Name; Shape srcshape; Mesh mesh; VertexArray verts; int p = name.IndexOf('.'); if (p > 0) { name = name.Substring(p); } srcshape = srcroot.Find(name, Group.FIND_DESCEND | Group.FIND_END) as Shape; mesh = srcshape.Geometry as Mesh; verts = mesh.Vertices; SharedWorld.Trace(meshanim.Name + " -> " + srcshape.Name); meshanim.SetSource(-1, verts); } catch (Exception ex) { SharedWorld.LogError(ex.Message); } } dstroot = dstroot.First() as Engine; while (dstroot != null) { AddMeshSource(srcroot, dstroot); dstroot = dstroot.Next() as Engine; } }
protected override void OnInitialized(System.EventArgs e) { if (KinectConfig != null) { MainWindow mainwin = (MainWindow)Parent; //mainwin.FullScreen(true); try { scene = new KioskScene(GetMediaPath(KinectConfig)); } catch (System.IO.FileNotFoundException exc) { SharedWorld.LogError(exc.Message); scene = new KioskScene(); } } else { scene = new KioskScene(); } base.OnInitialized(e); }
public Garment OnLoad(Scene scene, SharedWorld world, dynamic avatarconfig) { Garment g = Find(scene.Name); dynamic tmp = g; if (g == null) { SharedWorld.LogError(scene.Name + " not a garment - ignoring this load event"); return(null); } if (g.IsLoaded) { SharedWorld.LogError(scene.Name + " already loaded - ignoring this load event"); return(g); } g.Connect(world, scene, avatarconfig); if ((scriptor != null) && (tmp.script != null)) { scriptor.LoadScript(tmp.script); } Select(g); return(g); }
/*! * Customizes the 3D user interface to the current closet. * The 3D UI has a 3D shape corresponding to each item that can * be selected. The name and texture of these shapes are * changed to correspond to individual garments in the closet. * If there are more clothes in the closet than items in the UI, * some clothing won't be selectable. * * The 3D art must adhere to the following structure: * Model "uifile.selectable" * Shape "uifile.icon_item1" (background) * Shape "uifile.plane_item1" (thumbnail with texture) * Shape "uifile.icon_item2" (background) * Shape "uifile.plane_item2" (thumbnail with texture) * ... */ public virtual void AttachCloset() { Model cur = UIRoot.First(); foreach (dynamic g in Clothing) { if (cur == null) { return; } try { string name = cur.Name; int i = name.IndexOf(".icon_"); if (i > 0) { Shape plane = cur.First() as Shape; name = name.Substring(0, i + 6) + g.Name; cur.Name = name; name = plane.Name; i = name.IndexOf(".plane_"); if (i > 0) { plane.Name = name.Substring(0, i + 7) + g.Name; Sampler sampler = plane.Appearance.GetSampler(0); sampler.Texture.Load(g.IconFile); SharedWorld.Trace(plane.Name + " replacing texture " + g.IconFile); } } } catch (Exception ex) { SharedWorld.LogError("AttachCloset " + ex.Message); } cur = cur.Next(); } }
/*! * Performs selection highlighting for the 3D shape picked. */ public virtual bool Select(Shape picked) { System.String name = picked.Name; if (selectedItem != null) // deselect the current item { // by puttings it's former appearance back if ((picked != null) && (selectedItem.Name == name)) { return(false); } SharedWorld.Trace(selectedItem.Name + " unselected\n"); selectedItem.Appearance = selectedAppear; selectedItem = null; // now nothing is selected selectedAppear = null; } selectedItem = picked; if (picked != null) { SharedWorld.Trace(name + " picked\n"); selectedAppear = selectedItem.Appearance; selectedItem.Appearance = Hilite; return(true); } return(false); }
/*! * Pauses the currently playing animation. * * @see LoadAnimation PlayAnimation */ public void PauseAnimation(string name) { try { Viewer3D viewer = Viewer as Viewer3D; string skelname = ConnectSkeleton(); Scriptor scp = AnimScriptor; if (skelname != null) { if (name != null) { scp.End(name + skelname); } else { scp.End(_animName); } } } catch (Exception ex) { SharedWorld.LogError("PauseAnimation EXCEPTION " + ex.Message); } }
/* * Reads a DAZ Studio DSF file with a pose in it and produces * a Vixen Pose object for this avatar's skeleton. * @param posename name of pose */ public Pose ReadPose(System.String posename) { System.String filename = "pose/" + posename + "pose.dsf"; Hashtable poseinfo = new Hashtable(); try { /* * Parse the DAZ Studio pose file and extract the rotations * for each bone into a hash table */ using (StreamReader posefile = new StreamReader(filename)) { System.String line; Regex pattern = new Regex("([a-zA-Z0-9]+)" + Regex.Escape(":?") + "rotation/([xyz])"); while ((line = posefile.ReadLine()) != null) { Match match = pattern.Match(line); System.String name; System.String axis; if (!match.Success) { continue; } name = match.Groups[1].ToString(); axis = match.Groups[2].ToString(); line = posefile.ReadLine(); int p = line.IndexOf("[ 0, "); if (p > 0) { System.String s = line.Substring(p + 5); float angle; Quat rot; Quat q = null; s = s.Substring(0, s.IndexOf("]")); angle = float.Parse(s); if (angle == 0) { continue; } angle *= (float)Math.PI / 180.0f; if (axis == "x") { q = new Quat(Model.XAXIS, angle); } else if (axis == "y") { q = new Quat(Model.YAXIS, angle); } else if (axis == "z") { q = new Quat(Model.ZAXIS, angle); } if (q == null) { continue; } if (poseinfo.Contains(name)) { rot = poseinfo[name] as Quat; rot.Mul(rot, q); } else { poseinfo.Add(name, q); } } } } /* * Convert hash table with rotations into a Pose. * Map DAZ bone names into Vixen bone names. */ Pose pose = new Pose(BodyPoser); foreach (DictionaryEntry entry in poseinfo) { System.String key = entry.Key.ToString(); System.String bonename = key; Quat q = entry.Value as Quat; int boneindex; if (key == "abdomen") { bonename = "Torso"; } else if (key == "rHand") { bonename = "RightWrist"; } else if (key == "lHand") { bonename = "LeftWrist"; } else if (key == "rShldr") { bonename = "RightShoulder"; } else if (key == "lShldr") { bonename = "LeftShoulder"; } else if (key == "rForeArm") { bonename = "RightElbow"; } else if (key == "lForeArm") { bonename = "LeftElbow"; } else if (key == "rShin") { bonename = "RightKnee"; } else if (key == "lShin") { bonename = "LeftShin"; } else if (key == "rThigh") { bonename = "RightHip"; } else if (key == "lThigh") { bonename = "LeftHip"; } else if (key == "lFoot") { bonename = "LeftAnkle"; } else if (key == "rFoot") { bonename = "RightAnkle"; } boneindex = BodyPoser.GetBoneIndex(bonename); if (boneindex >= 0) { pose.SetLocalRotation(boneindex, q); SharedWorld.Trace(bonename + " " + q.x + " " + q.y + " " + q.z + " " + q.w + "\n"); } } return(pose); } catch (Exception ex) { Canvas3D.LogError(ex.Message + " Cannot read pose file " + filename); return(null); } }
/* * Reads a DAZ Studio PZ2 file with a pose in it and produces * a Vixen Pose object for this avatar's skeleton. * @param posename file name containing pose */ public Pose ReadPose(System.String name) { Hashtable poseinfo = new Hashtable(); int level = 0; int numbones = 0; int offset = -1; try { /* * Parse the DAZ Studio pose file and extract the rotations * for each bone into a hash table */ using (StreamReader posefile = new StreamReader("pose/" + name + ".pz2")) { System.String line; System.String bonename = ""; char[] space = new char[] { ' ' }; float xrot = 0; float yrot = 0; float zrot = 0; while ((line = posefile.ReadLine().Trim()) != null) { string[] words = line.Split(space); string opcode; if (line == "") { continue; } if (line.EndsWith("{")) // open bracket increases nesting leve4l { ++level; continue; } if (line.EndsWith("}")) // close bracket decreases nesting level { --level; if (level == 0) { break; } continue; } if (words.Length == 0) // nothing parsed? { continue; } opcode = words[0]; if (words.Length < 1) // has an argument? { continue; } if (opcode == "actor") // found a new bone? { bonename = words[1]; // save the bone name xrot = 0; yrot = 0; zrot = 0; ++numbones; } else if (opcode == "rotateX") // X rotation coming up? { offset = 0; } else if (opcode == "rotateY") // Y rotation coming up? { offset = 1; } else if (opcode == "rotateZ") // Z rotation coming up? { offset = 2; } else if (opcode == "k") // is it a key? { float time = float.Parse(words[1]); // parse the time float angle = float.Parse(words[2]); // parse the rotation angle in degrees Quat q; angle *= (float)Math.PI / 180; switch (offset) { case 0: xrot = angle; break; case 1: yrot = angle; break; case 2: zrot = angle; if ((xrot == 0) && (yrot == 0) && (zrot == 0)) { break; } q = new Quat(Model.XAXIS, xrot); if (yrot != 0) { q *= new Quat(Model.YAXIS, yrot); } if (zrot != 0) { q *= new Quat(Model.ZAXIS, yrot); } q.Normalize(); offset = -1; if (q.IsEmpty()) { break; } if (bonename.Length > 0) // save rotation for the bone { poseinfo[bonename] = q; SharedWorld.Trace(bonename + " " + q.x + " " + q.y + " " + q.z + " " + q.w + "\n"); } break; } } } } if (numbones != BodyPoser.NumBones) { Canvas3D.LogError(System.String.Format("Pose with {0} bones does not match skeleton with {1} bones", numbones, BodyPoser.NumBones)); } /* * Convert hash table with rotations into a Pose. */ Pose pose = new Pose(BodyPoser); foreach (DictionaryEntry entry in poseinfo) { System.String key = entry.Key.ToString(); System.String bonename = key; Quat q = entry.Value as Quat; int boneindex; boneindex = BodyPoser.GetBoneIndex(bonename); if (boneindex >= 0) { pose.SetLocalRotation(boneindex, q); SharedWorld.Trace(bonename + " " + q.x + " " + q.y + " " + q.z + " " + q.w + "\n"); } else { Canvas3D.LogError("Cannot find bone " + bonename + " in skeleton "); } } return(pose); } catch (Exception ex) { Canvas3D.LogError(ex.Message + " Cannot read pose file " + name); return(null); } }
/* * Reads a DAZ Studio PZ2 file with a pose in it and produces * a Vixen Pose object for this avatar's skeleton. * @param posename file name containing pose */ public Pose ReadPose(System.String name) { ArrayList bones = new ArrayList(); ArrayList positions = new ArrayList(); int level = 0; int numbones = 0; Int32 numframes = 0; bool parsing_motion = false; System.String bonename = ""; Pose bindpose = BodyPoser.BindPose; Pose pose = new Pose(BodyPoser); float x, y, z; pose.Copy(bindpose); try { /* * Parse the DAZ Studio pose file and extract the rotations * for each bone into a hash table */ using (StreamReader posefile = new StreamReader("pose/" + name + ".bvh")) { System.String line; char[] space = new char[] { ' ' }; while ((line = posefile.ReadLine().Trim()) != null) { string[] words = line.Split(space); string opcode; if (line == "") { continue; } /* * Parsing motion for each frame. * Each line in the file contains the root joint position and rotations for all joints. */ if (parsing_motion) { int nbones = 0; if (words[0].StartsWith("Frame")) { continue; } x = float.Parse(words[0]); // root bone position y = float.Parse(words[1]); z = float.Parse(words[2]); pose.SetPosition(new Vec3(x, y, z)); for (int i = 3; i < words.Length; i += 3) { bonename = bones[nbones] as System.String; int boneindex = BodyPoser.GetBoneIndex(bonename); ++nbones; if (boneindex >= 0) { Quat q, b; z = float.Parse(words[i]); // Z, Y, X rotation angles y = float.Parse(words[i + 1]); x = float.Parse(words[i + 2]); if ((x == 0) && (y == 0) && (z == 0)) { continue; } if (true) { q = new Quat(Model.ZAXIS, z * (float)Math.PI / 180); q *= new Quat(Model.YAXIS, x * (float)Math.PI / 180); q *= new Quat(Model.XAXIS, y * (float)Math.PI / 180); } else { q = new Quat(Model.ZAXIS, y * (float)Math.PI / 180); q *= new Quat(Model.YAXIS, x * (float)Math.PI / 180); q *= new Quat(Model.XAXIS, z * (float)Math.PI / 180); } q.Normalize(); b = pose.GetLocalRotation(boneindex); q *= b; pose.SetLocalRotation(boneindex, q); SharedWorld.Trace(bonename + " " + q.x + " " + q.y + " " + q.z + " " + q.w + "\n"); } else { Canvas3D.LogError("Cannot find bone " + bonename + " in skeleton "); } } break; } /* * Parsing skeleton definition with joint names and positions. */ else { if (words.Length < 1) // has an argument? { continue; } opcode = words[0]; if ((opcode == "ROOT") || // found root bone? (opcode == "JOINT")) // found any bone? { bonename = words[1]; // save the bone name ++numbones; } else if (opcode == "OFFSET") // bone position { float xpos = float.Parse(words[1]); float ypos = float.Parse(words[2]); float zpos = float.Parse(words[3]); if (bonename.Length > 0) // save position for the bone { bones.Add(bonename); positions.Add(new Vec3(xpos, ypos, zpos)); SharedWorld.Trace(bonename + " " + xpos + " " + ypos + " " + zpos + "\n"); } bonename = ""; continue; } else if (opcode == "MOTION") { parsing_motion = true; if (numbones != BodyPoser.NumBones) { Canvas3D.LogError(System.String.Format("Pose with {0} bones does not match skeleton with {1} bones", numbones, BodyPoser.NumBones)); } } } } } return(pose); } catch (Exception ex) { Canvas3D.LogError(ex.Message + " Cannot read pose file " + name); return(null); } }