//--------------------------------------------------------------------- void PanelOverlayElement::updatePositionGeometry(void) { /* 0-----2 | /| | / | |/ | 1-----3 */ Real left, right, top, bottom; /* Convert positions into -1, 1 coordinate space (homogenous clip space). - Left / right is simple range conversion - Top / bottom also need inverting since y is upside down - this means that top will end up greater than bottom and when computing texture coordinates, we have to flip the v-axis (ie. subtract the value from 1.0 to get the actual correct value). */ left = _getDerivedLeft() * 2 - 1; right = left + (mWidth * 2); top = -((_getDerivedTop() * 2) - 1); bottom = top - (mHeight * 2); HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); float* pPos = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); // Use the furthest away depth value, since materials should have depth-check off // This initialised the depth buffer for any 3D objects in front Real zValue = Root::getSingleton().getRenderSystem()->getMaximumDepthInputValue(); *pPos++ = left; *pPos++ = top; *pPos++ = zValue; *pPos++ = left; *pPos++ = bottom; *pPos++ = zValue; *pPos++ = right; *pPos++ = top; *pPos++ = zValue; *pPos++ = right; *pPos++ = bottom; *pPos++ = zValue; vbuf->unlock(); }
/// internal method for setting up geometry, called by OverlayElement::update void cColourClipTextOverlay::updatePositionGeometry(void) { if (mpFont.isNull()) return; UpdateVars(); // big vars static for efficiency static VertexRect clipped; static Ogre::Rectangle clippingRegion; // calc clipping if (mbClipInitialized) { clippingRegion = mClip; // calc clip region in screen-relative coords if (mMetricsMode != GMM_RELATIVE) { clippingRegion.left *= mPixelScaleX; clippingRegion.right *= mPixelScaleX; clippingRegion.top *= mPixelScaleY; clippingRegion.bottom *= mPixelScaleY; } } // set up variables used in loop clipped.lt.col = clipped.rt.col = mColourTop; clipped.lb.col = clipped.rb.col = mColourBottom; float left = _getDerivedLeft(); float top = _getDerivedTop(); cOgreFontHelper myFontHelper(mpFont,mCharHeight * mViewportAspectCoef,mCharHeight,mSpaceWidth,mWrapMaxW,cOgreFontHelper::Alignment(mAlignment)); cOgreFontHelper::cTextIterator itor(myFontHelper,mCaption); Real z = -1.0; // iterate over all chars in caption Begin(mCaption.size() * 6,0,false,false,Ogre::RenderOperation::OT_TRIANGLE_LIST); while (itor.HasNext()) { cOgreFontHelper::unicode_char c = itor.Next(); if (cOgreFontHelper::IsWhiteSpace(c)) { // whitespace character, skip triangles cRobRenderOp::SkipVertices(6); } else { // draw character clipped.SetLTWH(left+itor.x,top+itor.y,myFontHelper.GetCharWidth(c),mCharHeight); // TODO : if (mbClipInitialized && invis by clip) { cRobRenderOp::SkipVertices(6); continue; } Ogre::Font::UVRect uvRect = mpFont->getGlyphTexCoords( c ); clipped.SetUV(uvRect.left,uvRect.top,uvRect.right,uvRect.bottom); if (mbClipInitialized) clipped = clipped.Intersect(clippingRegion); clipped.DrawList(this,z); } } End(); }
/// input pos in absolute pixel coordinates /// (e.g. clicking to place the caret) /// returns the INDEX of the char in the string, not the charcode /// returns -1 if nothing was hit /// TODO : TEST ME ! int cColourClipTextOverlay::GetGlyphAtPos (const size_t x,const size_t y) { _update(); // get the variables right UpdateVars(); if (mpFont.isNull()) return -1; // set up variables used in loop float left = _getDerivedLeft(); float top = _getDerivedTop(); float vw = float(cOgreWrapper::GetSingleton().GetViewportWidth()); float vh = float(cOgreWrapper::GetSingleton().GetViewportHeight()); if (vw == 0) vw = 1; // avoid division by zero if (vh == 0) vh = 1; // avoid division by zero cOgreFontHelper myFontHelper(mpFont,mCharHeight * mViewportAspectCoef,mCharHeight,mSpaceWidth,mWrapMaxW,cOgreFontHelper::Alignment(mAlignment)); return myFontHelper.GetGlyphAtPos(mCaption,x/vw-left,y/vh-top); }
/// internal method for setting up geometry, called by OverlayElement::update void cCompassOverlay::updatePositionGeometry(void) { /* // init clip to fullscreen if (!mbClipInitialized) { mbClipInitialized = true; mClip.left = 0; mClip.top = 0; if (mMetricsMode != GMM_RELATIVE) { mClip.right = mClip.left+cOgreWrapper::GetSingleton().GetViewportWidth(); mClip.bottom = mClip.top+cOgreWrapper::GetSingleton().GetViewportHeight(); } else { mClip.right = mClip.left+1.0; mClip.bottom = mClip.top+1.0; } } */ //mForm.SetLTWH(_getDerivedLeft(),_getDerivedTop(),mWidth,mHeight); // clear z buffer under overlay Real maxz = GetMaxZ(); // construct geometry int iSteps = 21; Begin(2+iSteps,3*iSteps,true,false,Ogre::RenderOperation::OT_TRIANGLE_LIST); float radx = (mWidth / 2.0) * 2.0; float rady = (mHeight / 2.0) * 2.0; float midx = (_getDerivedLeft()) * 2.0 - 1.0 + radx; float midy = - (_getDerivedTop() * 2.0 - 1.0 + rady); float ang; float partang = 2.0 * 3.1415 / float(iSteps); Vertex(Vector3(midx,midy,maxz),mfMidU,mfMidV); for (int i=0;i<=iSteps;++i) { ang = float((i==iSteps)?0:i) * partang; Vertex(Vector3(midx-radx*sin(ang),midy+rady*cos(ang),maxz),mfMidU+mfRadU*sin(ang+mfAngBias),mfMidV+mfRadV*cos(ang+mfAngBias)); if (i>0) { Index(0); Index(i+1); Index(i); } } //clipped.DrawStrip(this,maxz); End(); //pRobRenderOp->Vertex(Vector3(x * 2.0 - 1.0,-(y * 2.0 - 1.0),z),u,v,col); }
/// returns result in pixels /// TODO : TEST ME ! void cColourClipTextOverlay::GetGlyphBounds (const size_t iIndex,Ogre::Real& l,Ogre::Real& t,Ogre::Real& r,Ogre::Real& b) { _update(); // get the variables right UpdateVars(); l=t=r=b=0; if (mpFont.isNull()) return; // set up variables used in loop cOgreFontHelper myFontHelper(mpFont,mCharHeight * mViewportAspectCoef,mCharHeight,mSpaceWidth,mWrapMaxW,cOgreFontHelper::Alignment(mAlignment)); myFontHelper.GetGlyphBounds(mCaption,iIndex,l,t,r,b); float left = _getDerivedLeft(); float top = _getDerivedTop(); float vw = float(cOgreWrapper::GetSingleton().GetViewportWidth()); float vh = float(cOgreWrapper::GetSingleton().GetViewportHeight()); l = (l + left)*vw; r = (r + left)*vw; t = (t + top)*vh; b = (b + top)*vh; }
void TextAreaOverlayElement::updatePositionGeometry() { float *pVert; if (mFont.isNull()) { // not initialised yet, probably due to the order of creation in a template return; } size_t charlen = mCaption.size(); checkMemoryAllocation( charlen ); mRenderOp.vertexData->vertexCount = charlen * 6; // Get position / texcoord buffer const HardwareVertexBufferSharedPtr& vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(POS_TEX_BINDING); pVert = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD, Root::getSingleton().getFreqUpdatedBuffersUploadOption()) ); float largestWidth = 0; float left = _getDerivedLeft() * 2.0f - 1.0f; float top = -( (_getDerivedTop() * 2.0f ) - 1.0f ); // Derive space with from a number 0 if(!mSpaceWidthOverridden) { mSpaceWidth = mFont->getGlyphAspectRatio(UNICODE_ZERO) * mCharHeight; } // Use iterator DisplayString::iterator i, iend; iend = mCaption.end(); bool newLine = true; for( i = mCaption.begin(); i != iend; ++i ) { if( newLine ) { Real len = 0.0f; for( DisplayString::iterator j = i; j != iend; j++ ) { Font::CodePoint character = OGRE_DEREF_DISPLAYSTRING_ITERATOR(j); if (character == UNICODE_CR || character == UNICODE_NEL || character == UNICODE_LF) { break; } else if (character == UNICODE_SPACE) // space { len += mSpaceWidth * 2.0f * mViewportAspectCoef; } else { len += mFont->getGlyphAspectRatio(character) * mCharHeight * 2.0f * mViewportAspectCoef; } } if( mAlignment == Right ) left -= len; else if( mAlignment == Center ) left -= len * 0.5f; newLine = false; } Font::CodePoint character = OGRE_DEREF_DISPLAYSTRING_ITERATOR(i); if (character == UNICODE_CR || character == UNICODE_NEL || character == UNICODE_LF) { left = _getDerivedLeft() * 2.0f - 1.0f; top -= mCharHeight * 2.0f; newLine = true; // Also reduce tri count mRenderOp.vertexData->vertexCount -= 6; // consume CR/LF in one if (character == UNICODE_CR) { DisplayString::iterator peeki = i; peeki++; if (peeki != iend && OGRE_DEREF_DISPLAYSTRING_ITERATOR(peeki) == UNICODE_LF) { i = peeki; // skip both as one newline // Also reduce tri count mRenderOp.vertexData->vertexCount -= 6; } } continue; } else if (character == UNICODE_SPACE) // space { // Just leave a gap, no tris left += mSpaceWidth * 2.0f * mViewportAspectCoef; // Also reduce tri count mRenderOp.vertexData->vertexCount -= 6; continue; } Real horiz_height = mFont->getGlyphAspectRatio(character) * mViewportAspectCoef ; const Font::UVRect& uvRect = mFont->getGlyphTexCoords(character); // each vert is (x, y, z, u, v) //------------------------------------------------------------------------------------- // First tri // // Upper left *pVert++ = left; *pVert++ = top; *pVert++ = -1.0; *pVert++ = uvRect.left; *pVert++ = uvRect.top; top -= mCharHeight * 2.0f; // Bottom left *pVert++ = left; *pVert++ = top; *pVert++ = -1.0; *pVert++ = uvRect.left; *pVert++ = uvRect.bottom; top += mCharHeight * 2.0f; left += horiz_height * mCharHeight * 2.0f; // Top right *pVert++ = left; *pVert++ = top; *pVert++ = -1.0; *pVert++ = uvRect.right; *pVert++ = uvRect.top; //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- // Second tri // // Top right (again) *pVert++ = left; *pVert++ = top; *pVert++ = -1.0; *pVert++ = uvRect.right; *pVert++ = uvRect.top; top -= mCharHeight * 2.0f; left -= horiz_height * mCharHeight * 2.0f; // Bottom left (again) *pVert++ = left; *pVert++ = top; *pVert++ = -1.0; *pVert++ = uvRect.left; *pVert++ = uvRect.bottom; left += horiz_height * mCharHeight * 2.0f; // Bottom right *pVert++ = left; *pVert++ = top; *pVert++ = -1.0; *pVert++ = uvRect.right; *pVert++ = uvRect.bottom; //------------------------------------------------------------------------------------- // Go back up with top top += mCharHeight * 2.0f; float currentWidth = (left + 1)/2 - _getDerivedLeft(); if (currentWidth > largestWidth) { largestWidth = currentWidth; } } // Unlock vertex buffer vbuf->unlock(); if (mMetricsMode == GMM_PIXELS) { // Derive parametric version of dimensions Real vpWidth; vpWidth = (Real) (OverlayManager::getSingleton().getViewportWidth()); largestWidth *= vpWidth; }; if (getWidth() < largestWidth) setWidth(largestWidth); }
void LIRenImageOverlay::updatePositionGeometry () { // Prevent divide by zero. if (!mPixelWidth || !mPixelHeight) { render_op.vertexData->vertexCount = 0; return; } // Calculate offset and dimensions. float left = _getDerivedLeft() * 2.0f - 1.0f; float top = 1.0f - _getDerivedTop() * 2.0f; float xscale = 2.0f * mWidth / mPixelWidth; float yscale = 2.0f * mHeight / mPixelHeight; float xtile = xscale * src_tiling[1]; float ytile = yscale * src_tiling[4]; // Ogre seems to divide by zero during startup when the viewport // hasn't been initialized. Refuse to do anything if that happened. if (!limat_number_is_finite (left) || !limat_number_is_finite (top)) { render_op.vertexData->vertexCount = 0; return; } // Calculate vertex coordinates. float x[4] = { left, left + xscale * src_tiling[0], left + xscale * (mPixelWidth - src_tiling[2]), left + xscale * mPixelWidth }; float y[4] = { top, top - yscale * src_tiling[3], top - yscale * (mPixelHeight - src_tiling[5]), top - yscale * mPixelHeight }; /* Calculate texture coordinates. */ float uscale = 1.0f / src_size[0]; float vscale = 1.0f / src_size[1]; float u[4] = { uscale * (src_pos[0]), uscale * (src_pos[0] + src_tiling[0]), uscale * (src_pos[0] + src_tiling[0] + src_tiling[1]), uscale * (src_pos[0] + src_tiling[0] + src_tiling[1] + src_tiling[2]) }; float v[4] = { vscale * (src_pos[1]), vscale * (src_pos[1] + src_tiling[3]), vscale * (src_pos[1] + src_tiling[3] + src_tiling[4]), vscale * (src_pos[1] + src_tiling[3] + src_tiling[4] + src_tiling[5]) }; /* Setup vertex packing. */ float z = Ogre::Root::getSingleton().getRenderSystem()->getMaximumDepthInputValue (); LIRenTilePacker packer (z); float color_[4] = { color[0], color[1], color[2], color[3] * alpha }; packer.set_color (color_); if (rotation_angle != 0.0f) { float cx = left + xscale * rotation_center[0]; float cy = top - yscale * rotation_center[1]; packer.set_rotation (rotation_angle, cx, cy, xscale / yscale); } float clip[4]; if (clipping) { clip[0] = left + xscale * dst_clip[0]; clip[1] = top - yscale * (dst_clip[1] + dst_clip[3]); clip[2] = xscale * dst_clip[2]; clip[3] = yscale * dst_clip[3]; packer.set_clipping (clip); } /* Add corners. */ packer.add_quad (x[0], y[0], u[0], v[0], x[1], y[1], u[1], v[1]); packer.add_quad (x[2], y[0], u[2], v[0], x[3], y[1], u[3], v[1]); packer.add_quad (x[2], y[2], u[2], v[2], x[3], y[3], u[3], v[3]); packer.add_quad (x[0], y[2], u[0], v[2], x[1], y[3], u[1], v[3]); /* Add top and bottom borders. */ for (float i = x[1] ; i < x[2] ; i += xtile) { float wtile = LIMAT_MIN (x[2] - i, xtile); float xe = i + wtile; float ue = u[1] + (u[2] - u[1]) * (wtile / xtile); packer.add_quad (i, y[0], u[1], v[0], xe, y[1], ue, v[1]); packer.add_quad (i, y[2], u[1], v[2], xe, y[3], ue, v[3]); } /* Add left and right borders. */ for (float j = y[1] ; j > y[2] ; j -= ytile) { float htile = LIMAT_MIN (j - y[2], ytile); float ye = j - htile; float ve = v[1] + (v[2] - v[1]) * (htile / ytile); packer.add_quad (x[0], j, u[0], v[1], x[1], ye, u[1], ve); packer.add_quad (x[2], j, u[2], v[1], x[3], ye, u[3], ve); } /* Add the filling. */ for (float i = x[1] ; i < x[2] ; i += xtile) { float wtile = LIMAT_MIN (x[2] - i, xtile); float xe = i + wtile; float ue = u[1] + (u[2] - u[1]) * (wtile / xtile); for (float j = y[1] ; j > y[2] ; j -= ytile) { float htile = LIMAT_MIN (j - y[2], ytile); float ye = j - htile; float ve = v[1] + (v[2] - v[1]) * (htile / ytile); packer.add_quad (i, j, u[1], v[1], xe, ye, ue, ve); } } /* Update vertex buffer. */ lisys_assert (packer.pos <= 6 * VERTEX_COUNT_MAX); if (vbuf->getNumVertices () < (size_t)(packer.pos / 6)) { vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer ( VERTEX_SIZE, packer.pos / 6, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); render_op.vertexData->vertexBufferBinding->setBinding (0, vbuf); } vbuf->writeData (0, vbuf->getSizeInBytes (), packer.verts); /* Bind the vertex buffer. */ render_op.useIndexes = false; render_op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; render_op.vertexData->vertexCount = packer.pos / 6; }
//--------------------------------------------------------------------- void BorderPanelOverlayElement::updatePositionGeometry(void) { /* Grid is like this: +--+---------------+--+ |0 | 1 |2 | +--+---------------+--+ | | | | | | | | |3 | center |4 | | | | | +--+---------------+--+ |5 | 6 |7 | +--+---------------+--+ */ // Convert positions into -1, 1 coordinate space (homogenous clip space) // Top / bottom also need inverting since y is upside down Real left[8], right[8], top[8], bottom[8]; // Horizontal left[0] = left[3] = left[5] = _getDerivedLeft() * 2 - 1; left[1] = left[6] = right[0] = right[3] = right[5] = left[0] + (mLeftBorderSize * 2); right[2] = right[4] = right[7] = left[0] + (mWidth * 2); left[2] = left[4] = left[7] = right[1] = right[6] = right[2] - (mRightBorderSize * 2); // Vertical top[0] = top[1] = top[2] = -((_getDerivedTop() * 2) - 1); top[3] = top[4] = bottom[0] = bottom[1] = bottom[2] = top[0] - (mTopBorderSize * 2); bottom[5] = bottom[6] = bottom[7] = top[0] - (mHeight * 2); top[5] = top[6] = top[7] = bottom[3] = bottom[4] = bottom[5] + (mBottomBorderSize * 2); // Lock the whole position buffer in discard mode HardwareVertexBufferSharedPtr vbuf = mRenderOp2.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); float* pPos = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); // Use the furthest away depth value, since materials should have depth-check off // This initialised the depth buffer for any 3D objects in front Real zValue = Root::getSingleton().getRenderSystem()->getMaximumDepthInputValue(); for (ushort cell = 0; cell < 8; ++cell) { /* 0-----2 | /| | / | |/ | 1-----3 */ *pPos++ = left[cell]; *pPos++ = top[cell]; *pPos++ = zValue; *pPos++ = left[cell]; *pPos++ = bottom[cell]; *pPos++ = zValue; *pPos++ = right[cell]; *pPos++ = top[cell]; *pPos++ = zValue; *pPos++ = right[cell]; *pPos++ = bottom[cell]; *pPos++ = zValue; } vbuf->unlock(); // Also update center geometry // NB don't use superclass because we need to make it smaller because of border vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); pPos = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); // Use cell 1 and 3 to determine positions *pPos++ = left[1]; *pPos++ = top[3]; *pPos++ = zValue; *pPos++ = left[1]; *pPos++ = bottom[3]; *pPos++ = zValue; *pPos++ = right[1]; *pPos++ = top[3]; *pPos++ = zValue; *pPos++ = right[1]; *pPos++ = bottom[3]; *pPos++ = zValue; vbuf->unlock(); }