public static XElement generateXmlByItem(RenderBase item) { XElement xml = new XElement("Node"); item.setAttrToXml(ref xml); return(xml); }
/// <summary> /// Creates a Index Buffer for a Mesh, trying to repeat as less Vertices as possible. /// </summary> /// <param name="mesh">The Mesh that should be optimized</param> /// <returns></returns> public static optimizedMesh optimizeMesh(RenderBase.OMesh mesh) { optimizedMesh output = new optimizedMesh(); output.hasNormal = mesh.hasNormal; output.hasTangent = mesh.hasTangent; output.hasColor = mesh.hasColor; output.hasNode = mesh.hasNode; output.hasWeight = mesh.hasWeight; output.texUVCount = mesh.texUVCount; for (int i = 0; i < mesh.vertices.Count; i++) { bool found = false; for (int j = 1; j <= optimizerLookBack; j++) { int p = output.vertices.Count - j; if (p < 0 || p >= output.vertices.Count) break; if (output.vertices[p].Equals(mesh.vertices[i])) { output.indices.Add((uint)p); found = true; break; } } if (!found) { output.vertices.Add(mesh.vertices[i]); output.indices.Add((uint)(output.vertices.Count - 1)); } } return output; }
public async Task <string> RenderContent <T>(T content, string name = null) where T : ContentBase { var renderData = new RenderBase <T>(_hostingOptions, content); var html = await _viewRender.Render <RenderBase <T>, T>(name ?? typeof(T).Name, renderData); return(html); }
public OModelExportForm(RenderBase.OModelGroup models, int modelIndex = -1) { InitializeComponent(); mdls = models; mdlIndex = modelIndex; if (modelIndex > -1) TxtModelName.Text = mdls.model[mdlIndex].name; }
public OTextureExportForm(RenderBase.OModelGroup models, int textureIndex = -1) { InitializeComponent(); mdls = models; texIndex = textureIndex; if (textureIndex > -1) TxtTextureName.Text = mdls.texture[texIndex].name; }
/// <summary> /// Calculates the minimun and maximum vector values for a Model. /// </summary> /// <param name="mdl">The target model</param> /// <param name="vertex">The current mesh vertex</param> public static void calculateBounds(RenderBase.OModel mdl, RenderBase.OVertex vertex) { if (vertex.position.x < mdl.minVector.x) mdl.minVector.x = vertex.position.x; if (vertex.position.x > mdl.maxVector.x) mdl.maxVector.x = vertex.position.x; if (vertex.position.y < mdl.minVector.y) mdl.minVector.y = vertex.position.y; if (vertex.position.y > mdl.maxVector.y) mdl.maxVector.y = vertex.position.y; if (vertex.position.z < mdl.minVector.z) mdl.minVector.z = vertex.position.z; if (vertex.position.z > mdl.maxVector.z) mdl.maxVector.z = vertex.position.z; }
/// <summary> /// Initializes the control with animation data. /// </summary> /// <param name="renderEngine">Renderer used to render the model</param> /// <param name="ctrl">The animation control</param> /// <param name="anms">The list with animations</param> /// <param name="t">The animation type (used on Export/Import options)</param> public void initialize(RenderEngine renderEngine, RenderEngine.animationControl ctrl, RenderBase.OAnimationListBase anms, FileIO.fileType t) { renderer = renderEngine; control = ctrl; animations = anms; type = t; control.FrameChanged += Control_FrameChanged; updateList(); }
public void addNodeInfo(TreeNode node, RenderBase render) { TreeNode chldNode = new TreeNode(); chldNode.Text = render.Name + (render.Tag.Length > 0 ? (":" + render.Tag) : ("")); chldNode.Tag = render.uniqueName; chldNode.SelectedImageIndex = chldNode.ImageIndex = ImageIndexPng; if (render is RenderScene) { this.treeView1.Nodes.Add(chldNode); //List<RenderBase> childItems = (render as TDPanel).ChildItems; //for (int i = childItems.Count - 1; i >= 0; i-- ) //{ // addNodeInfo(chldNode, childItems[i]); //} foreach (RenderBase item in (render as TDPanel).ChildItems) { addNodeInfo(chldNode, item); } chldNode.Expand(); } else if (render is TDPanel) { if ((render as TDPanel).panelPath.Length == 0) { chldNode.SelectedImageIndex = chldNode.ImageIndex = ImageIndexPng; //List<RenderBase> childItems = (render as TDPanel).ChildItems; //for (int i = childItems.Count - 1; i >= 0; i--) //{ // addNodeInfo(chldNode, childItems[i]); //} foreach (RenderBase item in (render as TDPanel).ChildItems) { addNodeInfo(chldNode, item); } } else { chldNode.Text = chldNode.Text + ":" + (render as TDPanel).panelPath; } if (node != null) { node.Nodes.Add(chldNode); } } else { chldNode.SelectedImageIndex = chldNode.ImageIndex = ImageIndexPng; if (node != null) { node.Nodes.Add(chldNode); } } }
/// <summary> /// Interpolates a point between two vectors using Linear Interpolation. /// </summary> /// <param name="a">First vector</param> /// <param name="b">Second vector</param> /// <param name="mu">Value between 0-1 of the interpolation amount</param> /// <returns></returns> public static RenderBase.OVector3 interpolateLinear(RenderBase.OVector3 a, RenderBase.OVector3 b, float mu) { RenderBase.OVector3 output = new RenderBase.OVector3(); output.x = interpolateLinear(a.x, b.x, mu); output.y = interpolateLinear(a.y, b.y, mu); output.z = interpolateLinear(a.z, b.z, mu); return output; }
public override void Undo() { RenderBase item = renderScene.getRenderByUniqueName(uniqueName); if (item == null) { return; } item.removeFromParent(); }
public override void Redo() { RenderBase item = renderScene.getRenderByUniqueName(uniqueName); if (item == null) { return; } item.pos = _finish; }
/// <summary> /// Interpolates a Key Frame from a list of Key Frames. /// </summary> /// <param name="sourceFrame">The list of key frames</param> /// <param name="frame">The frame that should be returned or interpolated from the list</param> /// <returns></returns> public static float getKey(RenderBase.OAnimationKeyFrameGroup sourceFrame, float frame) { switch (sourceFrame.interpolation) { case RenderBase.OInterpolationMode.step: return interpolateStep(sourceFrame.keyFrames, frame); case RenderBase.OInterpolationMode.linear: return interpolateLinear(sourceFrame.keyFrames, frame); case RenderBase.OInterpolationMode.hermite: return interpolateHermite(sourceFrame.keyFrames, frame); default: return 0; //Shouldn't happen } }
public override void Undo() { RenderBase item = renderScene.getRenderByUniqueName(uniqueName); if (item == null) { return; } item.size = _orign; }
public UConstantBuffer(RenderBase rb, int size) { this.RenderBase = rb; Buffer = new Buffer(rb.Device, new BufferDescription() { Usage = ResourceUsage.Dynamic, SizeInBytes = size, BindFlags = BindFlags.ConstantBuffer, CpuAccessFlags = CpuAccessFlags.Write, OptionFlags = ResourceOptionFlags.None, }); }
public override void Redo() { RenderBase item = renderScene.getRenderByUniqueName(parentUnique); if (item == null) { return; } RenderBase undoItem = UIHelper.CEGenerateViewByXml(xml, item); if (undoItem != null) { undoItem.uniqueName = this.uniqueName; } }
public override void SetValue(object component, object value) { if (component is RenderBase) { RenderBase render = component as RenderBase; RenderScene scene = render.getRenderScene(); render.recordOriStatus(); mProp.SetValue(component, value); if (scene == null) { return; } if (mProp.Name == "pos") { scene.commandManager.AddCommand(new CommandMove(scene, render)); } else if (mProp.Name == "size") { scene.commandManager.AddCommand(new CommandResize(scene, render)); } else if (mProp.Name == "anchorPos") { scene.commandManager.AddCommand(new CommandAnchorPos(scene, render)); } else if (mProp.Name == "scale") { scene.commandManager.AddCommand(new CommandScale(scene, render)); } else if (mProp.Name == "Tag") { EventManager.RaiserEvent(Constant.RenderItemChange, scene, null); } scene.checkModifyStatus(); } else { mProp.SetValue(component, value); } }
public static RenderBase CEGenerateItemByName(String type, String path = null, RenderBase parent = null) { RenderBase item = null; try { if (parent != null) { parent.recordChildItems(); } item = generateItemByName(type, path, parent); } catch (NestException ex) { if (parent != null) { parent.recoverChildItems(); } EventManager.RaiserEvent(Constant.StatusInfoChange, null, String.Format("{0} 文件不能嵌套使用", ex.Message)); } return(item); }
/// <summary> /// Exports a model to the Wavefront OBJ format. /// </summary> /// <param name="model">The model to be exported</param> /// <param name="fileName">The output file name</param> /// <param name="modelIndex">The index of the model that should be exported</param> public static void export(RenderBase.OModelGroup model, string fileName, int modelIndex) { StringBuilder output = new StringBuilder(); RenderBase.OModel mdl = model.model[modelIndex]; int faceIndexBase = 1; for (int objIndex = 0; objIndex < mdl.mesh.Count; objIndex++) { output.AppendLine("g " + mdl.mesh[objIndex].name); output.AppendLine(null); output.AppendLine("usemtl " + mdl.material[mdl.mesh[objIndex].materialId].name0 + ".png"); output.AppendLine(null); MeshUtils.optimizedMesh obj = MeshUtils.optimizeMesh(mdl.mesh[objIndex]); foreach (RenderBase.OVertex vertex in obj.vertices) { output.AppendLine("v " + getString(vertex.position.x) + " " + getString(vertex.position.y) + " " + getString(vertex.position.z)); output.AppendLine("vn " + getString(vertex.normal.x) + " " + getString(vertex.normal.y) + " " + getString(vertex.normal.z)); output.AppendLine("vt " + getString(vertex.texture0.x) + " " + getString(vertex.texture0.y)); } output.AppendLine(null); for (int i = 0; i < obj.indices.Count; i += 3) { output.AppendLine( string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", faceIndexBase + obj.indices[i], faceIndexBase + obj.indices[i + 1], faceIndexBase + obj.indices[i + 2])); } faceIndexBase += obj.vertices.Count; output.AppendLine(null); } File.WriteAllText(fileName, output.ToString()); }
private static RenderBase generateViewByPath(String path, RenderBase parent = null) { String absPath = UIProject.Instance().GetRealFile(path); String content = FileHelper.GetFullContent(absPath); XElement xml = XmlHelper.Parse(content); if (xml == null) { return(null); } if (parent != null && path.Length > 0 && parent.checkParentPathNest(UIProject.Instance().GetRelativePath(absPath))) { throw new NestException(UIProject.Instance().GetRelativePath(absPath)); } xml.SetAttributeValue("Name", Constant.TypePanel); RenderBase render = generateViewByXml(xml, parent); if (render is TDPanel) { (render as TDPanel).panelPath = UIProject.Instance().GetRelativePath(absPath); } return(render); }
private void MainForm_Load(object sender, EventArgs e) { // create render instance ..//創建render instance this.Base = new RenderBase();//先去執行構造函數 // create render log instance ..//創建render日志instance this.LogMsg = new RenderEvents(); // append to logs object ..//追加到日志對象 RenderEvents.AppendLog(string.Format("{0}", "initialize render base service has successful.")); // setting list view sort provider ..//設置list view排序provider this.ListView_Render_Status.ListViewItemSorter = ListViewSorter; this.ListViewSorter.Order = SortOrder.Descending; // start read server data information thread ..//開始讀服務器數據信息線程 Thread StateThread = new Thread(new ThreadStart(this.ReadData)); StateThread.Priority = ThreadPriority.BelowNormal; StateThread.Start(); // append to logs object ..//追加到日志對象 RenderEvents.AppendLog(string.Format("{0}", "start data object delegate thread.")); }
private static RenderBase generateViewByXml(XElement xml, RenderBase parent) { if (xml == null) { return(null); } RenderBase item = null; String name = XmlHelper.GetString(xml, "Name"); String path = XmlHelper.GetString(xml, "Path"); if (name.Length > 0) { if (parent != null && path.Length > 0 && parent.checkParentPathNest(path)) { throw new NestException(UIProject.Instance().GetRelativePath(path)); } item = generateItemByName(name, path, parent); if (item == null) { return(item); } item.getAttrByXml(xml); //XElement child = xml.Element("Child"); //if (child != null) //{ // foreach (XElement element in child.Elements("Node")) // { // generateViewByXml(element, item); // } //} item.loadComplete(); } return(item); }
public void SetSelectItem(RenderBase render) { if (render == null) { propGrid.SelectedObject = null; return; } XmlNode tmpXNode = DynamicObj.propXmlDoc.SelectSingleNode("Components/Component[@Name='" + render.Name + "']"); XmlNodeList tmpXPropLst = null; if (tmpXNode != null) { tmpXPropLst = tmpXNode.SelectNodes("Propertys/Property"); } CustomProperty cp = new CustomProperty(render, tmpXPropLst); tmpXNode = DynamicObj.propXmlDoc.SelectSingleNode("Components/Component[@Name='Base']"); if (tmpXNode != null) { tmpXPropLst = tmpXNode.SelectNodes("Propertys/Property"); cp.AddProperty(tmpXPropLst); } propGrid.SelectedObject = cp; }
/// <summary> /// Creates a Quaternion from a Quaternion Vector4. /// </summary> /// <param name="vector">The quaternion vector</param> /// <returns></returns> private Quaternion getQuaternion(RenderBase.OVector4 vector) { return new Quaternion(vector.x, vector.y, vector.z, vector.w); }
public static String generateSrcByItem(RenderBase item) { XElement xml = generateXmlByItem(item); return(xml.ToString()); }
/// <summary> /// Interpolates a point between two vectors using Linear Interpolation. /// </summary> /// <param name="a">First vector</param> /// <param name="b">Second vector</param> /// <param name="mu">Value between 0-1 of the interpolation amount</param> /// <returns></returns> public static RenderBase.OVector4 interpolateLinear(RenderBase.OVector4 a, RenderBase.OVector4 b, float mu) { RenderBase.OVector4 output = new RenderBase.OVector4(); output.x = interpolateLinear(a.x, b.x, mu); output.y = interpolateLinear(a.y, b.y, mu); output.z = interpolateLinear(a.z, b.z, mu); output.w = interpolateLinear(a.w, b.w, mu); return output; }
/// <summary> /// Exports a Model to the Collada format. /// See: https://www.khronos.org/files/collada_spec_1_4.pdf for more information. /// </summary> /// <param name="model">The Model that will be exported</param> /// <param name="fileName">The output File Name</param> /// <param name="modelIndex">Index of the model to be exported</param> /// <param name="skeletalAnimationIndex">(Optional) Index of the skeletal animation</param> public static void export(RenderBase.OModelGroup model, string fileName, int modelIndex, int skeletalAnimationIndex = -1) { RenderBase.OModel mdl = model.model[modelIndex]; COLLADA dae = new COLLADA(); COLLADA daeShiny = new COLLADA(); dae.asset.created = DateTime.Now.ToString("yyyy-MM-ddThh:mm:ssZ"); dae.asset.modified = dae.asset.created; daeShiny.asset.created = DateTime.Now.ToString("yyyy-MM-ddThh:mm:ssZ"); daeShiny.asset.modified = dae.asset.created; bool hasShiny = false; // Attempt to detect packaged textures. See http://www.github.com/Quibilia/Ohana3DS-Transfigured for directions. try { string modelDir; string sDir; string[] texDirs; string[] texFiles; modelDir = Path.GetFileNameWithoutExtension(fileName).Remove(4); sDir = Path.GetDirectoryName(fileName); texDirs = Directory.GetDirectories(Path.Combine(sDir, "../../Textures/")); foreach (string texDir in texDirs) { if (texDir.Contains(modelDir)) { texFiles = Directory.GetFiles(texDir); if (Directory.Exists(texDir.Replace("Textures", "Models/DAE")) == false && texDir.Contains("Xtra") == false) { Directory.CreateDirectory(texDir.Replace("Textures", "Models/DAE")); } bool hasIris = false; foreach (string texFile in texFiles) { if (texFile.Contains("Iris1")) { hasIris = true; } } foreach (string texFile in texFiles) { if (texFile.Contains("Xtra") == false) { Bitmap tempBMP = (Bitmap)Bitmap.FromFile(texFile); if (texFile.Contains("Body") && texFile.Contains("Nor") == false) { int w = tempBMP.Width / 2; Bitmap scaledBMP = new Bitmap(tempBMP, tempBMP.Width / 2, tempBMP.Height); Bitmap reverseBMP = new Bitmap(tempBMP, tempBMP.Width / 2, tempBMP.Height); reverseBMP.RotateFlip(RotateFlipType.RotateNoneFlipX); Bitmap finalBMP = new Bitmap(tempBMP.Width, tempBMP.Height); for (int x = 0; x < scaledBMP.Width; x++) { for (int y = 0; y < scaledBMP.Height; y++) { finalBMP.SetPixel(x, y, scaledBMP.GetPixel(x, y)); } } for (int x = 0; x < reverseBMP.Width; x++) { for (int y = 0; y < reverseBMP.Height; y++) { finalBMP.SetPixel(x + reverseBMP.Width, y, reverseBMP.GetPixel(x, y)); } } if (texFile.Contains("BodyA2") == false && texFile.Contains("BodyB2") == false && texFile.Contains("Body2") == false) { finalBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(finalBMP, texFile.Replace("Textures", "Models/DAE"))); } } else if (texFile.Contains("Iris1")) { Bitmap eyeBMP = (Bitmap)Bitmap.FromFile(texFile.Replace("Iris", "Eye")); foreach (string norFile in texFiles) { if (norFile.Contains("Xtra") == false && norFile.Contains("EyeNor")) { Bitmap thisEye = new Bitmap(eyeBMP.Width / 2, eyeBMP.Height / 4); Bitmap norBMP = (Bitmap)Bitmap.FromFile(norFile); Bitmap thisNor = new Bitmap(norBMP.Width / 4, norBMP.Height / 4); Bitmap finalBMP = new Bitmap(eyeBMP.Width * 2, eyeBMP.Height); int eye = 0; int half = 0; bool reflectEye = false; bool reflectIris = true; bool reflectNor = true; for (int eyeY = 0; eyeY < 4; eyeY++) { eye = 0; for (int eyeX = 0; eyeX < 2; eyeX++) { reflectEye = !reflectEye; reflectNor = !reflectNor; reflectIris = !reflectIris; for (half = 0; half < 2; half++) { for (int x = half * (eyeBMP.Width / 2); x < (half + 1) * (eyeBMP.Width / 2); x++) { for (int y = eyeY * (eyeBMP.Height / 4); y < (eyeY + 1) * (eyeBMP.Height / 4); y++) { thisEye.SetPixel(x - (half * (eyeBMP.Width / 2)), y - (eyeY * (eyeBMP.Height / 4)), eyeBMP.GetPixel(x, y)); } } for (int x = (half * 2) * (norBMP.Width / 4); x < ((half * 2) + 1) * (norBMP.Width / 4); x++) { for (int y = eyeY * (norBMP.Height / 4); y < (eyeY + 1) * (norBMP.Height / 4); y++) { thisNor.SetPixel(x - ((half * 2) * (norBMP.Width / 4)), y - (eyeY * (norBMP.Height / 4)), norBMP.GetPixel(x, y)); } } if (reflectEye == true) { thisEye.RotateFlip(RotateFlipType.RotateNoneFlipX); } reflectEye = !reflectEye; if (reflectNor == true) { thisNor.RotateFlip(RotateFlipType.RotateNoneFlipX); } if (reflectIris == true) { tempBMP.RotateFlip(RotateFlipType.RotateNoneFlipX); reflectIris = false; } // By now, tempBMP, thisEye, and thisNor should all be the same size. for (int x = 0; x < tempBMP.Width; x++) { for (int y = 0; y < tempBMP.Height; y++) { if (tempBMP.GetPixel(x, y).A >= 0x7F && thisNor.GetPixel(x, y).A >= 0x7F) { thisEye.SetPixel(x, y, tempBMP.GetPixel(x, y)); } } } for (int x = eye * (norBMP.Width / 4); x < (eye + 1) * (norBMP.Width / 4); x++) { for (int y = eyeY * (norBMP.Height / 4); y < (eyeY + 1) * (norBMP.Height / 4); y++) { finalBMP.SetPixel(x, y, thisEye.GetPixel(x - (eye * (norBMP.Width / 4)), y - (eyeY * (norBMP.Height / 4)))); } } if (eye == 3) { eye--; } else if (eye == 1) { eye += 2; } else if (eye == 0) { eye++; } else if (eye == 2) { eye -= 2; } } } } finalBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(finalBMP, texFile.Replace("Textures", "Models/DAE"))); } } } else if (texFile.Contains("Mouth1") && texFile.Contains("Nor") == false) { bool hasNormals = false; foreach (string norFile in texFiles) { // If the mouth has a normal file, the UV coordinates expect it split across the image border. if (norFile.Contains("Mouth") && norFile.Contains("Nor")) { hasNormals = true; } } if (hasNormals == true) { Bitmap thisHalf = new Bitmap(tempBMP.Width / 2, tempBMP.Height / 4); Bitmap finalBMP = new Bitmap(tempBMP.Width * 2, tempBMP.Height); for (int halfY = 0; halfY < 4; halfY++) { for (int halfX = 0; halfX < 2; halfX++) { for (int x = halfX * (tempBMP.Width / 2); x < (halfX + 1) * (tempBMP.Width / 2); x++) { for (int y = halfY * (tempBMP.Height / 4); y < (halfY + 1) * (tempBMP.Height / 4); y++) { thisHalf.SetPixel(x - (halfX * (tempBMP.Width / 2)), y - (halfY * (tempBMP.Height / 4)), tempBMP.GetPixel(x, y)); } } for (int x = halfX * (tempBMP.Width / 2); x < (halfX + 1) * (tempBMP.Width / 2); x++) { for (int y = halfY * (tempBMP.Height / 4); y < (halfY + 1) * (tempBMP.Height / 4); y++) { finalBMP.SetPixel(x, y, thisHalf.GetPixel(x - (halfX * (tempBMP.Width / 2)), y - (halfY * (tempBMP.Height / 4)))); } } for (int x = halfX * (tempBMP.Width / 2); x < (halfX + 1) * (tempBMP.Width / 2); x++) { for (int y = halfY * (tempBMP.Height / 4); y < (halfY + 1) * (tempBMP.Height / 4); y++) { finalBMP.SetPixel(finalBMP.Width - (x + 1), y, thisHalf.GetPixel(x - (halfX * (tempBMP.Width / 2)), y - (halfY * (tempBMP.Height / 4)))); } } } } finalBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(finalBMP, texFile.Replace("Textures", "Models/DAE"))); } else { // If the mouth doesn't have a normal file, the UV coordinates expect it as-is. Hooray! tempBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(tempBMP, texFile.Replace("Textures", "Models/DAE"))); } } else if (texFile.Contains("Eye1") && hasIris == false && texFile.Contains("AEye") == false && texFile.Contains("BEye") == false & texFile.Contains("CEye") == false) { if (tempBMP.Width == tempBMP.Height) { tempBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(tempBMP, texFile.Replace("Textures", "Models/DAE"))); } else { Bitmap thisEye = new Bitmap(tempBMP.Width / 2, tempBMP.Height / 4); Bitmap finalBMP = new Bitmap(tempBMP.Width * 2, tempBMP.Height); for (int eyeY = 0; eyeY < 4; eyeY++) { for (int eyeX = 0; eyeX < 2; eyeX++) { for (int x = eyeX * (tempBMP.Width / 2); x < (eyeX + 1) * (tempBMP.Width / 2); x++) { for (int y = eyeY * (tempBMP.Height / 4); y < (eyeY + 1) * (tempBMP.Height / 4); y++) { thisEye.SetPixel(x - (eyeX * (tempBMP.Width / 2)), y - (eyeY * (tempBMP.Height / 4)), tempBMP.GetPixel(x, y)); } } for (int x = eyeX * (tempBMP.Width / 2); x < (eyeX + 1) * (tempBMP.Width / 2); x++) { for (int y = eyeY * (tempBMP.Height / 4); y < (eyeY + 1) * (tempBMP.Height / 4); y++) { finalBMP.SetPixel(x, y, thisEye.GetPixel(x - (eyeX * (tempBMP.Width / 2)), y - (eyeY * (tempBMP.Height / 4)))); } } for (int x = eyeX * (tempBMP.Width / 2); x < (eyeX + 1) * (tempBMP.Width / 2); x++) { for (int y = eyeY * (tempBMP.Height / 4); y < (eyeY + 1) * (tempBMP.Height / 4); y++) { finalBMP.SetPixel(finalBMP.Width - (x + 1), y, thisEye.GetPixel(x - (eyeX * (tempBMP.Width / 2)), y - (eyeY * (tempBMP.Height / 4)))); } } } } finalBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(finalBMP, texFile.Replace("Textures", "Models/DAE"))); } } else if (texFile.Contains("AEye") || texFile.Contains("BEye") || texFile.Contains("CEye")) { Bitmap finalBMP = new Bitmap(tempBMP, tempBMP.Width / 2, tempBMP.Height); finalBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(finalBMP, texFile.Replace("Textures", "Models/DAE"))); } else if (texFile.Contains("Fire")) { Bitmap finalBMP = new Bitmap(tempBMP); foreach (string bodyFile in texFiles) { if ((bodyFile.Contains("Body1") || bodyFile.Contains("BodyA1")) && bodyFile.Contains("Nor") == false) { Bitmap bodyBMP = (Bitmap)Bitmap.FromFile(bodyFile); byte r, g, b; // Most-Frequent Body Color Color MFBC = Color.FromArgb(0xFF, 0xFF, 0x00, 0x00), LFBC = Color.FromArgb(0xFF, 0xFF, 0xFF, 0x00); int LF = 0, SF = 65536; List<Color> colors = new List<Color>(); List<int> freqs = new List<int>(); for (int x = 0; x < bodyBMP.Width; x++) { for (int y = 0; y < bodyBMP.Height; y++) { r = bodyBMP.GetPixel(x, y).R; g = bodyBMP.GetPixel(x, y).G; b = bodyBMP.GetPixel(x, y).B; if (bodyBMP.GetPixel(x, y).A != 0x00) { bool matchFound = false; foreach (Color c in colors) { if (c.R == r && c.G == g && c.B == b) { matchFound = true; int freq = freqs[colors.IndexOf(c)]; freq++; freqs[colors.IndexOf(c)] = freq; } } if (matchFound == false) { colors.Add(Color.FromArgb(r, g, b)); freqs.Add(1); } } } } int tolerance = 18; foreach (Color c in colors) { if (freqs[colors.IndexOf(c)] > LF) { LF = freqs[colors.IndexOf(c)]; MFBC = c; } else if (freqs[colors.IndexOf(c)] + 150 < SF) { if (c.R <= (c.G - tolerance) || c.R >= (c.G + tolerance)) { if (c.B <= (c.G - tolerance) || c.B >= (c.G + tolerance)) { SF = freqs[colors.IndexOf(c)]; LFBC = c; } } } } bool mfbcgray = false; bool lfbcgray = false; bool bothgray = false; bool neithergray = false; if (MFBC.R > (MFBC.G - tolerance) && MFBC.R < (MFBC.G + tolerance)) { if (MFBC.B > (MFBC.G - tolerance) && MFBC.B < (MFBC.G + tolerance)) { mfbcgray = true; } } if (LFBC.R > (LFBC.G - tolerance) && LFBC.R < (LFBC.G + tolerance)) { if (LFBC.B > (LFBC.G - tolerance) && LFBC.B < (LFBC.G + tolerance)) { lfbcgray = true; } } if (mfbcgray && lfbcgray) { bothgray = true; } if (!mfbcgray && !lfbcgray) { neithergray = true; } Color baseOperator; Color accentOperator; if (bothgray) { baseOperator = Color.FromArgb(0xFF, 0xFF, 0x00, 0x00); accentOperator = Color.FromArgb(0xFF, 0xFF, 0xFF, 0x00); } else if (neithergray) { baseOperator = Color.FromArgb(0xFF, 0xFF, 0x00, 0x00); accentOperator = Color.FromArgb(0xFF, 0xFF, 0xFF, 0x00); } else { if (mfbcgray) { baseOperator = LFBC; accentOperator = LFBC; } else if (lfbcgray) { baseOperator = MFBC; accentOperator = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF); } else { // Just to satisfy C#... baseOperator = MFBC; accentOperator = LFBC; } } for (int x = 0; x < finalBMP.Width; x++) { for (int y = 0; y < finalBMP.Height; y++) { Color tempColor = tempBMP.GetPixel(x, y); Color finalColor; if (tempColor.R < 0x10 && tempColor.G < 0x10 && tempColor.B < 0x10) { finalColor = Color.FromArgb(0x1F, baseOperator.R, baseOperator.G, baseOperator.B); } else { finalColor = Color.FromArgb(0x1F, tempColor.R & accentOperator.R, tempColor.G & accentOperator.G, tempColor.B & accentOperator.B); } finalBMP.SetPixel(x, y, finalColor); } } finalBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(finalBMP, texFile.Replace("Textures", "Models/DAE"))); } } } else { if (texFile.Contains("Iris2") == false && texFile.Contains("Eye2") == false && texFile.Contains("Mouth2") == false) { tempBMP.Save(texFile.Replace("Textures", "Models/DAE")); model.texture.Add(new RenderBase.OTexture(tempBMP, texFile.Replace("Textures", "Models/DAE"))); } } } } } } } catch // No packaged textures detected... { } foreach (RenderBase.OTexture tex in model.texture) { daeImage img = new daeImage(); string n = Path.GetFileNameWithoutExtension(tex.name); img.id = n; img.name = n; if (tex.name.Contains("Shiny")) { img.id += "_shiny"; img.name += "_shiny"; hasShiny = true; } img.id += "_id"; img.init_from = tex.name; if (img.id.Contains("_shiny")) { daeShiny.library_images.Add(img); } else { dae.library_images.Add(img); } } #region Normal int currentMat = 0; foreach (RenderBase.OMaterial mat in mdl.material) { if (mat.name0 == null) { mat.name0 = mat.name; } mdl.material[currentMat].name = mat.name; mdl.material[currentMat].name0 = mat.name0; currentMat++; daeMaterial mtl = new daeMaterial(); mtl.name = mat.name + "_mat"; mtl.id = mtl.name + "_id"; mtl.instance_effect.url = "#eff_" + mtl.id; dae.library_materials.Add(mtl); daeEffect eff = new daeEffect(); eff.id = "eff_" + mtl.id; eff.name = "eff_" + mtl.name; daeParam surface = new daeParam(); surface.surface = new daeParamSurfaceElement(); surface.sid = "img_surface"; surface.surface.type = "2D"; surface.surface.init_from = mat.name0 + "_id"; surface.surface.format = "PNG"; eff.profile_COMMON.newparam.Add(surface); bool fire = false; for (int i = 0; i < dae.library_images.Count; i++) { if (dae.library_images[i].init_from.Contains(mat.name) || dae.library_images[i].id.Contains(mat.name) || dae.library_images[i].init_from.Contains(mat.name0) || dae.library_images[i].id.Contains(mat.name0)) { if (dae.library_images[i].init_from.Contains("Nor") == false) { if (mat.name.Contains("Fire")) { fire = true; dae.library_images[i].name = dae.library_images[i].name.Replace("Mask", "1"); dae.library_images[i].id = dae.library_images[i].id.Replace("Mask", "1"); dae.library_images[i].init_from = dae.library_images[i].init_from.Replace("Mask", "1"); mat.name = mat.name.Replace("Mask", "1"); mat.name0 = mat.name0.Replace("Mask", "1"); } surface.surface.init_from = dae.library_images[i].id; } } } daeParam sampler = new daeParam(); sampler.sampler2D = new daeParamSampler2DElement(); sampler.sid = "img_sampler"; sampler.sampler2D.source = "img_surface"; switch (mat.textureMapper[0].wrapU) { case RenderBase.OTextureWrap.repeat: sampler.sampler2D.wrap_s = "WRAP"; break; case RenderBase.OTextureWrap.mirroredRepeat: sampler.sampler2D.wrap_s = "MIRROR"; break; case RenderBase.OTextureWrap.clampToEdge: sampler.sampler2D.wrap_s = "CLAMP"; break; case RenderBase.OTextureWrap.clampToBorder: sampler.sampler2D.wrap_s = "BORDER"; break; default: sampler.sampler2D.wrap_s = "WRAP"; break; } switch (mat.textureMapper[0].wrapV) { case RenderBase.OTextureWrap.repeat: sampler.sampler2D.wrap_t = "WRAP"; break; case RenderBase.OTextureWrap.mirroredRepeat: sampler.sampler2D.wrap_t = "MIRROR"; break; case RenderBase.OTextureWrap.clampToEdge: sampler.sampler2D.wrap_t = "CLAMP"; break; case RenderBase.OTextureWrap.clampToBorder: sampler.sampler2D.wrap_t = "BORDER"; break; default: sampler.sampler2D.wrap_t = "WRAP"; break; } switch (mat.textureMapper[0].minFilter) { case RenderBase.OTextureMinFilter.linearMipmapLinear: sampler.sampler2D.minfilter = "LINEAR_MIPMAP_LINEAR"; break; case RenderBase.OTextureMinFilter.linearMipmapNearest: sampler.sampler2D.minfilter = "LINEAR_MIPMAP_NEAREST"; break; case RenderBase.OTextureMinFilter.nearestMipmapLinear: sampler.sampler2D.minfilter = "NEAREST_MIPMAP_LINEAR"; break; case RenderBase.OTextureMinFilter.nearestMipmapNearest: sampler.sampler2D.minfilter = "NEAREST_MIPMAP_NEAREST"; break; default: sampler.sampler2D.minfilter = "NONE"; break; } switch (mat.textureMapper[0].magFilter) { case RenderBase.OTextureMagFilter.linear: sampler.sampler2D.magfilter = "LINEAR"; break; case RenderBase.OTextureMagFilter.nearest: sampler.sampler2D.magfilter = "NEAREST"; break; default: sampler.sampler2D.magfilter = "NONE"; break; } sampler.sampler2D.mipfilter = sampler.sampler2D.magfilter; eff.profile_COMMON.newparam.Add(sampler); eff.profile_COMMON.technique.sid = "img_technique"; eff.profile_COMMON.technique.phong.emission.set(Color.Black); eff.profile_COMMON.technique.phong.ambient.set(Color.Black); eff.profile_COMMON.technique.phong.specular.set(Color.White); eff.profile_COMMON.technique.phong.diffuse.texture.texture = "img_sampler"; eff.profile_COMMON.technique.phong.transparency = new daePhongTransparent(); if (fire) { eff.profile_COMMON.technique.phong.transparency.value = "0.1"; } else { eff.profile_COMMON.technique.phong.transparency.value = "1.0"; } dae.library_effects.Add(eff); } string jointNames = null; string invBindPoses = null; for (int index = 0; index < mdl.skeleton.Count; index++) { RenderBase.OMatrix transform = new RenderBase.OMatrix(); transformSkeleton(mdl.skeleton, index, ref transform); jointNames += mdl.skeleton[index].name; daeMatrix mtx = new daeMatrix(); mtx.set(transform.invert()); invBindPoses += mtx.data; if (index < mdl.skeleton.Count - 1) { jointNames += " "; invBindPoses += " "; } } int meshIndex = 0; daeVisualScene vs = new daeVisualScene(); vs.name = "vs_" + mdl.name; vs.id = vs.name + "_id"; if (mdl.skeleton.Count > 0) writeSkeleton(mdl.skeleton, 0, ref vs.node); bool rightIris = false; foreach (RenderBase.OMesh obj in mdl.mesh) { float largestUV = 0.0f; //Geometry daeGeometry geometry = new daeGeometry(); string meshName = "mesh_" + meshIndex++ + "_" + obj.name; geometry.id = meshName + "_id"; geometry.name = meshName; MeshUtils.optimizedMesh mesh = MeshUtils.optimizeMesh(obj); List<float> positions = new List<float>(); List<float> normals = new List<float>(); List<float> uv0 = new List<float>(); List<float> uv1 = new List<float>(); List<float> uv2 = new List<float>(); List<float> colors = new List<float>(); if (obj.name.Contains("Iris")) { foreach (RenderBase.OVertex vtx in mesh.vertices) { if (mesh.texUVCount > 0) { if (vtx.texture0.x > largestUV) { largestUV = vtx.texture0.x; } } } foreach (RenderBase.OVertex vtx in mesh.vertices) { if (mesh.texUVCount > 0) { vtx.texture0.x = largestUV - vtx.texture0.x; if (rightIris) { vtx.texture0.x = 1.25f - vtx.texture0.x; } } if (mesh.texUVCount > 1) { vtx.texture1.x = largestUV - vtx.texture1.x; if (rightIris) { vtx.texture1.x = 1.25f - vtx.texture1.x; } } if (mesh.texUVCount > 2) { vtx.texture2.x = largestUV - vtx.texture2.x; if (rightIris) { vtx.texture2.x = 1.25f - vtx.texture2.x; } } } rightIris = !rightIris; } else if (obj.name.Contains("Eye")) { foreach (RenderBase.OVertex vtx in mesh.vertices) { if (mesh.texUVCount > 0) { if (vtx.texture0.x > largestUV) { largestUV = vtx.texture0.x; } } } foreach (RenderBase.OVertex vtx in mesh.vertices) { if (mesh.texUVCount > 0) { vtx.texture0.x = largestUV - vtx.texture0.x; } if (mesh.texUVCount > 1) { vtx.texture1.x = largestUV - vtx.texture1.x; } if (mesh.texUVCount > 2) { vtx.texture2.x = largestUV - vtx.texture2.x; } } } foreach (RenderBase.OVertex vtx in mesh.vertices) { positions.Add(vtx.position.x); positions.Add(vtx.position.y); positions.Add(vtx.position.z); if (mesh.hasNormal) { normals.Add(vtx.normal.x); normals.Add(vtx.normal.y); normals.Add(vtx.normal.z); } if (mesh.texUVCount > 0) { uv0.Add(vtx.texture0.x); uv0.Add(vtx.texture0.y); } if (mesh.texUVCount > 1) { uv1.Add(vtx.texture1.x); uv1.Add(vtx.texture1.y); } if (mesh.texUVCount > 2) { uv2.Add(vtx.texture2.x); uv2.Add(vtx.texture2.y); } if (mesh.hasColor) { colors.Add(((vtx.diffuseColor >> 16) & 0xff) / 255f); colors.Add(((vtx.diffuseColor >> 8) & 0xff) / 255f); colors.Add((vtx.diffuseColor & 0xff) / 255f); colors.Add(((vtx.diffuseColor >> 24) & 0xff) / 255f); } } daeSource position = new daeSource(); position.name = meshName + "_position"; position.id = position.name + "_id"; position.float_array = new daeFloatArray(); position.float_array.id = position.name + "_array_id"; position.float_array.set(positions); position.technique_common.accessor.source = "#" + position.float_array.id; position.technique_common.accessor.count = (uint)mesh.vertices.Count; position.technique_common.accessor.stride = 3; position.technique_common.accessor.addParam("X", "float"); position.technique_common.accessor.addParam("Y", "float"); position.technique_common.accessor.addParam("Z", "float"); geometry.mesh.source.Add(position); daeSource normal = new daeSource(); if (mesh.hasNormal) { normal.name = meshName + "_normal"; normal.id = normal.name + "_id"; normal.float_array = new daeFloatArray(); normal.float_array.id = normal.name + "_array_id"; normal.float_array.set(normals); normal.technique_common.accessor.source = "#" + normal.float_array.id; normal.technique_common.accessor.count = (uint)mesh.vertices.Count; normal.technique_common.accessor.stride = 3; normal.technique_common.accessor.addParam("X", "float"); normal.technique_common.accessor.addParam("Y", "float"); normal.technique_common.accessor.addParam("Z", "float"); geometry.mesh.source.Add(normal); } daeSource[] texUV = new daeSource[3]; for (int i = 0; i < mesh.texUVCount; i++) { texUV[i] = new daeSource(); texUV[i].name = meshName + "_uv" + i; texUV[i].id = texUV[i].name + "_id"; texUV[i].float_array = new daeFloatArray(); texUV[i].float_array.id = texUV[i].name + "_array_id"; texUV[i].technique_common.accessor.source = "#" + texUV[i].float_array.id; texUV[i].technique_common.accessor.count = (uint)mesh.vertices.Count; texUV[i].technique_common.accessor.stride = 2; texUV[i].technique_common.accessor.addParam("S", "float"); texUV[i].technique_common.accessor.addParam("T", "float"); geometry.mesh.source.Add(texUV[i]); } daeSource color = new daeSource(); if (mesh.hasColor) { color.name = meshName + "_color"; color.id = color.name + "_id"; color.float_array = new daeFloatArray(); color.float_array.id = color.name + "_array_id"; color.float_array.set(colors); color.technique_common.accessor.source = "#" + color.float_array.id; color.technique_common.accessor.count = (uint)mesh.vertices.Count; color.technique_common.accessor.stride = 4; color.technique_common.accessor.addParam("R", "float"); color.technique_common.accessor.addParam("G", "float"); color.technique_common.accessor.addParam("B", "float"); color.technique_common.accessor.addParam("A", "float"); geometry.mesh.source.Add(color); } geometry.mesh.vertices.id = meshName + "_vertices_id"; geometry.mesh.vertices.addInput("POSITION", "#" + position.id); geometry.mesh.triangles.material = mdl.material[obj.materialId].name + "_mat"; geometry.mesh.triangles.addInput("VERTEX", "#" + geometry.mesh.vertices.id); if (mesh.hasNormal) geometry.mesh.triangles.addInput("NORMAL", "#" + normal.id); if (mesh.hasColor) geometry.mesh.triangles.addInput("COLOR", "#" + color.id); if (mesh.texUVCount > 0) { texUV[0].float_array.set(uv0); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[0].id); } if (mesh.texUVCount > 1) { texUV[1].float_array.set(uv1); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[1].id, 0, 1); } if (mesh.texUVCount > 2) { texUV[2].float_array.set(uv2); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[2].id, 0, 2); } geometry.mesh.triangles.set(mesh.indices); dae.library_geometries.Add(geometry); bool hasNode = obj.vertices[0].node.Count > 0; bool hasWeight = obj.vertices[0].weight.Count > 0; bool hasController = hasNode && hasWeight; //Controller daeController controller = new daeController(); if (hasController) { controller.id = meshName + "_ctrl_id"; controller.skin.source = "#" + geometry.id; controller.skin.bind_shape_matrix.set(new RenderBase.OMatrix()); daeSource joints = new daeSource(); joints.id = meshName + "_ctrl_joint_names_id"; joints.Name_array = new daeNameArray(); joints.Name_array.id = meshName + "_ctrl_joint_names_array_id"; joints.Name_array.count = (uint)mdl.skeleton.Count; joints.Name_array.data = jointNames; joints.technique_common.accessor.source = "#" + joints.Name_array.id; joints.technique_common.accessor.count = joints.Name_array.count; joints.technique_common.accessor.stride = 1; joints.technique_common.accessor.addParam("JOINT", "Name"); controller.skin.src.Add(joints); daeSource bindPoses = new daeSource(); bindPoses.id = meshName + "_ctrl_inv_bind_poses_id"; bindPoses.float_array = new daeFloatArray(); bindPoses.float_array.id = meshName + "_ctrl_inv_bind_poses_array_id"; bindPoses.float_array.count = (uint)(mdl.skeleton.Count * 16); bindPoses.float_array.data = invBindPoses; bindPoses.technique_common.accessor.source = "#" + bindPoses.float_array.id; bindPoses.technique_common.accessor.count = (uint)mdl.skeleton.Count; bindPoses.technique_common.accessor.stride = 16; bindPoses.technique_common.accessor.addParam("TRANSFORM", "float4x4"); controller.skin.src.Add(bindPoses); daeSource weights = new daeSource(); weights.id = meshName + "_ctrl_weights_id"; weights.float_array = new daeFloatArray(); weights.float_array.id = meshName + "_ctrl_weights_array_id"; weights.technique_common.accessor.source = "#" + weights.float_array.id; weights.technique_common.accessor.stride = 1; weights.technique_common.accessor.addParam("WEIGHT", "float"); StringBuilder w = new StringBuilder(); StringBuilder vcount = new StringBuilder(); StringBuilder v = new StringBuilder(); float[] wLookBack = new float[32]; uint wLookBackIndex = 0; int buffLen = 0; int wIndex = 0; int wCount = 0; foreach (RenderBase.OVertex vtx in mesh.vertices) { int count = Math.Min(vtx.node.Count, vtx.weight.Count); vcount.Append(count + " "); for (int n = 0; n < count; n++) { v.Append(vtx.node[n] + " "); bool found = false; uint bPos = (wLookBackIndex - 1) & 0x1f; for (int i = 0; i < buffLen; i++) { if (wLookBack[bPos] == vtx.weight[n]) { v.Append(wIndex - (i + 1) + " "); found = true; break; } bPos = (bPos - 1) & 0x1f; } if (!found) { v.Append(wIndex++ + " "); w.Append(vtx.weight[n].ToString(CultureInfo.InvariantCulture) + " "); wCount++; wLookBack[wLookBackIndex] = vtx.weight[n]; wLookBackIndex = (wLookBackIndex + 1) & 0x1f; if (buffLen < wLookBack.Length) buffLen++; } } } weights.float_array.data = w.ToString().TrimEnd(); weights.float_array.count = (uint)wCount; weights.technique_common.accessor.count = (uint)wCount; controller.skin.src.Add(weights); controller.skin.vertex_weights.vcount = vcount.ToString().TrimEnd(); controller.skin.vertex_weights.v = v.ToString().TrimEnd(); controller.skin.vertex_weights.count = (uint)mesh.vertices.Count; controller.skin.joints.addInput("JOINT", "#" + joints.id); controller.skin.joints.addInput("INV_BIND_MATRIX", "#" + bindPoses.id); controller.skin.vertex_weights.addInput("JOINT", "#" + joints.id); controller.skin.vertex_weights.addInput("WEIGHT", "#" + weights.id, 1); if (dae.library_controllers == null) dae.library_controllers = new List<daeController>(); dae.library_controllers.Add(controller); } //Visual scene node daeNode node = new daeNode(); node.name = "vsn_" + meshName; node.id = node.name + "_id"; node.matrix.set(new RenderBase.OMatrix()); if (hasController) { node.instance_controller = new daeInstanceController(); node.instance_controller.url = "#" + controller.id; node.instance_controller.skeleton = "#" + mdl.skeleton[0].name + "_bone_id"; node.instance_controller.bind_material.technique_common.instance_material.symbol = mdl.material[obj.materialId].name + "_mat"; node.instance_controller.bind_material.technique_common.instance_material.target = "#" + mdl.material[obj.materialId].name + "_mat_id"; } else { node.instance_geometry = new daeInstanceGeometry(); node.instance_geometry.url = "#" + geometry.id; node.instance_geometry.bind_material.technique_common.instance_material.symbol = mdl.material[obj.materialId].name + "_mat"; node.instance_geometry.bind_material.technique_common.instance_material.target = "#" + mdl.material[obj.materialId].name + "_mat_id"; } vs.node.Add(node); } dae.library_visual_scenes.Add(vs); daeInstaceVisualScene scene = new daeInstaceVisualScene(); scene.url = "#" + vs.id; dae.scene.Add(scene); XmlWriterSettings settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true }; XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", "http://www.collada.org/2005/11/COLLADASchema"); XmlSerializer serializer = new XmlSerializer(typeof(COLLADA)); XmlWriter output = XmlWriter.Create(new FileStream(fileName.Replace(".bch", ".dae").Replace("BCH", "DAE"), FileMode.Create), settings); serializer.Serialize(output, dae, ns); output.Close(); #endregion #region Shiny if (hasShiny) { currentMat = 0; foreach (RenderBase.OMaterial mat in mdl.material) { if (mat.name0 == null) { mat.name0 = mat.name; } mat.name += "_shiny"; mat.name0 += "_shiny"; mdl.material[currentMat].name = mat.name; mdl.material[currentMat].name0 = mat.name0; currentMat++; daeMaterial mtl = new daeMaterial(); mtl.name = mat.name + "_mat"; mtl.id = mtl.name + "_id"; mtl.instance_effect.url = "#eff_" + mtl.id; daeShiny.library_materials.Add(mtl); daeEffect eff = new daeEffect(); eff.id = "eff_" + mtl.id; eff.name = "eff_" + mtl.name; daeParam surface = new daeParam(); surface.surface = new daeParamSurfaceElement(); surface.sid = "img_surface"; surface.surface.type = "2D"; surface.surface.init_from = mat.name0 + "_id"; surface.surface.format = "PNG"; eff.profile_COMMON.newparam.Add(surface); bool fire = false; for (int i = 0; i < daeShiny.library_images.Count; i++) { if (daeShiny.library_images[i].init_from.Contains(mat.name) || daeShiny.library_images[i].id.Contains(mat.name) || daeShiny.library_images[i].init_from.Contains(mat.name0) || daeShiny.library_images[i].id.Contains(mat.name0)) { if (daeShiny.library_images[i].init_from.Contains("Nor") == false) { if (mat.name.Contains("Fire")) { fire = true; daeShiny.library_images[i].name = daeShiny.library_images[i].name.Replace("Mask", "1"); daeShiny.library_images[i].id = daeShiny.library_images[i].id.Replace("Mask", "1"); daeShiny.library_images[i].init_from = daeShiny.library_images[i].init_from.Replace("Mask", "1"); mat.name = mat.name.Replace("Mask", "1"); mat.name0 = mat.name0.Replace("Mask", "1"); } surface.surface.init_from = daeShiny.library_images[i].id; } } } if (mat.name.Contains("Fire")) { fire = true; } daeParam sampler = new daeParam(); sampler.sampler2D = new daeParamSampler2DElement(); sampler.sid = "img_sampler"; sampler.sampler2D.source = "img_surface"; switch (mat.textureMapper[0].wrapU) { case RenderBase.OTextureWrap.repeat: sampler.sampler2D.wrap_s = "WRAP"; break; case RenderBase.OTextureWrap.mirroredRepeat: sampler.sampler2D.wrap_s = "MIRROR"; break; case RenderBase.OTextureWrap.clampToEdge: sampler.sampler2D.wrap_s = "CLAMP"; break; case RenderBase.OTextureWrap.clampToBorder: sampler.sampler2D.wrap_s = "BORDER"; break; default: sampler.sampler2D.wrap_s = "WRAP"; break; } switch (mat.textureMapper[0].wrapV) { case RenderBase.OTextureWrap.repeat: sampler.sampler2D.wrap_t = "WRAP"; break; case RenderBase.OTextureWrap.mirroredRepeat: sampler.sampler2D.wrap_t = "MIRROR"; break; case RenderBase.OTextureWrap.clampToEdge: sampler.sampler2D.wrap_t = "CLAMP"; break; case RenderBase.OTextureWrap.clampToBorder: sampler.sampler2D.wrap_t = "BORDER"; break; default: sampler.sampler2D.wrap_t = "WRAP"; break; } switch (mat.textureMapper[0].minFilter) { case RenderBase.OTextureMinFilter.linearMipmapLinear: sampler.sampler2D.minfilter = "LINEAR_MIPMAP_LINEAR"; break; case RenderBase.OTextureMinFilter.linearMipmapNearest: sampler.sampler2D.minfilter = "LINEAR_MIPMAP_NEAREST"; break; case RenderBase.OTextureMinFilter.nearestMipmapLinear: sampler.sampler2D.minfilter = "NEAREST_MIPMAP_LINEAR"; break; case RenderBase.OTextureMinFilter.nearestMipmapNearest: sampler.sampler2D.minfilter = "NEAREST_MIPMAP_NEAREST"; break; default: sampler.sampler2D.minfilter = "NONE"; break; } switch (mat.textureMapper[0].magFilter) { case RenderBase.OTextureMagFilter.linear: sampler.sampler2D.magfilter = "LINEAR"; break; case RenderBase.OTextureMagFilter.nearest: sampler.sampler2D.magfilter = "NEAREST"; break; default: sampler.sampler2D.magfilter = "NONE"; break; } sampler.sampler2D.mipfilter = sampler.sampler2D.magfilter; eff.profile_COMMON.newparam.Add(sampler); eff.profile_COMMON.technique.sid = "img_technique"; eff.profile_COMMON.technique.phong.emission.set(Color.Black); eff.profile_COMMON.technique.phong.ambient.set(Color.Black); eff.profile_COMMON.technique.phong.specular.set(Color.White); eff.profile_COMMON.technique.phong.diffuse.texture.texture = "img_sampler"; eff.profile_COMMON.technique.phong.transparency = new daePhongTransparent(); if (fire) { eff.profile_COMMON.technique.phong.transparency.value = "0.1"; } else { eff.profile_COMMON.technique.phong.transparency.value = "1.0"; } daeShiny.library_effects.Add(eff); } jointNames = null; invBindPoses = null; for (int index = 0; index < mdl.skeleton.Count; index++) { RenderBase.OMatrix transform = new RenderBase.OMatrix(); transformSkeleton(mdl.skeleton, index, ref transform); jointNames += mdl.skeleton[index].name; daeMatrix mtx = new daeMatrix(); mtx.set(transform.invert()); invBindPoses += mtx.data; if (index < mdl.skeleton.Count - 1) { jointNames += " "; invBindPoses += " "; } } meshIndex = 0; vs = new daeVisualScene(); vs.name = "vs_" + mdl.name; vs.id = vs.name + "_id"; if (mdl.skeleton.Count > 0) writeSkeleton(mdl.skeleton, 0, ref vs.node); rightIris = false; foreach (RenderBase.OMesh obj in mdl.mesh) { float largestUV = 0.0f; //Geometry daeGeometry geometry = new daeGeometry(); string meshName = "mesh_" + meshIndex++ + "_" + obj.name; geometry.id = meshName + "_id"; geometry.name = meshName; MeshUtils.optimizedMesh mesh = MeshUtils.optimizeMesh(obj); List<float> positions = new List<float>(); List<float> normals = new List<float>(); List<float> uv0 = new List<float>(); List<float> uv1 = new List<float>(); List<float> uv2 = new List<float>(); List<float> colors = new List<float>(); if (obj.name.Contains("Iris")) { foreach (RenderBase.OVertex vtx in mesh.vertices) { if (mesh.texUVCount > 0) { if (vtx.texture0.x > largestUV) { largestUV = vtx.texture0.x; } } } foreach (RenderBase.OVertex vtx in mesh.vertices) { if (mesh.texUVCount > 0) { vtx.texture0.x = largestUV - vtx.texture0.x; if (rightIris) { vtx.texture0.x = 1.25f - vtx.texture0.x; } } if (mesh.texUVCount > 1) { vtx.texture1.x = largestUV - vtx.texture1.x; if (rightIris) { vtx.texture1.x = 1.25f - vtx.texture1.x; } } if (mesh.texUVCount > 2) { vtx.texture2.x = largestUV - vtx.texture2.x; if (rightIris) { vtx.texture2.x = 1.25f - vtx.texture2.x; } } } rightIris = !rightIris; } else if (obj.name.Contains("Eye")) { foreach (RenderBase.OVertex vtx in mesh.vertices) { if (mesh.texUVCount > 0) { if (vtx.texture0.x > largestUV) { largestUV = vtx.texture0.x; } } } foreach (RenderBase.OVertex vtx in mesh.vertices) { if (mesh.texUVCount > 0) { vtx.texture0.x = largestUV - vtx.texture0.x; } if (mesh.texUVCount > 1) { vtx.texture1.x = largestUV - vtx.texture1.x; } if (mesh.texUVCount > 2) { vtx.texture2.x = largestUV - vtx.texture2.x; } } } foreach (RenderBase.OVertex vtx in mesh.vertices) { positions.Add(vtx.position.x); positions.Add(vtx.position.y); positions.Add(vtx.position.z); if (mesh.hasNormal) { normals.Add(vtx.normal.x); normals.Add(vtx.normal.y); normals.Add(vtx.normal.z); } if (mesh.texUVCount > 0) { uv0.Add(vtx.texture0.x); uv0.Add(vtx.texture0.y); } if (mesh.texUVCount > 1) { uv1.Add(vtx.texture1.x); uv1.Add(vtx.texture1.y); } if (mesh.texUVCount > 2) { uv2.Add(vtx.texture2.x); uv2.Add(vtx.texture2.y); } if (mesh.hasColor) { colors.Add(((vtx.diffuseColor >> 16) & 0xff) / 255f); colors.Add(((vtx.diffuseColor >> 8) & 0xff) / 255f); colors.Add((vtx.diffuseColor & 0xff) / 255f); colors.Add(((vtx.diffuseColor >> 24) & 0xff) / 255f); } } daeSource position = new daeSource(); position.name = meshName + "_position"; position.id = position.name + "_id"; position.float_array = new daeFloatArray(); position.float_array.id = position.name + "_array_id"; position.float_array.set(positions); position.technique_common.accessor.source = "#" + position.float_array.id; position.technique_common.accessor.count = (uint)mesh.vertices.Count; position.technique_common.accessor.stride = 3; position.technique_common.accessor.addParam("X", "float"); position.technique_common.accessor.addParam("Y", "float"); position.technique_common.accessor.addParam("Z", "float"); geometry.mesh.source.Add(position); daeSource normal = new daeSource(); if (mesh.hasNormal) { normal.name = meshName + "_normal"; normal.id = normal.name + "_id"; normal.float_array = new daeFloatArray(); normal.float_array.id = normal.name + "_array_id"; normal.float_array.set(normals); normal.technique_common.accessor.source = "#" + normal.float_array.id; normal.technique_common.accessor.count = (uint)mesh.vertices.Count; normal.technique_common.accessor.stride = 3; normal.technique_common.accessor.addParam("X", "float"); normal.technique_common.accessor.addParam("Y", "float"); normal.technique_common.accessor.addParam("Z", "float"); geometry.mesh.source.Add(normal); } daeSource[] texUV = new daeSource[3]; for (int i = 0; i < mesh.texUVCount; i++) { texUV[i] = new daeSource(); texUV[i].name = meshName + "_uv" + i; texUV[i].id = texUV[i].name + "_id"; texUV[i].float_array = new daeFloatArray(); texUV[i].float_array.id = texUV[i].name + "_array_id"; texUV[i].technique_common.accessor.source = "#" + texUV[i].float_array.id; texUV[i].technique_common.accessor.count = (uint)mesh.vertices.Count; texUV[i].technique_common.accessor.stride = 2; texUV[i].technique_common.accessor.addParam("S", "float"); texUV[i].technique_common.accessor.addParam("T", "float"); geometry.mesh.source.Add(texUV[i]); } daeSource color = new daeSource(); if (mesh.hasColor) { color.name = meshName + "_color"; color.id = color.name + "_id"; color.float_array = new daeFloatArray(); color.float_array.id = color.name + "_array_id"; color.float_array.set(colors); color.technique_common.accessor.source = "#" + color.float_array.id; color.technique_common.accessor.count = (uint)mesh.vertices.Count; color.technique_common.accessor.stride = 4; color.technique_common.accessor.addParam("R", "float"); color.technique_common.accessor.addParam("G", "float"); color.technique_common.accessor.addParam("B", "float"); color.technique_common.accessor.addParam("A", "float"); geometry.mesh.source.Add(color); } geometry.mesh.vertices.id = meshName + "_vertices_id"; geometry.mesh.vertices.addInput("POSITION", "#" + position.id); geometry.mesh.triangles.material = mdl.material[obj.materialId].name + "_mat"; geometry.mesh.triangles.addInput("VERTEX", "#" + geometry.mesh.vertices.id); if (mesh.hasNormal) geometry.mesh.triangles.addInput("NORMAL", "#" + normal.id); if (mesh.hasColor) geometry.mesh.triangles.addInput("COLOR", "#" + color.id); if (mesh.texUVCount > 0) { texUV[0].float_array.set(uv0); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[0].id); } if (mesh.texUVCount > 1) { texUV[1].float_array.set(uv1); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[1].id, 0, 1); } if (mesh.texUVCount > 2) { texUV[2].float_array.set(uv2); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[2].id, 0, 2); } geometry.mesh.triangles.set(mesh.indices); daeShiny.library_geometries.Add(geometry); bool hasNode = obj.vertices[0].node.Count > 0; bool hasWeight = obj.vertices[0].weight.Count > 0; bool hasController = hasNode && hasWeight; //Controller daeController controller = new daeController(); if (hasController) { controller.id = meshName + "_ctrl_id"; controller.skin.source = "#" + geometry.id; controller.skin.bind_shape_matrix.set(new RenderBase.OMatrix()); daeSource joints = new daeSource(); joints.id = meshName + "_ctrl_joint_names_id"; joints.Name_array = new daeNameArray(); joints.Name_array.id = meshName + "_ctrl_joint_names_array_id"; joints.Name_array.count = (uint)mdl.skeleton.Count; joints.Name_array.data = jointNames; joints.technique_common.accessor.source = "#" + joints.Name_array.id; joints.technique_common.accessor.count = joints.Name_array.count; joints.technique_common.accessor.stride = 1; joints.technique_common.accessor.addParam("JOINT", "Name"); controller.skin.src.Add(joints); daeSource bindPoses = new daeSource(); bindPoses.id = meshName + "_ctrl_inv_bind_poses_id"; bindPoses.float_array = new daeFloatArray(); bindPoses.float_array.id = meshName + "_ctrl_inv_bind_poses_array_id"; bindPoses.float_array.count = (uint)(mdl.skeleton.Count * 16); bindPoses.float_array.data = invBindPoses; bindPoses.technique_common.accessor.source = "#" + bindPoses.float_array.id; bindPoses.technique_common.accessor.count = (uint)mdl.skeleton.Count; bindPoses.technique_common.accessor.stride = 16; bindPoses.technique_common.accessor.addParam("TRANSFORM", "float4x4"); controller.skin.src.Add(bindPoses); daeSource weights = new daeSource(); weights.id = meshName + "_ctrl_weights_id"; weights.float_array = new daeFloatArray(); weights.float_array.id = meshName + "_ctrl_weights_array_id"; weights.technique_common.accessor.source = "#" + weights.float_array.id; weights.technique_common.accessor.stride = 1; weights.technique_common.accessor.addParam("WEIGHT", "float"); StringBuilder w = new StringBuilder(); StringBuilder vcount = new StringBuilder(); StringBuilder v = new StringBuilder(); float[] wLookBack = new float[32]; uint wLookBackIndex = 0; int buffLen = 0; int wIndex = 0; int wCount = 0; foreach (RenderBase.OVertex vtx in mesh.vertices) { int count = Math.Min(vtx.node.Count, vtx.weight.Count); vcount.Append(count + " "); for (int n = 0; n < count; n++) { v.Append(vtx.node[n] + " "); bool found = false; uint bPos = (wLookBackIndex - 1) & 0x1f; for (int i = 0; i < buffLen; i++) { if (wLookBack[bPos] == vtx.weight[n]) { v.Append(wIndex - (i + 1) + " "); found = true; break; } bPos = (bPos - 1) & 0x1f; } if (!found) { v.Append(wIndex++ + " "); w.Append(vtx.weight[n].ToString(CultureInfo.InvariantCulture) + " "); wCount++; wLookBack[wLookBackIndex] = vtx.weight[n]; wLookBackIndex = (wLookBackIndex + 1) & 0x1f; if (buffLen < wLookBack.Length) buffLen++; } } } weights.float_array.data = w.ToString().TrimEnd(); weights.float_array.count = (uint)wCount; weights.technique_common.accessor.count = (uint)wCount; controller.skin.src.Add(weights); controller.skin.vertex_weights.vcount = vcount.ToString().TrimEnd(); controller.skin.vertex_weights.v = v.ToString().TrimEnd(); controller.skin.vertex_weights.count = (uint)mesh.vertices.Count; controller.skin.joints.addInput("JOINT", "#" + joints.id); controller.skin.joints.addInput("INV_BIND_MATRIX", "#" + bindPoses.id); controller.skin.vertex_weights.addInput("JOINT", "#" + joints.id); controller.skin.vertex_weights.addInput("WEIGHT", "#" + weights.id, 1); if (daeShiny.library_controllers == null) daeShiny.library_controllers = new List<daeController>(); daeShiny.library_controllers.Add(controller); } //Visual scene node daeNode node = new daeNode(); node.name = "vsn_" + meshName; node.id = node.name + "_id"; node.matrix.set(new RenderBase.OMatrix()); if (hasController) { node.instance_controller = new daeInstanceController(); node.instance_controller.url = "#" + controller.id; node.instance_controller.skeleton = "#" + mdl.skeleton[0].name + "_bone_id"; node.instance_controller.bind_material.technique_common.instance_material.symbol = mdl.material[obj.materialId].name + "_mat"; node.instance_controller.bind_material.technique_common.instance_material.target = "#" + mdl.material[obj.materialId].name + "_mat_id"; } else { node.instance_geometry = new daeInstanceGeometry(); node.instance_geometry.url = "#" + geometry.id; node.instance_geometry.bind_material.technique_common.instance_material.symbol = mdl.material[obj.materialId].name + "_mat"; node.instance_geometry.bind_material.technique_common.instance_material.target = "#" + mdl.material[obj.materialId].name + "_mat_id"; } vs.node.Add(node); } daeShiny.library_visual_scenes.Add(vs); scene = new daeInstaceVisualScene(); scene.url = "#" + vs.id; daeShiny.scene.Add(scene); settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true }; ns = new XmlSerializerNamespaces(); ns.Add("", "http://www.collada.org/2005/11/COLLADASchema"); serializer = new XmlSerializer(typeof(COLLADA)); output = XmlWriter.Create(new FileStream(fileName.Replace(".bch", "_Shiny.dae").Replace("BCH", "DAE"), FileMode.Create), settings); serializer.Serialize(output, daeShiny, ns); output.Close(); } #endregion }
private static RenderBase generateItemByName(String type, String path = null, RenderBase parent = null) { RenderBase item = null; bool isComplete = true; switch (type) { case Constant.TypeSprite: item = new TDSprite(); break; case Constant.TypeSliderBar: item = new TDSliderBar(); break; case Constant.TypeScale9: item = new TDScale9(); break; case Constant.TypeButton: item = new TDButton(); break; case Constant.TypeCheckBox: item = new TDCheckBox(); break; case Constant.TypeInput: item = new TDInput(); break; case Constant.TypeProgressBar: item = new TDProgressBar(); break; case Constant.TypeText: item = new TDText(); break; case Constant.TypePanel: if (path == null || path.Length == 0) { item = new TDPanel(); } else { item = generateViewByPath(path, parent); } isComplete = true; break; case Constant.TypePage: item = new TDPage(); break; default: item = null; break; } if (parent != null && item != null && item.getParent() == null) { item.setParent(parent); } if (item != null && isComplete) { item.loadComplete(); } return(item); }
/// <summary> /// Gets an Animation Key frame from the BCH file. /// The Reader position must be set to the beggining of the Key Frame Data. /// </summary> /// <param name="input">The BCH file Reader</param> /// <param name="header">The BCH file header</param> /// <returns></returns> private static void getAnimationKeyFrame(BinaryReader input, RenderBase.OAnimationKeyFrameGroup frame) { frame.startFrame = input.ReadSingle(); frame.endFrame = input.ReadSingle(); uint frameFlags = input.ReadUInt32(); frame.preRepeat = (RenderBase.ORepeatMethod)(frameFlags & 0xf); frame.postRepeat = (RenderBase.ORepeatMethod)((frameFlags >> 8) & 0xf); uint segmentFlags = input.ReadUInt32(); frame.interpolation = (RenderBase.OInterpolationMode)(segmentFlags & 0xf); RenderBase.OSegmentQuantization quantization = (RenderBase.OSegmentQuantization)((segmentFlags >> 8) & 0xff); uint entries = segmentFlags >> 16; float valueScale = input.ReadSingle(); float valueOffset = input.ReadSingle(); float frameScale = input.ReadSingle(); float frameOffset = input.ReadSingle(); uint offset = input.ReadUInt32(); if (offset < input.BaseStream.Length) input.BaseStream.Seek(offset, SeekOrigin.Begin); for (int key = 0; key < entries; key++) { RenderBase.OAnimationKeyFrame keyFrame = new RenderBase.OAnimationKeyFrame(); switch (quantization) { case RenderBase.OSegmentQuantization.hermite128: keyFrame.frame = input.ReadSingle(); keyFrame.value = input.ReadSingle(); keyFrame.inSlope = input.ReadSingle(); keyFrame.outSlope = input.ReadSingle(); break; case RenderBase.OSegmentQuantization.hermite64: uint h64Value = input.ReadUInt32(); keyFrame.frame = h64Value & 0xfff; keyFrame.value = h64Value >> 12; keyFrame.inSlope = input.ReadInt16() / 256f; keyFrame.outSlope = input.ReadInt16() / 256f; break; case RenderBase.OSegmentQuantization.hermite48: keyFrame.frame = input.ReadByte(); keyFrame.value = input.ReadUInt16(); byte slope0 = input.ReadByte(); byte slope1 = input.ReadByte(); byte slope2 = input.ReadByte(); keyFrame.inSlope = IOUtils.signExtend(slope0 | ((slope1 & 0xf) << 8), 12) / 32f; keyFrame.outSlope = IOUtils.signExtend((slope1 >> 4) | (slope2 << 4), 12) / 32f; break; case RenderBase.OSegmentQuantization.unifiedHermite96: keyFrame.frame = input.ReadSingle(); keyFrame.value = input.ReadSingle(); keyFrame.inSlope = input.ReadSingle(); keyFrame.outSlope = keyFrame.inSlope; break; case RenderBase.OSegmentQuantization.unifiedHermite48: keyFrame.frame = input.ReadUInt16() / 32f; keyFrame.value = input.ReadUInt16(); keyFrame.inSlope = input.ReadInt16() / 256f; keyFrame.outSlope = keyFrame.inSlope; break; case RenderBase.OSegmentQuantization.unifiedHermite32: keyFrame.frame = input.ReadByte(); ushort uH32Value = input.ReadUInt16(); keyFrame.value = uH32Value & 0xfff; keyFrame.inSlope = IOUtils.signExtend((uH32Value >> 12) | (input.ReadByte() << 4), 12) / 32f; keyFrame.outSlope = keyFrame.inSlope; break; case RenderBase.OSegmentQuantization.stepLinear64: keyFrame.frame = input.ReadSingle(); keyFrame.value = input.ReadSingle(); break; case RenderBase.OSegmentQuantization.stepLinear32: uint sL32Value = input.ReadUInt32(); keyFrame.frame = sL32Value & 0xfff; keyFrame.value = sL32Value >> 12; break; } keyFrame.frame = (keyFrame.frame * frameScale) + frameOffset; keyFrame.value = (keyFrame.value * valueScale) + valueOffset; frame.keyFrames.Add(keyFrame); } }
/// <summary> /// Transforms a Skeleton from relative to absolute positions. /// </summary> /// <param name="skeleton">The skeleton</param> /// <param name="index">Index of the bone to convert</param> /// <param name="target">Target matrix to save bone transformation</param> private static void transformSkeleton(List<RenderBase.OBone> skeleton, int index, ref RenderBase.OMatrix target) { target *= RenderBase.OMatrix.rotateX(skeleton[index].rotation.x); target *= RenderBase.OMatrix.rotateY(skeleton[index].rotation.y); target *= RenderBase.OMatrix.rotateZ(skeleton[index].rotation.z); target *= RenderBase.OMatrix.translate(skeleton[index].translation); if (skeleton[index].parentId > -1) transformSkeleton(skeleton, skeleton[index].parentId, ref target); }
private void SlaveThread() { ScanPort runConnect = null; bool NoProtocol = true;//ProtocolBase、RenderBase未開啟 try { // create object instance .. runConnect = new ScanPort(); do { //新增備援機制 是否是主機,如果不是建立連接測試類,如果可以連接主機,則不啟動備援,如果連接主機不通,則啟動備援機制 #region 本機是主機 if (EnvHostBase.LocalIpAddress.ToString() == Settings.Default.MasterServer) { if (NoProtocol) { this.OperationBase = new RenderBase(this.EnvData, this.EnvLog) { ConnectPort = this.__ListenRenderPort }; this.PortalBase = new ProtocolBase(this.EnvData, this.EnvLog) { ConnectPort = this.__ListenRenderPort, ListenPort = this.__ListenClientPort, MaxHistory = this.__JobHistoryMaxRecord }; //開啟監聽端口6601 this.MasterBase = new SlaveBase(this.EnvLog) { _listenSlavePort = this.__ServerSyncPort }; NoProtocol = false; } } #endregion #region 本機非主機 else { //主機未啟動 if (!runConnect.Scan(System.Net.IPAddress.Parse(Settings.Default.MasterServer), this.__ServerSyncPort)) { if (this.OperationBase == null) { this.OperationBase = new RenderBase(this.EnvData, this.EnvLog) { ConnectPort = this.__ListenRenderPort }; } if (this.PortalBase == null) { this.PortalBase = new ProtocolBase(this.EnvData, this.EnvLog) { ConnectPort = this.__ListenRenderPort, ListenPort = this.__ListenClientPort, MaxHistory = this.__JobHistoryMaxRecord }; } } //主機已啟動 else { //取消与客户端以及render端沟通的线程 if (this.OperationBase != null) { this.OperationBase.Dispose(); this.OperationBase = null; } if (this.PortalBase != null) { this.PortalBase.Dispose(); this.PortalBase = null; } } } #endregion Thread.Sleep(1000); } while (!requestStop); } catch (Exception ex) { string ExceptionMsg = ex.Message + "Master to Slave!"; // write to log file .. //EnvLog.Writer(AssemblyInfoClass.ProductInfo, Log.Level.Error, ExceptionMsg, true); } }
/// <summary> /// Gets the current frame of a Material Animation integer value. /// </summary> /// <param name="data">The animation data</param> /// <param name="color">The integer value where the animation will be applied</param> private void getMaterialAnimationInt(RenderBase.OMaterialAnimationData data, ref int value) { if (data.frameList[0].exists) value = (int)AnimationUtils.getKey(data.frameList[0], ctrlMA.Frame); }
/// <summary> /// Gets a MDX Matrix from a RenderBase Matrix. /// </summary> /// <param name="mtx">RenderBase matrix</param> /// <returns></returns> private Matrix getMatrix(RenderBase.OMatrix mtx) { Matrix output = Matrix.Identity; output.M11 = mtx.M11; output.M12 = mtx.M12; output.M13 = mtx.M13; output.M14 = mtx.M14; output.M21 = mtx.M21; output.M22 = mtx.M22; output.M23 = mtx.M23; output.M24 = mtx.M24; output.M31 = mtx.M31; output.M32 = mtx.M32; output.M33 = mtx.M33; output.M34 = mtx.M34; output.M41 = mtx.M41; output.M42 = mtx.M42; output.M43 = mtx.M43; output.M44 = mtx.M44; return output; }
/// <summary> /// Gets the current frame of a Material Animation 2-D vector. /// </summary> /// <param name="data">The animation data</param> /// <param name="color">The vector where the animation will be applied</param> private void getMaterialAnimationVector2(RenderBase.OMaterialAnimationData data, ref Vector2 vector) { if (data.frameList[0].exists) vector.X = AnimationUtils.getKey(data.frameList[0], ctrlMA.Frame); if (data.frameList[1].exists) vector.Y = AnimationUtils.getKey(data.frameList[1], ctrlMA.Frame); }
public CommandAnchorPos(RenderScene scene, RenderBase render) : base(scene, render.uniqueName) { this._orign = render.oriAnchorPos; this._finish = render.anchorPos; }
/// <summary> /// Adds a single texture to the model and the cache. /// </summary> /// <param name="texture">The texture to be added</param> public void addTexture(RenderBase.OTexture texture) { models.texture.Add(texture); cacheTexture(texture); }
/// <summary> /// Gets a DirectX Stencil operation from a RenderBase Stencil operation. /// </summary> /// <param name="function">The stencil operation</param> /// <returns></returns> private StencilOperation getStencilOperation(RenderBase.OStencilOp operation) { switch (operation) { case RenderBase.OStencilOp.decrease: return StencilOperation.Decrement; case RenderBase.OStencilOp.decreaseWrap: return StencilOperation.DecrementSaturation; case RenderBase.OStencilOp.increase: return StencilOperation.Increment; case RenderBase.OStencilOp.increaseWrap: return StencilOperation.IncrementSaturation; case RenderBase.OStencilOp.keep: return StencilOperation.Keep; case RenderBase.OStencilOp.replace: return StencilOperation.Replace; case RenderBase.OStencilOp.zero: return StencilOperation.Zero; } return 0; }
/// <summary> /// Gets a DirectX Compare from a RenderBase Compare. /// </summary> /// <param name="function">The compare test function</param> /// <returns></returns> private Compare getCompare(RenderBase.OTestFunction function) { switch (function) { case RenderBase.OTestFunction.always: return Compare.Always; case RenderBase.OTestFunction.equal: return Compare.Equal; case RenderBase.OTestFunction.greater: return Compare.Greater; case RenderBase.OTestFunction.greaterOrEqual: return Compare.GreaterEqual; case RenderBase.OTestFunction.less: return Compare.Less; case RenderBase.OTestFunction.lessOrEqual: return Compare.LessEqual; case RenderBase.OTestFunction.never: return Compare.Never; case RenderBase.OTestFunction.notEqual: return Compare.NotEqual; } return 0; }
/// <summary> /// Decodes a PICA200 Texture. /// </summary> /// <param name="data">Buffer with the Texture</param> /// <param name="width">Width of the Texture</param> /// <param name="height">Height of the Texture</param> /// <param name="format">Pixel Format of the Texture</param> /// <returns></returns> public static Bitmap decode(byte[] data, int width, int height, RenderBase.OTextureFormat format) { byte[] output = new byte[width * height * 4]; long dataOffset = 0; bool toggle = false; switch (format) { case RenderBase.OTextureFormat.rgba8: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + ((tY * 8 + y) * width)) * 4; Buffer.BlockCopy(data, (int)dataOffset + 1, output, (int)outputOffset, 3); output[outputOffset + 3] = data[dataOffset]; dataOffset += 4; } } } break; case RenderBase.OTextureFormat.rgb8: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; Buffer.BlockCopy(data, (int)dataOffset, output, (int)outputOffset, 3); output[outputOffset + 3] = 0xff; dataOffset += 3; } } } break; case RenderBase.OTextureFormat.rgba5551: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; ushort pixelData = (ushort)(data[dataOffset] | (data[dataOffset + 1] << 8)); byte r = (byte)(((pixelData >> 1) & 0x1f) << 3); byte g = (byte)(((pixelData >> 6) & 0x1f) << 3); byte b = (byte)(((pixelData >> 11) & 0x1f) << 3); byte a = (byte)((pixelData & 1) * 0xff); output[outputOffset] = (byte)(r | (r >> 5)); output[outputOffset + 1] = (byte)(g | (g >> 5)); output[outputOffset + 2] = (byte)(b | (b >> 5)); output[outputOffset + 3] = a; dataOffset += 2; } } } break; case RenderBase.OTextureFormat.rgb565: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; ushort pixelData = (ushort)(data[dataOffset] | (data[dataOffset + 1] << 8)); byte r = (byte)((pixelData & 0x1f) << 3); byte g = (byte)(((pixelData >> 5) & 0x3f) << 2); byte b = (byte)(((pixelData >> 11) & 0x1f) << 3); output[outputOffset] = (byte)(r | (r >> 5)); output[outputOffset + 1] = (byte)(g | (g >> 6)); output[outputOffset + 2] = (byte)(b | (b >> 5)); output[outputOffset + 3] = 0xff; dataOffset += 2; } } } break; case RenderBase.OTextureFormat.rgba4: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; ushort pixelData = (ushort)(data[dataOffset] | (data[dataOffset + 1] << 8)); byte r = (byte)((pixelData >> 4) & 0xf); byte g = (byte)((pixelData >> 8) & 0xf); byte b = (byte)((pixelData >> 12) & 0xf); byte a = (byte)(pixelData & 0xf); output[outputOffset] = (byte)(r | (r << 4)); output[outputOffset + 1] = (byte)(g | (g << 4)); output[outputOffset + 2] = (byte)(b | (b << 4)); output[outputOffset + 3] = (byte)(a | (a << 4)); dataOffset += 2; } } } break; case RenderBase.OTextureFormat.la8: case RenderBase.OTextureFormat.hilo8: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; output[outputOffset] = data[dataOffset]; output[outputOffset + 1] = data[dataOffset]; output[outputOffset + 2] = data[dataOffset]; output[outputOffset + 3] = data[dataOffset + 1]; dataOffset += 2; } } } break; case RenderBase.OTextureFormat.l8: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; output[outputOffset] = data[dataOffset]; output[outputOffset + 1] = data[dataOffset]; output[outputOffset + 2] = data[dataOffset]; output[outputOffset + 3] = 0xff; dataOffset++; } } } break; case RenderBase.OTextureFormat.a8: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; output[outputOffset] = 0xff; output[outputOffset + 1] = 0xff; output[outputOffset + 2] = 0xff; output[outputOffset + 3] = data[dataOffset]; dataOffset++; } } } break; case RenderBase.OTextureFormat.la4: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; output[outputOffset] = (byte)(data[dataOffset] >> 4); output[outputOffset + 1] = (byte)(data[dataOffset] >> 4); output[outputOffset + 2] = (byte)(data[dataOffset] >> 4); output[outputOffset + 3] = (byte)(data[dataOffset] & 0xf); dataOffset++; } } } break; case RenderBase.OTextureFormat.l4: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; byte c = toggle ? (byte)((data[dataOffset++] & 0xf0) >> 4) : (byte)(data[dataOffset] & 0xf); toggle = !toggle; c = (byte)((c << 4) | c); output[outputOffset] = c; output[outputOffset + 1] = c; output[outputOffset + 2] = c; output[outputOffset + 3] = 0xff; } } } break; case RenderBase.OTextureFormat.a4: for (int tY = 0; tY < height / 8; tY++) { for (int tX = 0; tX < width / 8; tX++) { for (int pixel = 0; pixel < 64; pixel++) { int x = tileOrder[pixel] % 8; int y = (tileOrder[pixel] - x) / 8; long outputOffset = ((tX * 8) + x + (((tY * 8 + y)) * width)) * 4; output[outputOffset] = 0xff; output[outputOffset + 1] = 0xff; output[outputOffset + 2] = 0xff; byte a = toggle ? (byte)((data[dataOffset++] & 0xf0) >> 4) : (byte)(data[dataOffset] & 0xf); toggle = !toggle; output[outputOffset + 3] = (byte)((a << 4) | a); } } } break; case RenderBase.OTextureFormat.etc1: case RenderBase.OTextureFormat.etc1a4: byte[] decodedData = etc1Decode(data, width, height, format == RenderBase.OTextureFormat.etc1a4); int[] etc1Order = etc1Scramble(width, height); int i = 0; for (int tY = 0; tY < height / 4; tY++) { for (int tX = 0; tX < width / 4; tX++) { int TX = etc1Order[i] % (width / 4); int TY = (etc1Order[i] - TX) / (width / 4); for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { dataOffset = ((TX * 4) + x + (((TY * 4) + y) * width)) * 4; long outputOffset = ((tX * 4) + x + (((tY * 4 + y)) * width)) * 4; Buffer.BlockCopy(decodedData, (int)dataOffset, output, (int)outputOffset, 4); } } i += 1; } } break; } return TextureUtils.getBitmap(output.ToArray(), width, height); }
/// <summary> /// Opens the windows used for a model. /// More windows can be opened later, for files with model and other data. /// </summary> /// <param name="model">The model</param> /// <param name="name">The file name (without the full path and extension)</param> private void launchModel(RenderBase.OModelGroup model, string name) { OViewportWindow viewportWindow = new OViewportWindow(); OModelWindow modelWindow = new OModelWindow(); OTextureWindow textureWindow = new OTextureWindow(); OAnimationsWindow animationWindow = new OAnimationsWindow(); viewportWindow.Title = name; RenderEngine renderer = new RenderEngine(); renderer.MSAALevel = Settings.Default.reAALevel; renderer.bgColor = Settings.Default.reBgColor; renderer.useLegacyTexturing = Settings.Default.reUseLegacyTexturing; renderer.showGrid = Settings.Default.reShowGrids; renderer.showHUD = Settings.Default.reShowHUD; renderer.model = model; launchWindow(viewportWindow); DockContainer.dockMainWindow(); launchWindow(modelWindow, false); launchWindow(textureWindow, false); launchWindow(animationWindow, false); WindowManager.Refresh(); modelWindow.initialize(renderer); textureWindow.initialize(renderer); animationWindow.initialize(renderer); viewportWindow.initialize(renderer); }
/// <summary> /// Exports a Model to the Source Model format. /// Note: SMD model specification doesnt support Model and Skeletal Animation on the same SMD. /// See: https://developer.valvesoftware.com/wiki/Studiomdl_Data for more information. /// </summary> /// <param name="model">The Model that will be exported</param> /// <param name="fileName">The output File Name</param> /// <param name="modelIndex">Index of the model to be exported</param> /// <param name="skeletalAnimationIndex">(Optional) Index of the skeletal animation</param> public static void export(RenderBase.OModelGroup model, string fileName, int modelIndex, int skeletalAnimationIndex = -1) { RenderBase.OModel mdl = model.model[modelIndex]; StringBuilder output = new StringBuilder(); output.AppendLine("version 1"); output.AppendLine("nodes"); for (int i = 0; i < mdl.skeleton.Count; i++) { output.AppendLine(i + " \"" + mdl.skeleton[i].name + "\" " + mdl.skeleton[i].parentId); } output.AppendLine("end"); output.AppendLine("skeleton"); if (skeletalAnimationIndex == -1) { output.AppendLine("time 0"); int index = 0; foreach (RenderBase.OBone bone in mdl.skeleton) { string line = index.ToString(); line += " " + getString(bone.translation.x); line += " " + getString(bone.translation.y); line += " " + getString(bone.translation.z); line += " " + getString(bone.rotation.x); line += " " + getString(bone.rotation.y); line += " " + getString(bone.rotation.z); output.AppendLine(line); index++; } } else { bool error = false; for (float frame = 0; frame < model.skeletalAnimation.list[skeletalAnimationIndex].frameSize; frame += 1) { output.AppendLine("time " + ((int)frame).ToString()); for (int index = 0; index < mdl.skeleton.Count; index++) { RenderBase.OBone newBone = new RenderBase.OBone(); newBone.parentId = mdl.skeleton[index].parentId; newBone.rotation = new RenderBase.OVector3(mdl.skeleton[index].rotation); newBone.translation = new RenderBase.OVector3(mdl.skeleton[index].translation); foreach (RenderBase.OSkeletalAnimationBone b in ((RenderBase.OSkeletalAnimation)model.skeletalAnimation.list[skeletalAnimationIndex]).bone) { if (b.isFrameFormat || b.isFullBakedFormat) error = true; if (b.name == mdl.skeleton[index].name && !b.isFrameFormat && !b.isFullBakedFormat) { if (b.rotationX.exists) newBone.rotation.x = AnimationUtils.getKey(b.rotationX, frame); if (b.rotationY.exists) newBone.rotation.y = AnimationUtils.getKey(b.rotationY, frame); if (b.rotationZ.exists) newBone.rotation.z = AnimationUtils.getKey(b.rotationZ, frame); if (b.translationX.exists) { newBone.translation.x = AnimationUtils.getKey(b.translationX, frame); newBone.translation.x *= mdl.skeleton[index].absoluteScale.x; } if (b.translationY.exists) { newBone.translation.y = AnimationUtils.getKey(b.translationY, frame); newBone.translation.y *= mdl.skeleton[index].absoluteScale.y; } if (b.translationZ.exists) { newBone.translation.z = AnimationUtils.getKey(b.translationZ, frame); newBone.translation.z *= mdl.skeleton[index].absoluteScale.z; } break; } } string line = index.ToString(); line += " " + getString(newBone.translation.x); line += " " + getString(newBone.translation.y); line += " " + getString(newBone.translation.z); line += " " + getString(newBone.rotation.x); line += " " + getString(newBone.rotation.y); line += " " + getString(newBone.rotation.z); output.AppendLine(line); } } if (error) MessageBox.Show( "One or more bones uses an animation type unsupported by Source Model!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } output.AppendLine("end"); if (skeletalAnimationIndex == -1) { output.AppendLine("triangles"); uint triangleCount = 0; int objectIndex = 0; foreach (RenderBase.OMesh obj in mdl.mesh) { string textureName = mdl.material[obj.materialId].name0 ?? "material_" + objectIndex.ToString(); foreach (RenderBase.OVertex vertex in obj.vertices) { if (triangleCount == 0) output.AppendLine(textureName); string line = "0"; line += " " + getString(vertex.position.x); line += " " + getString(vertex.position.y); line += " " + getString(vertex.position.z); line += " " + getString(vertex.normal.x); line += " " + getString(vertex.normal.y); line += " " + getString(vertex.normal.z); line += " " + getString(vertex.texture0.x); line += " " + getString(vertex.texture0.y); int nodeCount = Math.Min(vertex.node.Count, vertex.weight.Count); line += " " + nodeCount; for (int i = 0; i < nodeCount; i++) { line += " " + vertex.node[i]; line += " " + getString(vertex.weight[i]); } output.AppendLine(line); triangleCount = (triangleCount + 1) % 3; } objectIndex++; } output.AppendLine("end"); } File.WriteAllText(fileName, output.ToString()); }
/// <summary> /// Gets an Animation Key frame from the CGFX file. /// The Reader position must be set to the beggining of the Key Frame Data. /// </summary> /// <param name="input">The CGFX file Reader</param> /// <param name="header">The CGFX file header</param> /// <returns></returns> private static void getAnimationKeyFrame(BinaryReader input, RenderBase.OAnimationKeyFrameGroup frame) { float startFrame = input.ReadSingle(); float endFrame = input.ReadSingle(); input.BaseStream.Seek(0x10, SeekOrigin.Current); frame.startFrame = input.ReadSingle(); frame.endFrame = input.ReadSingle(); uint segmentFlags = input.ReadUInt32(); switch (segmentFlags & 0xf) { case 0: frame.interpolation = RenderBase.OInterpolationMode.step; break; case 4: frame.interpolation = RenderBase.OInterpolationMode.linear; break; case 8: frame.interpolation = RenderBase.OInterpolationMode.hermite; break; } RenderBase.OSegmentQuantization quantization = (RenderBase.OSegmentQuantization)(segmentFlags >> 5); uint entries = input.ReadUInt32(); float invDuration = input.ReadSingle(); float valueScale = 1; float valueOffset = 0; float frameScale = 1; if (quantization != RenderBase.OSegmentQuantization.hermite128 && quantization != RenderBase.OSegmentQuantization.unifiedHermite96 && quantization != RenderBase.OSegmentQuantization.stepLinear64) { valueScale = input.ReadSingle(); valueOffset = input.ReadSingle(); frameScale = input.ReadSingle(); } for (int key = 0; key < entries; key++) { RenderBase.OAnimationKeyFrame keyFrame = new RenderBase.OAnimationKeyFrame(); switch (quantization) { case RenderBase.OSegmentQuantization.hermite128: keyFrame.frame = input.ReadSingle(); keyFrame.value = input.ReadSingle(); keyFrame.inSlope = input.ReadSingle(); keyFrame.outSlope = input.ReadSingle(); break; case RenderBase.OSegmentQuantization.hermite64: uint h64Value = input.ReadUInt32(); keyFrame.frame = h64Value & 0xfff; keyFrame.value = h64Value >> 12; keyFrame.inSlope = input.ReadInt16() / 256f; keyFrame.outSlope = input.ReadInt16() / 256f; break; case RenderBase.OSegmentQuantization.hermite48: keyFrame.frame = input.ReadByte(); keyFrame.value = input.ReadUInt16(); byte slope0 = input.ReadByte(); byte slope1 = input.ReadByte(); byte slope2 = input.ReadByte(); keyFrame.inSlope = IOUtils.signExtend(slope0 | ((slope1 & 0xf) << 8), 12) / 32f; keyFrame.outSlope = IOUtils.signExtend((slope1 >> 4) | (slope2 << 4), 12) / 32f; break; case RenderBase.OSegmentQuantization.unifiedHermite96: keyFrame.frame = input.ReadSingle(); keyFrame.value = input.ReadSingle(); keyFrame.inSlope = input.ReadSingle(); keyFrame.outSlope = keyFrame.inSlope; break; case RenderBase.OSegmentQuantization.unifiedHermite48: keyFrame.frame = input.ReadUInt16() / 32f; keyFrame.value = input.ReadUInt16(); keyFrame.inSlope = input.ReadInt16() / 256f; keyFrame.outSlope = keyFrame.inSlope; break; case RenderBase.OSegmentQuantization.unifiedHermite32: keyFrame.frame = input.ReadByte(); ushort uH32Value = input.ReadUInt16(); keyFrame.value = uH32Value & 0xfff; keyFrame.inSlope = IOUtils.signExtend((uH32Value >> 12) | (input.ReadByte() << 4), 12) / 32f; keyFrame.outSlope = keyFrame.inSlope; break; case RenderBase.OSegmentQuantization.stepLinear64: keyFrame.frame = input.ReadSingle(); keyFrame.value = input.ReadSingle(); break; case RenderBase.OSegmentQuantization.stepLinear32: uint sL32Value = input.ReadUInt32(); keyFrame.frame = sL32Value & 0xfff; keyFrame.value = sL32Value >> 12; break; } keyFrame.frame = (keyFrame.frame * frameScale) + startFrame; keyFrame.value = (keyFrame.value * valueScale) + valueOffset; frame.keyFrames.Add(keyFrame); } }
/// <summary> /// Exports a Model to the Collada format. /// See: https://www.khronos.org/files/collada_spec_1_4.pdf for more information. /// </summary> /// <param name="model">The Model that will be exported</param> /// <param name="fileName">The output File Name</param> /// <param name="modelIndex">Index of the model to be exported</param> /// <param name="skeletalAnimationIndex">(Optional) Index of the skeletal animation</param> public static void export(RenderBase.OModelGroup model, string fileName, int modelIndex, int skeletalAnimationIndex = -1) { RenderBase.OModel mdl = model.model[modelIndex]; COLLADA dae = new COLLADA(); dae.asset.created = DateTime.Now.ToString("yyyy-MM-ddThh:mm:ssZ"); dae.asset.modified = dae.asset.created; foreach (RenderBase.OTexture tex in model.texture) { daeImage img = new daeImage(); img.id = tex.name + "_id"; img.name = tex.name; img.init_from = "./" + tex.name + ".png"; dae.library_images.Add(img); } foreach (RenderBase.OMaterial mat in mdl.material) { daeMaterial mtl = new daeMaterial(); mtl.name = mat.name + "_mat"; mtl.id = mtl.name + "_id"; mtl.instance_effect.url = "#eff_" + mat.name + "_id"; dae.library_materials.Add(mtl); daeEffect eff = new daeEffect(); eff.id = "eff_" + mat.name + "_id"; eff.name = "eff_" + mat.name; daeParam surface = new daeParam(); surface.surface = new daeParamSurfaceElement(); surface.sid = "img_surface"; surface.surface.type = "2D"; surface.surface.init_from = mat.name0 + "_id"; surface.surface.format = "PNG"; eff.profile_COMMON.newparam.Add(surface); daeParam sampler = new daeParam(); sampler.sampler2D = new daeParamSampler2DElement(); sampler.sid = "img_sampler"; sampler.sampler2D.source = "img_surface"; switch (mat.textureMapper[0].wrapU) { case RenderBase.OTextureWrap.repeat: sampler.sampler2D.wrap_s = "WRAP"; break; case RenderBase.OTextureWrap.mirroredRepeat: sampler.sampler2D.wrap_s = "MIRROR"; break; case RenderBase.OTextureWrap.clampToEdge: sampler.sampler2D.wrap_s = "CLAMP"; break; case RenderBase.OTextureWrap.clampToBorder: sampler.sampler2D.wrap_s = "BORDER"; break; default: sampler.sampler2D.wrap_s = "NONE"; break; } switch (mat.textureMapper[0].wrapV) { case RenderBase.OTextureWrap.repeat: sampler.sampler2D.wrap_t = "WRAP"; break; case RenderBase.OTextureWrap.mirroredRepeat: sampler.sampler2D.wrap_t = "MIRROR"; break; case RenderBase.OTextureWrap.clampToEdge: sampler.sampler2D.wrap_t = "CLAMP"; break; case RenderBase.OTextureWrap.clampToBorder: sampler.sampler2D.wrap_t = "BORDER"; break; default: sampler.sampler2D.wrap_t = "NONE"; break; } switch (mat.textureMapper[0].minFilter) { case RenderBase.OTextureMinFilter.linearMipmapLinear: sampler.sampler2D.minfilter = "LINEAR_MIPMAP_LINEAR"; break; case RenderBase.OTextureMinFilter.linearMipmapNearest: sampler.sampler2D.minfilter = "LINEAR_MIPMAP_NEAREST"; break; case RenderBase.OTextureMinFilter.nearestMipmapLinear: sampler.sampler2D.minfilter = "NEAREST_MIPMAP_LINEAR"; break; case RenderBase.OTextureMinFilter.nearestMipmapNearest: sampler.sampler2D.minfilter = "NEAREST_MIPMAP_NEAREST"; break; default: sampler.sampler2D.minfilter = "NONE"; break; } switch (mat.textureMapper[0].magFilter) { case RenderBase.OTextureMagFilter.linear: sampler.sampler2D.magfilter = "LINEAR"; break; case RenderBase.OTextureMagFilter.nearest: sampler.sampler2D.magfilter = "NEAREST"; break; default: sampler.sampler2D.magfilter = "NONE"; break; } sampler.sampler2D.mipfilter = sampler.sampler2D.magfilter; eff.profile_COMMON.newparam.Add(sampler); eff.profile_COMMON.technique.sid = "img_technique"; eff.profile_COMMON.technique.phong.emission.set(Color.Black); eff.profile_COMMON.technique.phong.ambient.set(Color.Black); eff.profile_COMMON.technique.phong.specular.set(Color.White); eff.profile_COMMON.technique.phong.diffuse.texture.texture = "img_sampler"; dae.library_effects.Add(eff); } string jointNames = null; string invBindPoses = null; for (int index = 0; index < mdl.skeleton.Count; index++) { RenderBase.OMatrix transform = new RenderBase.OMatrix(); transformSkeleton(mdl.skeleton, index, ref transform); jointNames += mdl.skeleton[index].name; daeMatrix mtx = new daeMatrix(); mtx.set(transform.invert()); invBindPoses += mtx.data; if (index < mdl.skeleton.Count - 1) { jointNames += " "; invBindPoses += " "; } } int meshIndex = 0; daeVisualScene vs = new daeVisualScene(); vs.name = "vs_" + mdl.name; vs.id = vs.name + "_id"; if (mdl.skeleton.Count > 0) writeSkeleton(mdl.skeleton, 0, ref vs.node); foreach (RenderBase.OMesh obj in mdl.mesh) { //Geometry daeGeometry geometry = new daeGeometry(); string meshName = "mesh_" + meshIndex++ + "_" + obj.name; geometry.id = meshName + "_id"; geometry.name = meshName; MeshUtils.optimizedMesh mesh = MeshUtils.optimizeMesh(obj); List<float> positions = new List<float>(); List<float> normals = new List<float>(); List<float> uv0 = new List<float>(); List<float> uv1 = new List<float>(); List<float> uv2 = new List<float>(); List<float> colors = new List<float>(); foreach (RenderBase.OVertex vtx in mesh.vertices) { positions.Add(vtx.position.x); positions.Add(vtx.position.y); positions.Add(vtx.position.z); if (mesh.hasNormal) { normals.Add(vtx.normal.x); normals.Add(vtx.normal.y); normals.Add(vtx.normal.z); } if (mesh.texUVCount > 0) { uv0.Add(vtx.texture0.x); uv0.Add(vtx.texture0.y); } if (mesh.texUVCount > 1) { uv1.Add(vtx.texture1.x); uv1.Add(vtx.texture1.y); } if (mesh.texUVCount > 2) { uv2.Add(vtx.texture2.x); uv2.Add(vtx.texture2.y); } if (mesh.hasColor) { colors.Add(((vtx.diffuseColor >> 16) & 0xff) / 255f); colors.Add(((vtx.diffuseColor >> 8) & 0xff) / 255f); colors.Add((vtx.diffuseColor & 0xff) / 255f); colors.Add(((vtx.diffuseColor >> 24) & 0xff) / 255f); } } daeSource position = new daeSource(); position.name = meshName + "_position"; position.id = position.name + "_id"; position.float_array = new daeFloatArray(); position.float_array.id = position.name + "_array_id"; position.float_array.set(positions); position.technique_common.accessor.source = "#" + position.float_array.id; position.technique_common.accessor.count = (uint)mesh.vertices.Count; position.technique_common.accessor.stride = 3; position.technique_common.accessor.addParam("X", "float"); position.technique_common.accessor.addParam("Y", "float"); position.technique_common.accessor.addParam("Z", "float"); geometry.mesh.source.Add(position); daeSource normal = new daeSource(); if (mesh.hasNormal) { normal.name = meshName + "_normal"; normal.id = normal.name + "_id"; normal.float_array = new daeFloatArray(); normal.float_array.id = normal.name + "_array_id"; normal.float_array.set(normals); normal.technique_common.accessor.source = "#" + normal.float_array.id; normal.technique_common.accessor.count = (uint)mesh.vertices.Count; normal.technique_common.accessor.stride = 3; normal.technique_common.accessor.addParam("X", "float"); normal.technique_common.accessor.addParam("Y", "float"); normal.technique_common.accessor.addParam("Z", "float"); geometry.mesh.source.Add(normal); } daeSource[] texUV = new daeSource[3]; for (int i = 0; i < mesh.texUVCount; i++) { texUV[i] = new daeSource(); texUV[i].name = meshName + "_uv" + i; texUV[i].id = texUV[i].name + "_id"; texUV[i].float_array = new daeFloatArray(); texUV[i].float_array.id = texUV[i].name + "_array_id"; texUV[i].technique_common.accessor.source = "#" + texUV[i].float_array.id; texUV[i].technique_common.accessor.count = (uint)mesh.vertices.Count; texUV[i].technique_common.accessor.stride = 2; texUV[i].technique_common.accessor.addParam("S", "float"); texUV[i].technique_common.accessor.addParam("T", "float"); geometry.mesh.source.Add(texUV[i]); } daeSource color = new daeSource(); if (mesh.hasColor) { color.name = meshName + "_color"; color.id = color.name + "_id"; color.float_array = new daeFloatArray(); color.float_array.id = color.name + "_array_id"; color.float_array.set(colors); color.technique_common.accessor.source = "#" + color.float_array.id; color.technique_common.accessor.count = (uint)mesh.vertices.Count; color.technique_common.accessor.stride = 4; color.technique_common.accessor.addParam("R", "float"); color.technique_common.accessor.addParam("G", "float"); color.technique_common.accessor.addParam("B", "float"); color.technique_common.accessor.addParam("A", "float"); geometry.mesh.source.Add(color); } geometry.mesh.vertices.id = meshName + "_vertices_id"; geometry.mesh.vertices.addInput("POSITION", "#" + position.id); geometry.mesh.triangles.material = mdl.material[obj.materialId].name; geometry.mesh.triangles.addInput("VERTEX", "#" + geometry.mesh.vertices.id); if (mesh.hasNormal) geometry.mesh.triangles.addInput("NORMAL", "#" + normal.id); if (mesh.hasColor) geometry.mesh.triangles.addInput("COLOR", "#" + color.id); if (mesh.texUVCount > 0) { texUV[0].float_array.set(uv0); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[0].id); } if (mesh.texUVCount > 1) { texUV[1].float_array.set(uv1); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[1].id, 0, 1); } if (mesh.texUVCount > 2) { texUV[2].float_array.set(uv2); geometry.mesh.triangles.addInput("TEXCOORD", "#" + texUV[2].id, 0, 2); } geometry.mesh.triangles.set(mesh.indices); dae.library_geometries.Add(geometry); bool hasNode = obj.vertices[0].node.Count > 0; bool hasWeight = obj.vertices[0].weight.Count > 0; bool hasController = hasNode && hasWeight; //Controller daeController controller = new daeController(); if (hasController) { controller.id = meshName + "_ctrl_id"; controller.skin.source = "#" + geometry.id; controller.skin.bind_shape_matrix.set(new RenderBase.OMatrix()); daeSource joints = new daeSource(); joints.id = meshName + "_ctrl_joint_names_id"; joints.Name_array = new daeNameArray(); joints.Name_array.id = meshName + "_ctrl_joint_names_array_id"; joints.Name_array.count = (uint)mdl.skeleton.Count; joints.Name_array.data = jointNames; joints.technique_common.accessor.source = "#" + joints.Name_array.id; joints.technique_common.accessor.count = joints.Name_array.count; joints.technique_common.accessor.stride = 1; joints.technique_common.accessor.addParam("JOINT", "Name"); controller.skin.src.Add(joints); daeSource bindPoses = new daeSource(); bindPoses.id = meshName +"_ctrl_inv_bind_poses_id"; bindPoses.float_array = new daeFloatArray(); bindPoses.float_array.id = meshName + "_ctrl_inv_bind_poses_array_id"; bindPoses.float_array.count = (uint)(mdl.skeleton.Count * 16); bindPoses.float_array.data = invBindPoses; bindPoses.technique_common.accessor.source = "#" + bindPoses.float_array.id; bindPoses.technique_common.accessor.count = (uint)mdl.skeleton.Count; bindPoses.technique_common.accessor.stride = 16; bindPoses.technique_common.accessor.addParam("TRANSFORM", "float4x4"); controller.skin.src.Add(bindPoses); daeSource weights = new daeSource(); weights.id = meshName + "_ctrl_weights_id"; weights.float_array = new daeFloatArray(); weights.float_array.id = meshName + "_ctrl_weights_array_id"; weights.technique_common.accessor.source = "#" + weights.float_array.id; weights.technique_common.accessor.stride = 1; weights.technique_common.accessor.addParam("WEIGHT", "float"); StringBuilder w = new StringBuilder(); StringBuilder vcount = new StringBuilder(); StringBuilder v = new StringBuilder(); float[] wLookBack = new float[32]; uint wLookBackIndex = 0; int buffLen = 0; int wIndex = 0; int wCount = 0; foreach (RenderBase.OVertex vtx in mesh.vertices) { int count = Math.Min(vtx.node.Count, vtx.weight.Count); vcount.Append(count + " "); for (int n = 0; n < count; n++) { v.Append(vtx.node[n] + " "); bool found = false; uint bPos = (wLookBackIndex - 1) & 0x1f; for (int i = 0; i < buffLen; i++) { if (wLookBack[bPos] == vtx.weight[n]) { v.Append(wIndex - (i + 1) + " "); found = true; break; } bPos = (bPos - 1) & 0x1f; } if (!found) { v.Append(wIndex++ + " "); w.Append(vtx.weight[n].ToString(CultureInfo.InvariantCulture) + " "); wCount++; wLookBack[wLookBackIndex] = vtx.weight[n]; wLookBackIndex = (wLookBackIndex + 1) & 0x1f; if (buffLen < wLookBack.Length) buffLen++; } } } weights.float_array.data = w.ToString().TrimEnd(); weights.float_array.count = (uint)wCount; weights.technique_common.accessor.count = (uint)wCount; controller.skin.src.Add(weights); controller.skin.vertex_weights.vcount = vcount.ToString().TrimEnd(); controller.skin.vertex_weights.v = v.ToString().TrimEnd(); controller.skin.vertex_weights.count = (uint)mesh.vertices.Count; controller.skin.joints.addInput("JOINT", "#" + joints.id); controller.skin.joints.addInput("INV_BIND_MATRIX", "#" + bindPoses.id); controller.skin.vertex_weights.addInput("JOINT", "#" + joints.id); controller.skin.vertex_weights.addInput("WEIGHT", "#" + weights.id, 1); if (dae.library_controllers == null) dae.library_controllers = new List<daeController>(); dae.library_controllers.Add(controller); } //Visual scene node daeNode node = new daeNode(); node.name = "vsn_" + meshName; node.id = node.name + "_id"; node.matrix.set(new RenderBase.OMatrix()); if (hasController) { node.instance_controller = new daeInstanceController(); node.instance_controller.url = "#" + controller.id; node.instance_controller.skeleton = "#" + mdl.skeleton[0].name + "_bone_id"; node.instance_controller.bind_material.technique_common.instance_material.symbol = mdl.material[obj.materialId].name; node.instance_controller.bind_material.technique_common.instance_material.target = "#" + mdl.material[obj.materialId].name + "_mat_id"; } else { node.instance_geometry = new daeInstanceGeometry(); node.instance_geometry.url = "#" + geometry.id; node.instance_geometry.bind_material.technique_common.instance_material.symbol = mdl.material[obj.materialId].name; node.instance_geometry.bind_material.technique_common.instance_material.target = "#" + mdl.material[obj.materialId].name + "_mat_id"; } vs.node.Add(node); } dae.library_visual_scenes.Add(vs); daeInstaceVisualScene scene = new daeInstaceVisualScene(); scene.url = "#" + vs.id; dae.scene.Add(scene); XmlWriterSettings settings = new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true }; XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", "http://www.collada.org/2005/11/COLLADASchema"); XmlSerializer serializer = new XmlSerializer(typeof(COLLADA)); XmlWriter output = XmlWriter.Create(new FileStream(fileName, FileMode.Create), settings); serializer.Serialize(output, dae, ns); output.Close(); }
public void set(RenderBase.OMatrix mtx) { StringBuilder strArray = new StringBuilder(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (i == 3 && j == 3) strArray.Append(mtx[j, i].ToString(CultureInfo.InvariantCulture)); else strArray.Append(mtx[j, i].ToString(CultureInfo.InvariantCulture) + " "); } } data = strArray.ToString(); }
/// <summary> /// Loads a SMES file. /// </summary> /// <param name="fileName">File Name of the SMES file</param> /// <returns></returns> public static void load(string fileName, RenderBase.OModel model) { load(new MemoryStream(File.ReadAllBytes(fileName)), model); }
public CommandResize(RenderScene scene, RenderBase render) : base(scene, render.uniqueName) { this._orign = render.oriSize; this._finish = render.size; }
/// <summary> /// Loads a SMES file. /// Note that SMES must start at offset 0x0. /// </summary> /// <param name="data">Stream of the SMES file.</param> /// <returns></returns> public static void load(Stream data, RenderBase.OModel model, bool ignoreMaterial = false) { BinaryReader input = new BinaryReader(data); //The node indices points to the index directly relative to the tree index on the Skeleton //Therefore, we must build a table to translate from the Skeleton Index to the absolute Bone Tree Index List<int> nodeBinding = new List<int>(); buildNodeBinding(model.skeleton, 0, ref nodeBinding); string smesMagic = IOUtils.readStringWithLength(input, 4); uint dataTableOffset = input.ReadUInt32(); uint meshCount = input.ReadUInt32(); for (int meshIndex = 0; meshIndex < meshCount; meshIndex++) { //Mesh descriptor data.Seek(0xc + meshIndex * 0x20, SeekOrigin.Begin); uint vector3TableEntries = input.ReadUInt32(); uint vector3TableOffset = input.ReadUInt32(); uint attributesCount = input.ReadUInt32(); uint primitiveCount = input.ReadUInt32(); uint vertexBufferOffset = input.ReadUInt32(); uint indexSectionOffset = input.ReadUInt32(); uint renderPriority = input.ReadUInt32(); uint materialIndex = input.ReadUInt32(); //Index Buffer section data.Seek(indexSectionOffset, SeekOrigin.Begin); RenderBase.OMesh obj = new RenderBase.OMesh(); if (!ignoreMaterial) obj.materialId = (ushort)materialIndex; obj.isVisible = true; obj.hasNormal = true; obj.hasTangent = true; obj.texUVCount = 1; ushort[] nodes = null; uint skinningMode = 0; bool hasData = true; while (hasData) { string magic = IOUtils.readStringWithLength(input, 4); uint sectionLength = input.ReadUInt32(); long startOffset = data.Position; switch (magic) { case "SKIN": skinningMode = input.ReadUInt32(); break; //0 = rigid, 1 = smooth case "BONI": nodes = new ushort[input.ReadUInt16()]; for (int n = 0; n < nodes.Length; n++) nodes[n] = input.ReadUInt16(); obj.hasNode = true; obj.hasWeight = true; break; case "IDX ": input.ReadUInt16(); ushort indicesCount = input.ReadUInt16(); //Note: The Stride seems to always be 0x40 uint vertexStride = (indexSectionOffset - vertexBufferOffset) / primitiveCount; for (int i = 0; i < indicesCount; i++) { ushort index = input.ReadUInt16(); long position = data.Position; data.Seek(vertexBufferOffset + index * vertexStride, SeekOrigin.Begin); RenderBase.OVertex vertex = new RenderBase.OVertex(); vertex.diffuseColor = 0xffffffff; vertex.position = new RenderBase.OVector3(input.ReadSingle(), input.ReadSingle(), input.ReadSingle()); vertex.normal = new RenderBase.OVector3(input.ReadSingle(), input.ReadSingle(), input.ReadSingle()); vertex.tangent = new RenderBase.OVector3(input.ReadSingle(), input.ReadSingle(), input.ReadSingle()); vertex.texture0 = new RenderBase.OVector2(input.ReadSingle(), input.ReadSingle()); if (model.skeleton.Count > 0) { if (nodes != null && nodes.Length > 0) { byte b0 = input.ReadByte(); byte b1 = input.ReadByte(); byte b2 = input.ReadByte(); byte b3 = input.ReadByte(); if (b0 < nodes.Length) vertex.node.Add(nodeBinding[nodes[b0]]); if (skinningMode > 0) { if (b1 < nodes.Length) vertex.node.Add(nodeBinding[nodes[b1]]); if (b2 < nodes.Length) vertex.node.Add(nodeBinding[nodes[b2]]); if (b3 < nodes.Length) vertex.node.Add(nodeBinding[nodes[b3]]); } } vertex.weight.Add(input.ReadSingle()); if (skinningMode > 0) { vertex.weight.Add(input.ReadSingle()); vertex.weight.Add(input.ReadSingle()); vertex.weight.Add(input.ReadSingle()); } } MeshUtils.calculateBounds(model, vertex); obj.vertices.Add(vertex); data.Seek(position, SeekOrigin.Begin); } break; default: hasData = false; break; } data.Seek(startOffset + sectionLength, SeekOrigin.Begin); } model.mesh.Add(obj); } data.Close(); }
public CommandMove(RenderScene scene, RenderBase render) : base(scene, render.uniqueName) { this._orign = render.oriPos; this._finish = render.pos; }
/// <summary> /// Transforms a Node from relative to absolute positions. /// </summary> /// <param name="nodes">A list with all nodes</param> /// <param name="index">Index of the node to convert</param> /// <param name="target">Target matrix to save node transformation</param> private static void transformNode(List<node> nodes, int index, ref RenderBase.OMatrix target) { target *= nodes[index].transform; if (nodes[index].parentId > -1) transformNode(nodes, nodes[index].parentId, ref target); }
private static RenderBase generateViewBySrc(String src, RenderBase parent) { return(generateViewByXml(XmlHelper.Parse(src), parent)); }
/// <summary> /// Gets the current frame of a Material Animation color. /// </summary> /// <param name="data">The animation data</param> /// <param name="color">The color where the animation will be applied</param> private void getMaterialAnimationColor(RenderBase.OMaterialAnimationData data, ref Color color) { float r = AnimationUtils.getKey(data.frameList[0], ctrlMA.Frame); float g = AnimationUtils.getKey(data.frameList[1], ctrlMA.Frame); float b = AnimationUtils.getKey(data.frameList[2], ctrlMA.Frame); float a = AnimationUtils.getKey(data.frameList[3], ctrlMA.Frame); byte R = data.frameList[0].exists ? (byte)(r * 0xff) : color.R; byte G = data.frameList[1].exists ? (byte)(g * 0xff) : color.G; byte B = data.frameList[2].exists ? (byte)(b * 0xff) : color.B; byte A = data.frameList[3].exists ? (byte)(a * 0xff) : color.A; color = Color.FromArgb(A, R, G, B); }
public CommandAdd(RenderScene scene, RenderBase opItem) : base(scene, opItem.uniqueName) { xml = UIHelper.generateXmlByItem(opItem); parentUnique = opItem.getParent().uniqueName; }
/// <summary> /// Creates a Quaternion from a Rotation 3-D Vector. /// </summary> /// <param name="vector">The rotation vector</param> /// <returns></returns> private Quaternion getQuaternion(RenderBase.OVector3 vector) { Quaternion output = Quaternion.Identity; output *= Quaternion.RotationAxis(new Vector3(1, 0, 0), vector.x); output *= Quaternion.RotationAxis(new Vector3(0, 1, 0), vector.y); output *= Quaternion.RotationAxis(new Vector3(0, 0, 1), vector.z); return output; }