/// <summary> /// /// </summary> /// <param name="group"></param> /// <param name="entity"></param> protected ImpostorTexture(ImpostorPage group, Entity entity) { //Store scene manager and entity mSceneMgr = group.SceneManager; mEntity = entity; //Add self to list of ImpostorTexture's mEntityKey = ImpostorBatch.GenerateEntityKey(entity); mSelfList.Add(mEntityKey, this); //Calculate the entity's bounding box and it's diameter mBoundingBox = entity.BoundingBox; //Note - this radius calculation assumes the object is somewhat rounded (like trees/rocks/etc.) float tmp = 0; mEntityRadius = mBoundingBox.Maximum.x - mBoundingBox.Center.x; tmp = mBoundingBox.Maximum.y - mBoundingBox.Center.y; if (tmp > mEntityRadius) mEntityRadius = tmp; tmp = mBoundingBox.Maximum.z - mBoundingBox.Center.z; if (tmp > mEntityRadius) mEntityRadius = tmp; mEntityDiameter = 2.0f * mEntityRadius; mEntityCenter = mBoundingBox.Center; //Render impostor textures RenderTextures(false); //Set up materials for (int o = 0; o < ImpostorYawAngles; o++) { for (int i = 0; i < ImpostorPitchAngles; i++) { mMaterial[i, o] = (Material)MaterialManager.Instance.Create(GetUniqueID("ImpostorMaterial"), "Impostors"); Material m = mMaterial[i, o]; Pass p = m.GetTechnique(0).GetPass(0); TextureUnitState t = p.CreateTextureUnitState(mTexture.Name); t.TextureScrollU = (float)(o / ImpostorYawAngles); t.TextureScrollV = (float)(i / ImpostorPitchAngles); p.LightingEnabled = false; m.ReceiveShadows = false; if (group.BlendMode == ImpostorBlendMode.AlphaReject) { p.AlphaRejectFunction = CompareFunction.GreaterEqual; p.AlphaRejectValue = 128; } else if (group.BlendMode == ImpostorBlendMode.AlphaBlend) { p.SetSceneBlending(SceneBlendFactor.SourceAlpha, SceneBlendFactor.OneMinusSourceAlpha); } } } }
/// <summary> /// /// </summary> /// <param name="group"></param> /// <param name="entity"></param> protected ImpostorBatch(ImpostorPage group, Entity entity) { //Render impostor texture for this entity mTex = ImpostorTexture.GetTexture(group, entity); //Create billboard set mBBSet = new StaticBillboardSet(group.SceneManager, group.PagedGeometry.SceneNode); mBBSet.SetTextureStacksAndSlices(ImpostorTexture.ImpostorPitchAngles, ImpostorTexture.ImpostorYawAngles); BillboardOrigin = ImpostorPage.ImpostorPivot; //Default the angle to 0 degrees mPitchIndex = -1; mYawIndex = -1; SetAngle(0.0f, 0.0f); }
/// <summary> /// /// </summary> /// <param name="group"></param> /// <param name="entity"></param> /// <returns></returns> public static ImpostorTexture GetTexture(ImpostorPage group, Entity entity) { //Search for an existing impostor texture for the given entity string entityKey = ImpostorBatch.GenerateEntityKey(entity); ImpostorTexture texture = null; if (!mSelfList.TryGetValue(entityKey, out texture)) { if (group != null) { texture = new ImpostorTexture(group, entity); } } return(texture); }
/// <summary> /// /// </summary> /// <param name="group"></param> /// <param name="entity"></param> /// <returns></returns> public static ImpostorBatch GetBatch(ImpostorPage group, Entity entity) { //Search for an existing impostor batch for this entity string entityKey = GenerateEntityKey(entity); ImpostorBatch batch = null; if (!group.mImpostorBatches.TryGetValue(entityKey, out batch)) { //Otherwise, create a new batch batch = new ImpostorBatch(group, entity); //Add it to the impostorBatches list group.mImpostorBatches.Add(entityKey, batch); } return(batch); }
/// <summary> /// /// </summary> /// <param name="group"></param> /// <param name="entity"></param> protected ImpostorBatch(ImpostorPage group, Entity entity) { //Render impostor texture for this entity mTex = ImpostorTexture.GetTexture(group, entity); //Create billboard set mBBSet = new StaticBillboardSet(group.SceneManager, group.PagedGeometry.SceneNode); mBBSet.SetTextureStacksAndSlices(ImpostorTexture.ImpostorPitchAngles, ImpostorTexture.ImpostorYawAngles); BillboardOrigin = ImpostorPage.ImpostorPivot; //Default the angle to 0 degrees mPitchIndex = -1; mYawIndex = -1; SetAngle(0.0f, 0.0f); }
/// <summary> /// /// </summary> /// <param name="group"></param> /// <param name="entity"></param> /// <returns></returns> public static ImpostorBatch GetBatch(ImpostorPage group, Entity entity) { //Search for an existing impostor batch for this entity string entityKey = GenerateEntityKey(entity); ImpostorBatch batch = null; if (!group.mImpostorBatches.TryGetValue(entityKey, out batch)) { //Otherwise, create a new batch batch = new ImpostorBatch(group, entity); //Add it to the impostorBatches list group.mImpostorBatches.Add(entityKey, batch); } return batch; }
/// <summary> /// /// </summary> /// <param name="group"></param> /// <param name="entity"></param> /// <returns></returns> public static ImpostorTexture GetTexture(ImpostorPage group, Entity entity) { //Search for an existing impostor texture for the given entity string entityKey = ImpostorBatch.GenerateEntityKey(entity); ImpostorTexture texture = null; if (!mSelfList.TryGetValue(entityKey, out texture)) { if (group != null) { texture = new ImpostorTexture(group, entity); } } return texture; }
/// <summary> /// /// </summary> /// <param name="group"></param> /// <param name="entity"></param> protected ImpostorTexture(ImpostorPage group, Entity entity) { //Store scene manager and entity mSceneMgr = group.SceneManager; mEntity = entity; //Add self to list of ImpostorTexture's mEntityKey = ImpostorBatch.GenerateEntityKey(entity); mSelfList.Add(mEntityKey, this); //Calculate the entity's bounding box and it's diameter mBoundingBox = entity.BoundingBox; //Note - this radius calculation assumes the object is somewhat rounded (like trees/rocks/etc.) float tmp = 0; mEntityRadius = mBoundingBox.Maximum.x - mBoundingBox.Center.x; tmp = mBoundingBox.Maximum.y - mBoundingBox.Center.y; if (tmp > mEntityRadius) { mEntityRadius = tmp; } tmp = mBoundingBox.Maximum.z - mBoundingBox.Center.z; if (tmp > mEntityRadius) { mEntityRadius = tmp; } mEntityDiameter = 2.0f * mEntityRadius; mEntityCenter = mBoundingBox.Center; //Render impostor textures RenderTextures(false); //Set up materials for (int o = 0; o < ImpostorYawAngles; o++) { for (int i = 0; i < ImpostorPitchAngles; i++) { mMaterial[i, o] = (Material)MaterialManager.Instance.Create(GetUniqueID("ImpostorMaterial"), "Impostors"); Material m = mMaterial[i, o]; Pass p = m.GetTechnique(0).GetPass(0); TextureUnitState t = p.CreateTextureUnitState(mTexture.Name); t.TextureScrollU = (float)(o / ImpostorYawAngles); t.TextureScrollV = (float)(i / ImpostorPitchAngles); p.LightingEnabled = false; m.ReceiveShadows = false; if (group.BlendMode == ImpostorBlendMode.AlphaReject) { p.AlphaRejectFunction = CompareFunction.GreaterEqual; p.AlphaRejectValue = 128; } else if (group.BlendMode == ImpostorBlendMode.AlphaBlend) { p.SetSceneBlending(SceneBlendFactor.SourceAlpha, SceneBlendFactor.OneMinusSourceAlpha); } } } }
/// <summary> /// /// </summary> /// <param name="bounds"></param> /// <returns></returns> internal void InitPages <T>(TBounds bounds) { // Calculate grid size, if left is Real minimum, it means that bounds are infinite // scrollBuffer is used as a flag. If it is allocated than infinite bounds are used // !!! Two cases are required because of the way scrolling is implemented // if it is redesigned it would allow to use the same functionality. if (bounds.Width < 0.00001f) { // In case of infinite bounds bounding rect needs to be calculated in a different manner, since // it represents local bounds, which are shifted along with the player's movements around the world. mGeomGridX = (int)((2 * mFarTransDist / mMainGeom.PageSize) + 4); mGridBounds.Top = 0; mGridBounds.Left = 0; mGridBounds.Right = mGeomGridX * mMainGeom.PageSize; mGridBounds.Bottom = mGeomGridX * mMainGeom.PageSize; // Allocate scroll buffer (used in scrolling the grid) mScrollBuffer = new GeometryPage[mGeomGridX]; //Note: All this padding and transition preparation is performed because even in infinite //mode, a local grid size must be chosen. Unfortunately, this also means that view ranges //and transition lengths cannot be exceeded dynamically with set functions. } else { //Bounded mode mGridBounds = bounds; // In case the devision does not give the round number use the next largest integer mGeomGridX = (int)System.Math.Ceiling(mGridBounds.Width / mMainGeom.PageSize); } mGeomGridZ = mGeomGridX;//Note: geomGridX == geomGridZ; Need to merge. //Allocate grid array mGeomGrid = new GeometryPage[mGeomGridX * mGeomGridZ]; for (int x = 0; x < mGeomGridX; ++x) { for (int z = 0; z < mGeomGridZ; ++z) { GeometryPage p = null; Type t = typeof(T); switch (t.Name) { case "GrassPage": p = new GrassPage(); break; case "BatchPage": p = new BatchPage(); break; case "ImpostorPage": p = new ImpostorPage(); break; default: throw new Exception("This GeometryPage is Unkown!,GeometryPageManager.Update!"); break; } p.Init(mMainGeom); float cx = 0, cy = 0, cz = 0; // 0,0 page is located at (gridBounds.left,gridBounds.top) corner of the bounds cx = ((x + 0.5f) * mMainGeom.PageSize) + mGridBounds.Left; cz = ((z + 0.5f) * mMainGeom.PageSize) + mGridBounds.Top; cy = 0.0f; p.CenterPoint = new Vector3(cx, cy, cz); p.mXIndex = x; p.mZIndex = z; p.mInactiveTime = 0; p.mIsLoaded = false; p.mNeedsUnload = false; p.mIsPending = false; p.mIsVisible = false; p.mUserData = null; p.ClearBoundingBox(); SetGridPage(x, z, p); } } }