2 using System.Collections.Generic;
\r
7 using OpenTK.Graphics.OpenGL;
\r
8 using System.Runtime.InteropServices;
\r
10 using OpenMetaverse.Rendering;
\r
12 namespace Radegast.Rendering
\r
14 public class FaceData
\r
16 public float[] Vertices;
\r
17 public ushort[] Indices;
\r
18 public float[] TexCoords;
\r
19 public float[] Normals;
\r
20 public int PickingID = -1;
\r
21 public int VertexVBO = -1;
\r
22 public int IndexVBO = -1;
\r
23 public TextureInfo TextureInfo = new TextureInfo();
\r
24 public BoundingSphere BoundingSphere = new BoundingSphere();
\r
25 public static int VertexSize = 32; // sizeof (vertex), 2 x vector3 + 1 x vector2 = 8 floats x 4 bytes = 32 bytes
\r
27 public void CheckVBO(Face face)
\r
29 if (VertexVBO == -1)
\r
31 Vertex[] vArray = face.Vertices.ToArray();
\r
32 GL.GenBuffers(1, out VertexVBO);
\r
33 GL.BindBuffer(BufferTarget.ArrayBuffer, VertexVBO);
\r
34 GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vArray.Length * VertexSize), vArray, BufferUsageHint.StreamDraw);
\r
39 ushort[] iArray = face.Indices.ToArray();
\r
40 GL.GenBuffers(1, out IndexVBO);
\r
41 GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexVBO);
\r
42 GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(iArray.Length * sizeof(ushort)), iArray, BufferUsageHint.StreamDraw);
\r
47 public class TextureInfo
\r
49 public System.Drawing.Image Texture;
\r
50 public int TexturePointer;
\r
51 public bool HasAlpha;
\r
52 public UUID TextureID;
\r
55 public class TextureLoadItem
\r
57 public FaceData Data;
\r
58 public Primitive Prim;
\r
59 public Primitive.TextureEntryFace TeFace;
\r
62 public enum RenderPass
\r
69 public static class Render
\r
71 public static IRendering Plugin;
\r
74 public static class RHelp
\r
76 public static OpenTK.Vector2 TKVector3(Vector2 v)
\r
78 return new OpenTK.Vector2(v.X, v.Y);
\r
81 public static OpenTK.Vector3 TKVector3(Vector3 v)
\r
83 return new OpenTK.Vector3(v.X, v.Y, v.Z);
\r
86 public static OpenTK.Vector4 TKVector3(Vector4 v)
\r
88 return new OpenTK.Vector4(v.X, v.Y, v.Z, v.W);
\r
93 /// Represents camera object
\r
95 public struct Camera
\r
98 Vector3 mFocalPoint;
\r
101 /// <summary>Camera position</summary>
\r
102 public Vector3 Position { get { return mPosition; } set { mPosition = value; mModified = true; } }
\r
103 /// <summary>Camera target</summary>
\r
104 public Vector3 FocalPoint { get { return mFocalPoint; } set { mFocalPoint = value; mModified = true; } }
\r
105 /// <summary>Zoom level</summary>
\r
107 /// <summary>Draw distance</summary>
\r
109 /// <summary>Has camera been modified</summary>
\r
110 public bool Modified { get { return mModified; } set { mModified = value; } }
\r
113 public static class MeshToOBJ
\r
115 public static bool MeshesToOBJ(Dictionary<uint, FacetedMesh> meshes, string filename)
\r
117 StringBuilder obj = new StringBuilder();
\r
118 StringBuilder mtl = new StringBuilder();
\r
120 FileInfo objFileInfo = new FileInfo(filename);
\r
122 string mtlFilename = objFileInfo.FullName.Substring(objFileInfo.DirectoryName.Length + 1,
\r
123 objFileInfo.FullName.Length - (objFileInfo.DirectoryName.Length + 1) - 4) + ".mtl";
\r
125 obj.AppendLine("# Created by libprimrender");
\r
126 obj.AppendLine("mtllib ./" + mtlFilename);
\r
129 mtl.AppendLine("# Created by libprimrender");
\r
133 foreach (FacetedMesh mesh in meshes.Values)
\r
135 for (int j = 0; j < mesh.Faces.Count; j++)
\r
137 Face face = mesh.Faces[j];
\r
139 if (face.Vertices.Count > 2)
\r
141 string mtlName = String.Format("material{0}-{1}", primNr, face.ID);
\r
142 Primitive.TextureEntryFace tex = face.TextureFace;
\r
143 string texName = tex.TextureID.ToString() + ".tga";
\r
145 // FIXME: Convert the source to TGA (if needed) and copy to the destination
\r
147 float shiny = 0.00f;
\r
150 case Shininess.High:
\r
153 case Shininess.Medium:
\r
156 case Shininess.Low:
\r
161 obj.AppendFormat("g face{0}-{1}{2}", primNr, face.ID, Environment.NewLine);
\r
163 mtl.AppendLine("newmtl " + mtlName);
\r
164 mtl.AppendFormat("Ka {0} {1} {2}{3}", tex.RGBA.R, tex.RGBA.G, tex.RGBA.B, Environment.NewLine);
\r
165 mtl.AppendFormat("Kd {0} {1} {2}{3}", tex.RGBA.R, tex.RGBA.G, tex.RGBA.B, Environment.NewLine);
\r
166 //mtl.AppendFormat("Ks {0} {1} {2}{3}");
\r
167 mtl.AppendLine("Tr " + tex.RGBA.A);
\r
168 mtl.AppendLine("Ns " + shiny);
\r
169 mtl.AppendLine("illum 1");
\r
170 if (tex.TextureID != UUID.Zero && tex.TextureID != Primitive.TextureEntry.WHITE_TEXTURE)
\r
171 mtl.AppendLine("map_Kd ./" + texName);
\r
174 // Write the vertices, texture coordinates, and vertex normals for this side
\r
175 for (int k = 0; k < face.Vertices.Count; k++)
\r
177 Vertex vertex = face.Vertices[k];
\r
181 Vector3 pos = vertex.Position;
\r
184 pos *= mesh.Prim.Scale;
\r
187 pos *= mesh.Prim.Rotation;
\r
189 // The root prim position is sim-relative, while child prim positions are
\r
190 // parent-relative. We want to apply parent-relative translations but not
\r
191 // sim-relative ones
\r
192 if (mesh.Prim.ParentID != 0)
\r
193 pos += mesh.Prim.Position;
\r
195 obj.AppendFormat("v {0} {1} {2}{3}", pos.X, pos.Y, pos.Z, Environment.NewLine);
\r
199 #region Texture Coord
\r
201 obj.AppendFormat("vt {0} {1}{2}", vertex.TexCoord.X, vertex.TexCoord.Y,
\r
202 Environment.NewLine);
\r
204 #endregion Texture Coord
\r
206 #region Vertex Normal
\r
208 // HACK: Sometimes normals are getting set to <NaN,NaN,NaN>
\r
209 if (!Single.IsNaN(vertex.Normal.X) && !Single.IsNaN(vertex.Normal.Y) && !Single.IsNaN(vertex.Normal.Z))
\r
210 obj.AppendFormat("vn {0} {1} {2}{3}", vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z,
\r
211 Environment.NewLine);
\r
213 obj.AppendLine("vn 0.0 1.0 0.0");
\r
215 #endregion Vertex Normal
\r
218 obj.AppendFormat("# {0} vertices{1}", face.Vertices.Count, Environment.NewLine);
\r
220 obj.AppendLine("usemtl " + mtlName);
\r
224 // Write all of the faces (triangles) for this side
\r
225 for (int k = 0; k < face.Indices.Count / 3; k++)
\r
227 obj.AppendFormat("f -{0}/-{0}/-{0} -{1}/-{1}/-{1} -{2}/-{2}/-{2}{3}",
\r
228 face.Vertices.Count - face.Indices[k * 3 + 0],
\r
229 face.Vertices.Count - face.Indices[k * 3 + 1],
\r
230 face.Vertices.Count - face.Indices[k * 3 + 2],
\r
231 Environment.NewLine);
\r
234 obj.AppendFormat("# {0} elements{1}", face.Indices.Count / 3, Environment.NewLine);
\r
237 #endregion Elements
\r
245 File.WriteAllText(filename, obj.ToString());
\r
246 File.WriteAllText(mtlFilename, mtl.ToString());
\r
257 public static class Math3D
\r
265 public static float[] CreateTranslationMatrix(Vector3 v)
\r
267 float[] mat = new float[16];
\r
272 mat[0] = mat[5] = mat[10] = mat[15] = 1;
\r
277 public static float[] CreateRotationMatrix(Quaternion q)
\r
279 float[] mat = new float[16];
\r
281 // Transpose the quaternion (don't ask me why)
\r
286 float x2 = q.X + q.X;
\r
287 float y2 = q.Y + q.Y;
\r
288 float z2 = q.Z + q.Z;
\r
289 float xx = q.X * x2;
\r
290 float xy = q.X * y2;
\r
291 float xz = q.X * z2;
\r
292 float yy = q.Y * y2;
\r
293 float yz = q.Y * z2;
\r
294 float zz = q.Z * z2;
\r
295 float wx = q.W * x2;
\r
296 float wy = q.W * y2;
\r
297 float wz = q.W * z2;
\r
299 mat[0] = 1.0f - (yy + zz);
\r
305 mat[5] = 1.0f - (xx + zz);
\r
311 mat[10] = 1.0f - (xx + yy);
\r
322 public static float[] CreateScaleMatrix(Vector3 v)
\r
324 float[] mat = new float[16];
\r
334 public static bool GluProject(OpenTK.Vector3 objPos, OpenTK.Matrix4 modelMatrix, OpenTK.Matrix4 projMatrix, int[] viewport, out OpenTK.Vector3 screenPos)
\r
336 OpenTK.Vector4 _in;
\r
337 OpenTK.Vector4 _out;
\r
344 _out = OpenTK.Vector4.Transform(_in, modelMatrix);
\r
345 _in = OpenTK.Vector4.Transform(_out, projMatrix);
\r
349 screenPos = OpenTK.Vector3.Zero;
\r
356 /* Map x, y and z to range 0-1 */
\r
357 _in.X = _in.X * 0.5f + 0.5f;
\r
358 _in.Y = _in.Y * 0.5f + 0.5f;
\r
359 _in.Z = _in.Z * 0.5f + 0.5f;
\r
361 /* Map x,y to viewport */
\r
362 _in.X = _in.X * viewport[2] + viewport[0];
\r
363 _in.Y = _in.Y * viewport[3] + viewport[1];
\r
365 screenPos.X = _in.X;
\r
366 screenPos.Y = _in.Y;
\r
367 screenPos.Z = _in.Z;
\r
373 public class attachment_point
\r
375 public string name;
\r
376 public string joint;
\r
377 public Vector3 position;
\r
378 public Vector3 rotation;
\r
382 public GLMesh jointmesh;
\r
383 public int jointmeshindex;
\r
385 public Vector3 getposition()
\r
388 pos = jointmesh.Position + position;
\r
392 public Quaternion getrotation()
\r
394 Vector3 rotvec = jointmesh.RotationAngles + rotation;
\r
395 rotvec.Normalize();
\r
396 Quaternion rot = new Quaternion(rotvec.X, rotvec.Y, rotvec.Z);
\r
402 /// Subclass of LindenMesh that adds vertex, index, and texture coordinate
\r
403 /// arrays suitable for pushing direct to OpenGL
\r
405 public class GLMesh : LindenMesh
\r
408 /// Subclass of LODMesh that adds an index array suitable for pushing
\r
409 /// direct to OpenGL
\r
413 public int teFaceID;
\r
415 new public class LODMesh : LindenMesh.LODMesh
\r
417 public ushort[] Indices;
\r
419 public override void LoadMesh(string filename)
\r
421 base.LoadMesh(filename);
\r
423 // Generate the index array
\r
424 Indices = new ushort[_numFaces * 3];
\r
426 for (int i = 0; i < _numFaces; i++)
\r
428 Indices[current++] = (ushort)_faces[i].Indices[0];
\r
429 Indices[current++] = (ushort)_faces[i].Indices[1];
\r
430 Indices[current++] = (ushort)_faces[i].Indices[2];
\r
438 public struct GLData
\r
440 public float[] Vertices;
\r
441 public ushort[] Indices;
\r
442 public float[] TexCoords;
\r
443 public Vector3 Center;
\r
446 public static GLData baseRenderData;
\r
447 public GLData RenderData;
\r
449 public GLMesh(string name)
\r
454 public override void LoadMesh(string filename)
\r
456 base.LoadMesh(filename);
\r
458 float minX, minY, minZ;
\r
459 minX = minY = minZ = Single.MaxValue;
\r
460 float maxX, maxY, maxZ;
\r
461 maxX = maxY = maxZ = Single.MinValue;
\r
463 // Generate the vertex array
\r
464 RenderData.Vertices = new float[_numVertices * 3];
\r
466 for (int i = 0; i < _numVertices; i++)
\r
468 RenderData.Vertices[current++] = _vertices[i].Coord.X;
\r
469 RenderData.Vertices[current++] = _vertices[i].Coord.Y;
\r
470 RenderData.Vertices[current++] = _vertices[i].Coord.Z;
\r
472 if (_vertices[i].Coord.X < minX)
\r
473 minX = _vertices[i].Coord.X;
\r
474 else if (_vertices[i].Coord.X > maxX)
\r
475 maxX = _vertices[i].Coord.X;
\r
477 if (_vertices[i].Coord.Y < minY)
\r
478 minY = _vertices[i].Coord.Y;
\r
479 else if (_vertices[i].Coord.Y > maxY)
\r
480 maxY = _vertices[i].Coord.Y;
\r
482 if (_vertices[i].Coord.Z < minZ)
\r
483 minZ = _vertices[i].Coord.Z;
\r
484 else if (_vertices[i].Coord.Z > maxZ)
\r
485 maxZ = _vertices[i].Coord.Z;
\r
488 // Calculate the center-point from the bounding box edges
\r
489 RenderData.Center = new Vector3((minX + maxX) / 2, (minY + maxY) / 2, (minZ + maxZ) / 2);
\r
491 // Generate the index array
\r
492 RenderData.Indices = new ushort[_numFaces * 3];
\r
494 for (int i = 0; i < _numFaces; i++)
\r
496 RenderData.Indices[current++] = (ushort)_faces[i].Indices[0];
\r
497 RenderData.Indices[current++] = (ushort)_faces[i].Indices[1];
\r
498 RenderData.Indices[current++] = (ushort)_faces[i].Indices[2];
\r
501 // Generate the texcoord array
\r
502 RenderData.TexCoords = new float[_numVertices * 2];
\r
504 for (int i = 0; i < _numVertices; i++)
\r
506 RenderData.TexCoords[current++] = _vertices[i].TexCoord.X;
\r
507 RenderData.TexCoords[current++] = _vertices[i].TexCoord.Y;
\r
511 public override void LoadLODMesh(int level, string filename)
\r
513 LODMesh lod = new LODMesh();
\r
514 lod.LoadMesh(filename);
\r
515 _lodMeshes[level] = lod;
\r
519 public class GLAvatar
\r
521 public static Dictionary<string, GLMesh> _meshes = new Dictionary<string, GLMesh>();
\r
522 public static bool _wireframe = true;
\r
523 public static bool _showSkirt = false;
\r
524 public static Dictionary<int, attachment_point> attachment_points = new Dictionary<int, attachment_point>();
\r
526 public static void loadlindenmeshes(string LODfilename)
\r
528 string basedir = Directory.GetCurrentDirectory() + System.IO.Path.DirectorySeparatorChar + "character" + System.IO.Path.DirectorySeparatorChar;
\r
530 // Parse through avatar_lad.xml to find all of the mesh references
\r
531 XmlDocument lad = new XmlDocument();
\r
532 lad.Load(basedir + LODfilename);
\r
534 attachment_points.Clear();
\r
536 XmlNodeList attach_points = lad.GetElementsByTagName("attachment_point");
\r
537 foreach (XmlNode apoint in attach_points)
\r
539 attachment_point point = new attachment_point();
\r
540 point.name = apoint.Attributes.GetNamedItem("name").Value;
\r
541 point.joint = apoint.Attributes.GetNamedItem("joint").Value;
\r
543 string pos = apoint.Attributes.GetNamedItem("position").Value;
\r
544 string[] posparts = pos.Split(' ');
\r
545 point.position = new Vector3(float.Parse(posparts[0]), float.Parse(posparts[1]), float.Parse(posparts[2]));
\r
547 string rot = apoint.Attributes.GetNamedItem("rotation").Value;
\r
548 string[] rotparts = rot.Split(' ');
\r
549 point.rotation = new Vector3(float.Parse(rotparts[0]), float.Parse(rotparts[1]), float.Parse(rotparts[2]));
\r
551 point.id = Int32.Parse(apoint.Attributes.GetNamedItem("id").Value);
\r
552 point.group = Int32.Parse(apoint.Attributes.GetNamedItem("group").Value);
\r
554 attachment_points.Add(point.id, point);
\r
558 XmlNodeList bones = lad.GetElementsByTagName("bone");
\r
560 XmlNodeList meshes = lad.GetElementsByTagName("mesh");
\r
562 foreach (XmlNode meshNode in meshes)
\r
564 string type = meshNode.Attributes.GetNamedItem("type").Value;
\r
565 int lod = Int32.Parse(meshNode.Attributes.GetNamedItem("lod").Value);
\r
566 string fileName = meshNode.Attributes.GetNamedItem("file_name").Value;
\r
567 //string minPixelWidth = meshNode.Attributes.GetNamedItem("min_pixel_width").Value;
\r
569 GLMesh mesh = (_meshes.ContainsKey(type) ? _meshes[type] : new GLMesh(type));
\r
573 case "lowerBodyMesh":
\r
574 mesh.teFaceID = (int)AvatarTextureIndex.LowerBaked;
\r
577 case "upperBodyMesh":
\r
578 mesh.teFaceID = (int)AvatarTextureIndex.UpperBaked;
\r
582 mesh.teFaceID = (int)AvatarTextureIndex.HeadBaked;
\r
586 mesh.teFaceID = (int)AvatarTextureIndex.HairBaked;
\r
589 case "eyelashMesh":
\r
590 mesh.teFaceID = (int)AvatarTextureIndex.HeadBaked;
\r
593 case "eyeBallRightMesh":
\r
594 case "eyeBallLeftMesh":
\r
595 mesh.teFaceID = (int)AvatarTextureIndex.EyesBaked;
\r
599 mesh.teFaceID = (int)AvatarTextureIndex.SkirtBaked;
\r
609 mesh.LoadMesh(basedir + fileName);
\r
613 mesh.LoadLODMesh(lod, basedir + fileName);
\r
616 _meshes[type] = mesh;
\r
620 //Associate each attachment point with the mesh that has its bones/joints
\r
621 foreach (attachment_point apoint in attachment_points.Values)
\r
625 foreach (string jointname in mesh.SkinJoints)
\r
627 if (jointname == apoint.joint)
\r
629 apoint.jointmesh = mesh;
\r
630 apoint.jointmeshindex = index;
\r
631 Logger.Log("Adding " + apoint.name +"with joint "+ jointname + "to mesh " + mesh.Name,Helpers.LogLevel.Info);
\r
646 public GLAvatar glavatar;
\r
647 public Avatar avatar;
\r
648 public FaceData[] data = new FaceData[32];
\r