/// <summary> /// Create the animation. The passed animation block is expected /// to contain a defintion of a fixed rotation. If not, bad things will happen. /// </summary> /// <param name="anim">The IAnimation block with the info.</param> /// <param name="id">localID to lookup the prim in the RegionRenderInfo.renderPrimList</param> public AnimatPosition(OMV.Vector3 newPos, float durationSeconds, RegionRenderInfo rri, uint id) : base(AnimatBase.AnimatTypePosition) { m_infoID = id; RenderablePrim rp = rri.renderPrimList[id]; m_origionalPosition = rp.Position; m_targetPosition = newPos; m_durationSeconds = durationSeconds; m_distanceVector = m_targetPosition - m_origionalPosition; m_progress = 0f; }
private void ComputeVisibility(RegionContextBase rcontext, RegionRenderInfo rri) { m_renderer.Camera.ComputeFrustum(); lock (rri.renderPrimList) { foreach (uint ind in rri.renderPrimList.Keys) { RenderablePrim rp = rri.renderPrimList[ind]; rp.isVisible = m_renderer.Camera.isVisible(rp.Position.X, rp.Position.Y, rp.Position.Z, 10f); } } return; }
/// <summary> /// Called for each frame. Advance the position. /// </summary> /// <param name="timeSinceLastFrame">seconds since last frame display</param> /// <param name="rri">RegionRenderInfo for region the animation is in</param> /// <returns>true to say we never exit</returns> public override bool Process(float timeSinceLastFrame, RegionRenderInfo rri) { bool ret = true; float thisProgress = timeSinceLastFrame / m_durationSeconds; m_progress += thisProgress; RenderablePrim rp = rri.renderPrimList[m_infoID]; if (m_progress >= 1f) { // if progressed all the way, we're at the destination rp.Position = m_targetPosition; ret = false; // we're done animating } else { // only part way there rp.Position = m_origionalPosition + m_distanceVector * m_progress; } return(ret); }
/// <summary> /// Called for each frame. Advance the rotation. /// </summary> /// <param name="timeSinceLastFrame">seconds since last frame display</param> /// <param name="rri">RegionRenderInfo for region the animation is in</param> /// <returns>true to say we never exit</returns> public override bool Process(float timeSinceLastFrame, RegionRenderInfo rri) { float nextStep = m_rotationsPerSecond * timeSinceLastFrame; float nextIncrement = Constants.TWOPI * nextStep; while (nextIncrement > Constants.TWOPI) { nextIncrement -= Constants.TWOPI; } OMV.Quaternion newRotation = OMV.Quaternion.CreateFromAxisAngle(m_rotationAxis, nextIncrement); lock (rri) { try { RenderablePrim rp = rri.renderPrimList[m_infoID]; rp.Rotation = newRotation * rp.Rotation; } catch (Exception e) { LogManager.Log.Log(LogLevel.DBADERROR, "Did not find prim for FixedRotation: {0}", e); } } return(true); // we never exit }
//int[] CubeMapDefines = new int[] //{ // Gl.GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, // Gl.GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, // Gl.GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, // Gl.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, // Gl.GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, // Gl.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB //}; private void RenderPrims(RegionContextBase rcontext, RegionRenderInfo rri) { GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.Texture2D); lock (rri.renderPrimList) { bool firstPass = true; // GL.Disable(EnableCap.Blend); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.Normalize); GL.EnableClientState(ArrayCap.TextureCoordArray); GL.EnableClientState(ArrayCap.VertexArray); GL.EnableClientState(ArrayCap.NormalArray); StartRender: List <RenderablePrim> rpList = new List <RenderablePrim>(rri.renderPrimList.Values); // sort back to front rpList.Sort(delegate(RenderablePrim rp1, RenderablePrim rp2) { return((int)(((OMV.Vector3.Distance(m_renderer.Camera.Position, rp1.Prim.Position)) - (OMV.Vector3.Distance(m_renderer.Camera.Position, rp2.Prim.Position))) * 100f)); }); foreach (RenderablePrim rp in rpList) { // if this prim is not visible, just loop if (!rp.isVisible) { continue; } RenderablePrim prp = RenderablePrim.Empty; OMV.Primitive prim = rp.Prim; if (prim.ParentID != 0) { // Get the parent reference if (!rri.renderPrimList.TryGetValue(prim.ParentID, out prp)) { // Can't render a child with no parent prim, skip it continue; } } GL.PushName(prim.LocalID); GL.PushMatrix(); if (prim.ParentID != 0) { // Apply parent translation and rotation GL.MultMatrix(Math3D.CreateTranslationMatrix(prp.Position)); GL.MultMatrix(Math3D.CreateRotationMatrix(prp.Rotation)); } // Apply prim translation and rotation GL.MultMatrix(Math3D.CreateTranslationMatrix(rp.Position)); // apply region offset for multiple regions GL.MultMatrix(Math3D.CreateTranslationMatrix(CalcRegionOffset(rp.rcontext))); GL.MultMatrix(Math3D.CreateRotationMatrix(rp.Rotation)); // Scale the prim GL.Scale(prim.Scale.X, prim.Scale.Y, prim.Scale.Z); // Draw the prim faces for (int j = 0; j < rp.Mesh.Faces.Count; j++) { OMVR.Face face = rp.Mesh.Faces[j]; FaceData data = (FaceData)face.UserData; OMV.Color4 color = face.TextureFace.RGBA; bool alpha = false; int textureID = 0; if (color.A < 1.0f) { alpha = true; } TextureInfo info; if (face.TextureFace.TextureID != OMV.UUID.Zero && face.TextureFace.TextureID != OMV.Primitive.TextureEntry.WHITE_TEXTURE && m_renderer.Textures.TryGetValue(face.TextureFace.TextureID, out info)) { if (info.Alpha) { alpha = true; } textureID = info.ID; // if textureID has not been set, need to generate the mipmaps if (textureID == 0) { GenerateMipMaps(rp.acontext, face.TextureFace.TextureID, out textureID); info.ID = textureID; } // Enable texturing for this face GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } else { if (face.TextureFace.TextureID == OMV.Primitive.TextureEntry.WHITE_TEXTURE || face.TextureFace.TextureID == OMV.UUID.Zero) { GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill); } else { GL.PolygonMode(MaterialFace.Front, PolygonMode.Line); } } // if (firstPass && !alpha || !firstPass && alpha) { // GL.Color4(color.R, color.G, color.B, color.A); float[] matDiffuse = { color.R, color.G, color.B, color.A }; GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, matDiffuse); // Bind the texture if (textureID != 0) { GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, textureID); } else { GL.Disable(EnableCap.Texture2D); } GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, data.TexCoords); GL.VertexPointer(3, VertexPointerType.Float, 0, data.Vertices); GL.NormalPointer(NormalPointerType.Float, 0, data.Normals); GL.DrawElements(BeginMode.Triangles, data.Indices.Length, DrawElementsType.UnsignedShort, data.Indices); // } } GL.PopMatrix(); GL.PopName(); } /* * if (firstPass) { * firstPass = false; * GL.Enable(EnableCap.Blend); * GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); * // GL.Disable(EnableCap.DepthTest); * * goto StartRender; * } */ } GL.Enable(EnableCap.DepthTest); GL.Disable(EnableCap.Texture2D); }
public void RenderUpdate(IEntity ent, UpdateCodes what) { m_log.Log(LogLevel.DRENDERDETAIL, "RenderUpdate: {0} for {1}", ent.Name.Name, what); bool fullUpdate = false; lock (ent) { if (ent is LLEntityBase && ((what & UpdateCodes.New) != 0)) { CreateNewPrim((LLEntityBase)ent); fullUpdate = true; } if ((what & UpdateCodes.Animation) != 0) { // the prim has changed its rotation animation IAnimation anim; if (ent.TryGet <IAnimation>(out anim)) { m_log.Log(LogLevel.DRENDERDETAIL, "RenderUpdate: animation "); RegionRenderInfo rri; if (ent.RegionContext.TryGet <RegionRenderInfo>(out rri)) { lock (rri) { rri.animations.Add(AnimatBase.CreateAnimation(anim, ((LLEntityBase)ent).Prim.LocalID)); } } } } if ((what & UpdateCodes.Text) != 0) { // text associated with the prim changed m_log.Log(LogLevel.DRENDERDETAIL, "RenderUpdate: text changed"); } if ((what & UpdateCodes.Particles) != 0) { // particles associated with the prim changed m_log.Log(LogLevel.DRENDERDETAIL, "RenderUpdate: particles changed"); } if (!fullUpdate && (what & (UpdateCodes.Scale | UpdateCodes.Position | UpdateCodes.Rotation)) != 0) { // world position has changed. Tell Ogre they have changed try { m_log.Log(LogLevel.DRENDERDETAIL, "RenderUpdate: Updating position/rotation for {0}", ent.Name.Name); RegionRenderInfo rri; if (ent.RegionContext.TryGet <RegionRenderInfo>(out rri)) { lock (rri.renderPrimList) { // exception if the casting does not work if (((LLEntityBase)ent).Prim != null) { uint localID = ((LLEntityBase)ent).Prim.LocalID; if (rri.renderPrimList.ContainsKey(localID)) { RenderablePrim rp = rri.renderPrimList[localID]; rp.Position = new OMV.Vector3(ent.RegionPosition.X, ent.RegionPosition.Y, ent.RegionPosition.Z); rp.Rotation = new OMV.Quaternion(ent.Heading.X, ent.Heading.Y, ent.Heading.Z, ent.Heading.W); } } } } } catch (Exception e) { m_log.Log(LogLevel.DBADERROR, "RenderUpdate: FAIL updating pos/rot: {0}", e); } } } return; }
private void CreateNewPrim(LLEntityBase ent) { m_log.Log(LogLevel.DRENDERDETAIL, "Create new prim {0}", ent.Name.Name); // entity render info is kept per region. Get the region prim structure RegionRenderInfo rri = GetRegionRenderInfo(ent.RegionContext); IEntityAvatar av; if (ent.TryGet <IEntityAvatar>(out av)) { // if this entity is an avatar, just put it on the display list lock (rri.renderAvatarList) { if (!rri.renderAvatarList.ContainsKey(av.LGID)) { RenderableAvatar ravv = new RenderableAvatar(); ravv.avatar = av; rri.renderAvatarList.Add(av.LGID, ravv); } } return; } OMV.Primitive prim = ent.Prim; /* don't do foliage yet * if (prim.PrimData.PCode == OMV.PCode.Grass || prim.PrimData.PCode == OMV.PCode.Tree || prim.PrimData.PCode == OMV.PCode.NewTree) { || lock (renderFoliageList) || renderFoliageList[prim.LocalID] = prim; || return; ||} */ RenderablePrim render = new RenderablePrim(); render.Prim = prim; render.acontext = ent.AssetContext; render.rcontext = ent.RegionContext; render.Position = prim.Position; render.Rotation = prim.Rotation; render.isVisible = true; // initially assume visible if (m_meshMaker == null) { m_meshMaker = new Renderer.Mesher.MeshmerizerR(); m_meshMaker.ShouldScaleMesh = false; } if (prim.Sculpt != null) { EntityNameLL textureEnt = EntityNameLL.ConvertTextureWorldIDToEntityName(ent.AssetContext, prim.Sculpt.SculptTexture); System.Drawing.Bitmap textureBitmap = ent.AssetContext.GetTexture(textureEnt); if (textureBitmap == null) { // the texture is not available. Request it. // Note that we just call this routine again when it is available. Hope it's not recursive ent.AssetContext.DoTextureLoad(textureEnt, AssetContextBase.AssetType.SculptieTexture, delegate(string name, bool trans) { CreateNewPrim(ent); return; } ); return; } render.Mesh = m_meshMaker.GenerateSculptMesh(textureBitmap, prim, OMVR.DetailLevel.Medium); textureBitmap.Dispose(); } else { render.Mesh = m_meshMaker.GenerateFacetedMesh(prim, OMVR.DetailLevel.High); } if (render.Mesh == null) { // mesh generation failed m_log.Log(LogLevel.DBADERROR, "FAILED MESH GENERATION: not generating new prim {0}", ent.Name.Name); return; } // Create a FaceData struct for each face that stores the 3D data // in an OpenGL friendly format for (int j = 0; j < render.Mesh.Faces.Count; j++) { OMVR.Face face = render.Mesh.Faces[j]; FaceData data = new FaceData(); // Vertices for this face data.Vertices = new float[face.Vertices.Count * 3]; for (int k = 0; k < face.Vertices.Count; k++) { data.Vertices[k * 3 + 0] = face.Vertices[k].Position.X; data.Vertices[k * 3 + 1] = face.Vertices[k].Position.Y; data.Vertices[k * 3 + 2] = face.Vertices[k].Position.Z; } // Indices for this face data.Indices = face.Indices.ToArray(); // Texture transform for this face OMV.Primitive.TextureEntryFace teFace = prim.Textures.GetFace((uint)j); m_meshMaker.TransformTexCoords(face.Vertices, face.Center, teFace); // Texcoords for this face data.TexCoords = new float[face.Vertices.Count * 2]; for (int k = 0; k < face.Vertices.Count; k++) { data.TexCoords[k * 2 + 0] = face.Vertices[k].TexCoord.X; data.TexCoords[k * 2 + 1] = face.Vertices[k].TexCoord.Y; } data.Normals = new float[face.Vertices.Count * 3]; for (int k = 0; k < face.Vertices.Count; k++) { data.Normals[k * 3 + 0] = face.Vertices[k].Normal.X; data.Normals[k * 3 + 1] = face.Vertices[k].Normal.Y; data.Normals[k * 3 + 2] = face.Vertices[k].Normal.Z; } // m_log.Log(LogLevel.DRENDERDETAIL, "CreateNewPrim: v={0}, i={1}, t={2}", // data.Vertices.GetLength(0), data.Indices.GetLength(0), data.TexCoords.GetLength(0)); // Texture for this face if (teFace.TextureID != OMV.UUID.Zero && teFace.TextureID != OMV.Primitive.TextureEntry.WHITE_TEXTURE) { lock (Textures) { if (!Textures.ContainsKey(teFace.TextureID)) { // temporarily add the entry to the table so we don't request it multiple times Textures.Add(teFace.TextureID, new TextureInfo(0, true)); // We haven't constructed this image in OpenGL yet, get ahold of it AssetContextBase.RequestTextureLoad( EntityNameLL.ConvertTextureWorldIDToEntityName(ent.AssetContext, teFace.TextureID), AssetContextBase.AssetType.Texture, OnTextureDownloadFinished); } } } // Set the UserData for this face to our FaceData struct face.UserData = data; render.Mesh.Faces[j] = face; } lock (rri.renderPrimList) { rri.renderPrimList[prim.LocalID] = render; } }