void PanoramicVideo::drawLocalClient(){ if(mVideoSprite){ ci::gl::TextureRef videoTexture = mVideoSprite->getFinalOutTexture(); if(!videoTexture) return; ci::Area newViewportBounds; DS_REPORT_GL_ERRORS(); if(!getPerspective()){ ci::Rectf bb = getBoundingBox(); ci::vec3 ul = getParent()->localToGlobal(ci::vec3(bb.getUpperLeft(), 0.0f)); ci::vec3 br = getParent()->localToGlobal(ci::vec3(bb.getLowerRight(), 0.0f)); float yScale = mEngine.getSrcRect().getHeight() / mEngine.getDstRect().getHeight(); float xScale = mEngine.getSrcRect().getWidth() / mEngine.getDstRect().getWidth(); // even though we're not in perspective, the cinder perspective camera starts from the bottom of the window // and counts upwards for y. So reverse that to draw where we expect ul = ul - ci::vec3(mEngine.getSrcRect().getUpperLeft(), 0.0f); ul.y /= yScale; ul.x /= xScale; ul.y = ci::app::getWindowBounds().getHeight() - ul.y; br = br - ci::vec3(mEngine.getSrcRect().getUpperLeft(), 0.0f); br.y /= yScale; br.x /= xScale; br.y = ci::app::getWindowBounds().getHeight() - br.y; newViewportBounds = ci::Area(ci::vec2(ul), ci::vec2(br)); } else { ci::vec3 ul = getParent()->localToGlobal(getPosition() - getCenter()*getSize()); ul = ul - ci::vec3(mEngine.getSrcRect().getUpperLeft(), 0.0f); ci::vec3 br = ul + ci::vec3(getWidth(), getHeight(), 0.0f); newViewportBounds = ci::Area(ci::vec2(ul.x, br.y), ci::vec2(br.x, ul.y)); } // might have to figure this out for client/server //ci::gl::ScopedViewport newViewport(newViewportBounds); videoTexture->bind(); ci::gl::ScopedMatrices matricies; ci::gl::setMatrices(mCamera); ci::gl::rotate(ci::toRadians(mXRot), 0.0f, 0.0f, 1.0f); ci::gl::rotate(ci::toRadians(mYRot), 0.0f, 1.0f, 0.0); ci::gl::draw(mSphereVbo); videoTexture->unbind(); } }
void ClipPlaneState::enableClipping(ds::ui::Sprite &s) { const ci::Rectf& cb = s.getClippingBounds(); const float x0 = cb.getX1(), y0 = cb.getY1(), x1 = cb.getX2(), y1 = cb.getY2(); glPushAttrib( GL_TRANSFORM_BIT | GL_ENABLE_BIT ); ci::Vec3f clippingPoints[4]; clippingPoints[0].set( x0, y0, 0 ); clippingPoints[1].set( x0, y1, 0 ); clippingPoints[2].set( x1, y1, 0 ); clippingPoints[3].set( x1, y0, 0 ); for (int i = 0; i < CLIP_PLANE_COUNT; ++i) { int j = (i+1) % 4, k = (i+2) % 4; // Going clockwise around clipping points... ci::Vec3f edgeA = clippingPoints[i] - clippingPoints[j], edgeB = clippingPoints[j] - clippingPoints[k]; // The edge-normal is found by first finding a vector perpendicular // to two consecutive edges. Next, we cross that with the forward- // facing (clockwise) edge vector to get an inward-facing edge- // normal vector for that edge ci::Vec3f norm = -(edgeA.cross( edgeB )).cross(edgeA).normalized(); // the four points we pass to glClipPlane are the solutions of the // equation Ax + By + Cz + D = 0. A, B, and C are the normal, and // we solve for D. C is always zero for the 2D case however, in the // 3D case, we must use a three-component normal vector. float d = -norm.dot(clippingPoints[i]); DS_REPORT_GL_ERRORS(); glEnable( GL_CLIP_PLANE0 + i ); DS_REPORT_GL_ERRORS(); GLdouble equation[4] = { norm.x, norm.y, norm.z, d }; glClipPlane( GL_CLIP_PLANE0 + i, equation ); DS_REPORT_GL_ERRORS(); } }
void ClipPlaneState::pop() { if (mEnabled.empty()) { DS_ASSERT_MSG(false, "ClipPlaneState unbalanced pop()"); return; } const bool is_enabled = (mEnabled.back() == true); if (is_enabled) { DS_REPORT_GL_ERRORS(); glPopAttrib(); DS_REPORT_GL_ERRORS(); } mEnabled.pop_back(); if (is_enabled && getDepth() < 1) { DS_REPORT_GL_ERRORS(); for (int i = 0; i < CLIP_PLANE_COUNT; ++i) { glDisable(GL_CLIP_PLANE0 + i); } DS_REPORT_GL_ERRORS(); } }
void LoadImageService::_load() { // Pop off the items I need mTmp.clear(); { Poco::Mutex::ScopedLock l(mMutex); mInput.swap(mTmp); } // Load them all DS_REPORT_GL_ERRORS(); for (int k=0; k<mTmp.size(); k++) { op& top = mTmp[k]; try { // DS_LOG_INFO_M("LoadImageService::_load() on file (" << top.mFilename << ")", LOAD_IMAGE_LOG_M); // If there's a function, then require this image have an alpha channel, because // who knows what the function will need. Otherwise let cinder do its thing. boost::tribool alpha = boost::logic::indeterminate; if (!top.mIpFunction.empty()) alpha = boost::tribool(true); const std::string fn = ds::Environment::expand(top.mKey.mFilename); const Poco::File file(fn); if (file.exists()) { top.mSurface = ci::Surface8u(ci::loadImage(fn), ci::SurfaceConstraintsDefault(), alpha); DS_REPORT_GL_ERRORS(); if (top.mSurface) { top.mIpFunction.on(top.mKey.mIpParams, top.mSurface); // This is to immediately place operations on the output... Poco::Mutex::ScopedLock l(mMutex); mOutput.push_back(op(top)); } } else { DS_LOG_WARNING_M("LoadImageService::_load() failed. File does not exist: " << top.mKey.mFilename, LOAD_IMAGE_LOG_M); } } catch (std::exception const& ex) { DS_LOG_WARNING_M("LoadImageService::_load() failed ex=" << ex.what() << " (file=" << top.mKey.mFilename << ")", LOAD_IMAGE_LOG_M); } top.clear(); DS_REPORT_GL_ERRORS(); } mTmp.clear(); }
void LoadImageService::update() { Poco::Mutex::ScopedLock l(mMutex); for (int k=0; k<mOutput.size(); k++) { op& out = mOutput[k]; holder& h = mImageResource[out.mKey]; if(h.mTexture) { DS_LOG_WARNING_M("Duplicate images for id=" << out.mKey.mFilename << " refs=" << h.mRefs, LOAD_IMAGE_LOG_M); } else { ci::gl::Texture::Format fmt; if ((h.mFlags&ds::ui::Image::IMG_ENABLE_MIPMAP_F) != 0) { fmt.enableMipmapping(true); fmt.setMinFilter(GL_LINEAR_MIPMAP_LINEAR); } h.mTexture = ci::gl::Texture(out.mSurface, fmt); if (glGetError() == GL_OUT_OF_MEMORY) { DS_LOG_ERROR_M("LoadImageService::update() called on filename: " << out.mKey.mFilename << " received an out of memory error. Image may be too big.", LOAD_IMAGE_LOG_M); } DS_REPORT_GL_ERRORS(); } out.clear(); } mOutput.clear(); }