public virtual object LoadLodMesh(int level, string filename) { if (filename != "avatar_eye_1.llm") { ReferenceMesh refMesh = new ReferenceMesh(); refMesh.LoadMesh(filename); LodMeshes[level] = refMesh; return(refMesh); } LindenMesh fullMesh = new LindenMesh(""); fullMesh.LoadMesh(filename); LodMeshes[level] = fullMesh; return(fullMesh); }
public virtual object LoadLodMesh(int level, string filename) { if (filename != "avatar_eye_1.llm") { ReferenceMesh refMesh = new ReferenceMesh(); refMesh.LoadMesh(filename); LodMeshes[level] = refMesh; return refMesh; } LindenMesh fullMesh = new LindenMesh(""); fullMesh.LoadMesh(filename); LodMeshes[level] = fullMesh; return fullMesh; }
/// <summary> /// Create a mesh for the avatar. We either use the specified avatar mesh or create the /// mesh from the LAD definition file. /// </summary> public bool CreateAvatarMeshResource(float priority, IEntity ent, string meshName, EntityName contextEntity) { if (m_defaultAvatarMesh != null && m_defaultAvatarMesh.Length > 0) { return CreateAvatarMeshFromDefault(priority, ent, meshName, contextEntity); } string meshInfoDir = LookingGlassBase.Instance.AppParams.ParamString("Renderer.Avatar.Mesh.InfoDir"); string meshInfoDefn = LookingGlassBase.Instance.AppParams.ParamString("Renderer.Avatar.Mesh.Description"); string meshDescriptionDir = LookingGlassBase.Instance.AppParams.ParamString("Renderer.Avatar.Mesh.DescriptionDir"); Dictionary<string, OMVR.LindenMesh> meshTypes = new Dictionary<string, OMVR.LindenMesh>(); XmlDocument lad = new XmlDocument(); lad.Load(Path.Combine(meshInfoDir, meshInfoDefn)); XmlNodeList meshes = lad.GetElementsByTagName("mesh"); foreach (XmlNode meshNode in meshes) { string type = meshNode.Attributes.GetNamedItem("type").Value; int lod = Int32.Parse(meshNode.Attributes.GetNamedItem("lod").Value); string fileName = meshNode.Attributes.GetNamedItem("file_name").Value; //string minPixelWidth = meshNode.Attributes.GetNamedItem("min_pixel_width").Value; // for the moment, ignore the skirt if (type == "skirtMesh") continue; if (lod == 0) { // only collect the meshes with the highest resolution try { fileName = Path.Combine(meshDescriptionDir, fileName); if (!meshTypes.ContainsKey(type)) { OMVR.LindenMesh lmesh = new OMVR.LindenMesh(type); lmesh.LoadMesh(fileName); meshTypes.Add(type, lmesh); } } catch (Exception e) { m_log.Log(LogLevel.DBADERROR, "Failure reading avatar defn file {0}: {1}", fileName, e); } } } // meshTypes now contains the pieces of the avatar. string[] meshOrder = { "headMesh", "upperBodyMesh", "lowerBodyMesh", "eyeBallLeftMesh", "hairMesh", "skirtMesh", "eyelashMesh", "eyeBallRightMesh" }; // Assemble into one mesh for passing to lower system // TODO: get and pass the skeleton information if (!CreateAvatarTextures(ent, false)) { // something about the textures can't be built yet. Try again later. return false; } const int faceCountsStride = 6; const int verticesStride = 8; const int indicesStride = 3; const int vertexColorStride = 4; // calculate how many floating point numbers we're pushing over int[] faceCounts = new int[meshTypes.Count * faceCountsStride + 2]; faceCounts[0] = faceCounts.Length; faceCounts[1] = meshTypes.Count; int totalVertices = 0; try { for (int jj=0; jj < meshTypes.Count; jj++) { if (!meshTypes.ContainsKey(meshOrder[jj])) continue; OMVR.LindenMesh lmesh = meshTypes[meshOrder[jj]]; int faceBase = jj * faceCountsStride + 2; faceCounts[faceBase + 0] = totalVertices; faceCounts[faceBase + 1] = lmesh.NumVertices; faceCounts[faceBase + 2] = verticesStride; totalVertices += vertexColorStride + lmesh.NumVertices * verticesStride; faceCounts[faceBase + 3] = totalVertices; faceCounts[faceBase + 4] = lmesh.NumFaces * indicesStride; faceCounts[faceBase + 5] = indicesStride; totalVertices += lmesh.NumFaces * indicesStride; } float[] faceVertices = new float[totalVertices + 2]; faceVertices[0] = faceVertices.Length; int vertI = 1; for (int jj=0; jj < meshTypes.Count; jj++) { if (!meshTypes.ContainsKey(meshOrder[jj])) continue; OMVR.LindenMesh lmesh = meshTypes[meshOrder[jj]]; faceVertices[vertI + 0] = 0.6f; faceVertices[vertI + 1] = 0.6f; faceVertices[vertI + 2] = 0.6f; faceVertices[vertI + 3] = 0.5f; vertI += vertexColorStride; for (int k = 0; k < lmesh.NumVertices; k++) { OMVR.LindenMesh.Vertex thisVert = lmesh.Vertices[k]; // m_log.Log(LogLevel.DRENDERDETAIL, "CreateMesh: vertices: p={0}, t={1}, n={2}", // thisVert.Position.ToString(), thisVert.TexCoord.ToString(), thisVert.Normal.ToString()); faceVertices[vertI + 0] = thisVert.Coord.X; faceVertices[vertI + 1] = thisVert.Coord.Y; faceVertices[vertI + 2] = thisVert.Coord.Z; faceVertices[vertI + 3] = thisVert.TexCoord.X; faceVertices[vertI + 4] = thisVert.TexCoord.Y; faceVertices[vertI + 5] = thisVert.Normal.X; faceVertices[vertI + 6] = thisVert.Normal.Y; faceVertices[vertI + 7] = thisVert.Normal.Z; vertI += verticesStride; } for (int k = 0; k < lmesh.NumFaces; k++) { faceVertices[vertI + 0] = lmesh.Faces[k].Indices[0]; faceVertices[vertI + 1] = lmesh.Faces[k].Indices[1]; faceVertices[vertI + 2] = lmesh.Faces[k].Indices[2]; vertI += indicesStride; } } m_log.Log(LogLevel.DRENDERDETAIL, "RenderOgreLL.CreateAvatarMeshResource: {0}, fcs={1}, fs={2}, vi={3}", ent.Name, faceCounts.Length, faceVertices.Length, vertI ); // We were passed a 'context' entity. Create a scene node name to pass to // Ogre. If the scene node is not found, nothing bad happens. string contextSceneNode = EntityNameOgre.ConvertToOgreSceneNodeName(contextEntity); // Now create the mesh Ogr.CreateMeshResourceBF(priority, meshName, contextSceneNode, faceCounts, faceVertices); } catch (Exception e) { m_log.Log(LogLevel.DBADERROR, "Failure building avatar mesh: {0}", e); } return true; }