/// <summary> /// Adds the given strand array to this hair mesh. /// </summary> /// <param name="strands"></param> public void AddStrands(TressFXStrand[] strands) { foreach (TressFXStrand strand in strands) { this.AddStrand(strand); } }
/// <summary> /// Adds the given strand to this tressfx hair mesh. /// </summary> /// <param name="strand"></param> public void AddStrand(TressFXStrand strand) { // Set lowest / highest vertex counts if (this.lowestVertexPerStrandCount == 0 || this.lowestVertexPerStrandCount > strand.vertices.Length) { this.lowestVertexPerStrandCount = strand.vertices.Length; } else if (this.highestVertexPerStrandCount == 0 || this.highestVertexPerStrandCount < strand.vertices.Length) { this.highestVertexPerStrandCount = strand.vertices.Length; } vertexCount += strand.vertices.Length; this.strands.Add(strand); }
/// <summary> /// This function converts the current tressfx hair object to a binary tressfx asset for use in unity. /// </summary> /// <returns></returns> public byte[] GenerateBinaryTressFXAsset() { // Generate follow hairs TressFXStrand[] followHairs = new TressFXStrand[0]; if (this.numFollowHairsPerGuideHair > 0) { // Now start follow hair generation int numFollowHairs = this.numFollowHairsPerGuideHair * this.strands.Count; // Follow hairs per guide hair * guide hairs followHairs = new TressFXStrand[numFollowHairs]; for (int i = 0; i < numFollowHairs; i++) { } } return null; }
public void LoadTressFXFile(string file) { ConsoleUtil.LogToConsole("Loading tressfx mesh file " + file, ConsoleColor.Yellow); this.filename = file; string[] lines = File.ReadAllLines(file); List<TressFXStrand> strands = new List<TressFXStrand>(); // Parse file for (int i = 0; i < lines.Length; i++) { string[] tokens = lines[i].Split(' '); switch (tokens[0]) { // Header information case "scale": this.scale = ParseUtils.ParseFloat(tokens[1]); break; case "rotation": this.rotation = new Vector3(ParseUtils.ParseFloat(tokens[1]), ParseUtils.ParseFloat(tokens[2]), ParseUtils.ParseFloat(tokens[3])); break; case "translation": this.translation = new Vector3(ParseUtils.ParseFloat(tokens[1]),ParseUtils.ParseFloat(tokens[2]),ParseUtils.ParseFloat(tokens[3])); break; case "bothEndsImmovable": this.bothEndsImmovable = (int.Parse(tokens[1]) == 1); break; case "numFollowHairsPerGuideHair": this.numFollowHairsPerGuideHair = int.Parse(tokens[1]); break; case "maxRadiusAroundGuideHair": this.maxRadiusAroundGuideHair = ParseUtils.ParseFloat(tokens[1]); break; // Strand information case "strand": int strandIndex = int.Parse(tokens[1]); int vertices = int.Parse(tokens[3]); float texcoordX = float.Parse(tokens[5]); TressFXStrand strand = new TressFXStrand(); strand.vertices = new Vector3[vertices]; for (int j = 0; j < vertices; j++) { i++; string[] vertexTokens = lines[i].Split(' '); float x = 0; float y = 0; float z = 0; // Replace points with comma's for (int k = 0; k < vertexTokens.Length; k++) vertexTokens[k] = vertexTokens[k].Replace('.', ','); if (float.TryParse(vertexTokens[0], out x) && float.TryParse(vertexTokens[1], out y) && float.TryParse(vertexTokens[2], out z)) { this.vertexCount++; strand.vertices[j] = new Vector3(x, y, z); } else { strand = null; break; } } if (strand != null) this.AddStrand(strand); break; } } ConsoleUtil.LogToConsole("Loaded tressfx file! Strands: " + this.strands.Count + ", Vertices: " + this.vertexCount, ConsoleColor.Green); ConsoleUtil.LogToConsole("Highest vertex count per strand: " + this.highestVertexPerStrandCount + ", Lowest count: " + this.lowestVertexPerStrandCount, ConsoleColor.Green); ConsoleUtil.LogToConsole("Header Information: ", ConsoleColor.Blue); ConsoleUtil.LogToConsole("Scale: " + this.scale, ConsoleColor.Blue); ConsoleUtil.LogToConsole("Rotation: " + this.rotation, ConsoleColor.Blue); ConsoleUtil.LogToConsole("Translation: " + this.translation, ConsoleColor.Blue); ConsoleUtil.LogToConsole("Both ends immovable: " + this.bothEndsImmovable, ConsoleColor.Blue); ConsoleUtil.LogToConsole("Num follow hairs per guide hair: " + this.numFollowHairsPerGuideHair, ConsoleColor.Blue); ConsoleUtil.LogToConsole("Max radius around guide hair: " + this.maxRadiusAroundGuideHair, ConsoleColor.Blue); }
/// <summary> /// Converts a given ase file to a dictionary of tressfx hairs. /// Key of the dictionary contains the mesh name, value is the tressfxhair data. /// </summary> /// <param name="asefile"></param> /// <param name="hairFilePrefix"></param> /// <param name="directory"></param> /// <returns></returns> public static Dictionary<string, TressFXHair> ConvertAse(string asefile) { // Start parsing the file ConsoleUtil.LogToConsole("Loading ASE File...", ConsoleColor.Blue); string[] aseContent = File.ReadAllLines(asefile); Dictionary<string, TressFXHair> hairMeshes = new Dictionary<string, TressFXHair>(); List<TressFXStrand> currentStrands = new List<TressFXStrand>(); string aseFilenameWithoutExt = Path.GetFileNameWithoutExtension(asefile); int currentStrand = 0; int currentHairId = -1; float texcoordMultiplier = 0; ConsoleUtil.LogToConsole("Starting ASE parsing... This may take a LONG while..", ConsoleColor.Blue); // Now the hard part begins... for (int i = 0; i < aseContent.Length; i++) { string[] tokens = aseContent[i].Split('\t'); if (aseContent[i].Contains("*SHAPE_LINECOUNT")) { tokens = tokens[1].Split(' '); } else if (aseContent[i].Contains("SHAPE_LINE")) { tokens = tokens[1].Split(' '); } if (tokens.Length >= 2) { if (tokens[0] == "*SHAPE_LINECOUNT") { if (currentStrand > 0) { currentHairId++; currentStrand = 0; // Add to mesh list TressFXHair hairMesh = new TressFXHair(); foreach (TressFXStrand strand in currentStrands) { hairMesh.AddStrand(strand); } hairMeshes.Add(aseFilenameWithoutExt + "_" + currentHairId, hairMesh); // Clear current strands currentStrands.Clear(); texcoordMultiplier = 1.0f / (float)int.Parse(tokens[1]); ConsoleUtil.LogToConsole("Starting parse hair: " + currentHairId + ", lines count: " + int.Parse(tokens[1]), ConsoleColor.Yellow); } } else if (tokens[0] == "*SHAPE_LINE") { // Parse the current line Vector3[] positions = null; string[] vertexCountTokens = aseContent[i + 1].Split(' '); positions = new Vector3[int.Parse(vertexCountTokens[1])]; // Parse vertices for (int j = 0; j < positions.Length; j++) { string[] vertexTokens = aseContent[i + 2 + j].Replace('.', ',').Split('\t'); positions[j] = new Vector3(float.Parse(vertexTokens[4]), float.Parse(vertexTokens[5]), float.Parse(vertexTokens[6])); } TressFXStrand strand = new TressFXStrand(); strand.vertices = positions; strand.texcoordX = texcoordMultiplier * currentStrand; currentStrands.Add(strand); i = i + 1 + positions.Length; currentStrand++; } } } ConsoleUtil.LogToConsole("Asefile Parsed! Hairs parsed: " + currentHairId + "!", ConsoleColor.Green); return hairMeshes; }