void CMatCanvas::Create(CWnd* parent,CRect pos,UINT in_winId) { const char* cName = AfxRegisterWndClass(CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT, ::LoadCursor(NULL,IDC_ARROW)); Base::Create(cName, "Canvas" ,WS_VISIBLE, pos, parent, in_winId,NULL); // DMMSOLID added point Point2I temp(0,0); GFXCDSSurface::create(m_pSurface, TRUE, pos.Width(), pos.Height(), GetSafeHwnd(), &temp); RectI screenView(Point2I(0,0),Point2I(pos.Width()-1, pos.Height()-1)); // double max_dim = (pos.Width() > pos.Height()) ? (double)pos.Width() : (double)pos.Height(); // RectF worldView(Point2F(-pos.Width()/max_dim, pos.Height()/max_dim), // Point2F(pos.Width()/max_dim, -pos.Height()/max_dim)); RectF worldView(Point2F(0, 0), Point2F(pos.Width(), pos.Height())); m_pTSCamera = new TSPerspectiveCamera(screenView, worldView, 1.F, 1.0E4f); m_renderContext->setSurface(m_pSurface); m_renderContext->setPointArray(&DefaultPointArray); m_renderContext->setCamera(m_pTSCamera); m_renderContext->setLights(m_GSceneLights); m_renderContext->getSurface()->setHazeSource(GFX_HAZE_NONE); // m_renderContext->getSurface()->setShadeSource(GFX_SHADE_NONE); m_renderContext->getSurface()->setAlphaSource(GFX_ALPHA_NONE); m_renderContext->getSurface()->setTransparency(FALSE); }
bool ShapeView::onAdd() { RectF rect; float width, height; if (Parent::onAdd()) { active = true; camera = new TSPerspectiveCamera( RectI(Point2I(0, 0), Point2I(0, 0)), RectF(Point2F(0.0f, 0.0f), Point2F(0.0f, 0.0f)), 256.0f, 1.0E8f); scene = new TSSceneLighting; scene->setAmbientIntensity(ColorF(0.7f, 0.7f, 0.7f)); light = new TSLight; light->setType(TS::Light::LightDirectional); light->setIntensity(1.0f, 1.0f, 1.0f); scene->installLight(light); return (true); } return (false); }
void Sphere::generate() { S32 segments2 = segments / 2; S32 slices2 = slices / 2; Vertex *points = new Vertex[segments * slices * 2]; U32 point = 0; for (S32 y = -slices2; y < slices2; y ++) { float cosy = cos(y * step); float cosy1 = cos((y + 1) * step); float siny = sin(y * step); float siny1 = sin((y + 1) * step); for (S32 i = -segments2; i < segments2; i ++) { float cosi = cos(i * step); float sini = sin(i * step); //Math not invented by me Point3F point0 = Point3F(radius * cosi * cosy, radius * siny, radius * sini * cosy); Point3F point1 = Point3F(radius * cosi * cosy1, radius * siny1, radius * sini * cosy1); Point4F color0 = Point4F(fabs(point0.x), fabs(point0.y), fabs(point0.z), radius).normalize(); Point4F color1 = Point4F(fabs(point1.x), fabs(point1.y), fabs(point1.z), radius).normalize(); color0 /= color0.z; color1 /= color1.z; Point2F uv0 = Point2F((F32)i / (F32)segments2, (F32)y / (F32)slices2); Point2F uv1 = Point2F((F32)i / (F32)segments2, (F32)(y + 1) / (F32)slices2); Point3F tangent0 = point0.cross(Point3F(0, 0, 1)).normalize(); Point3F tangent1 = point1.cross(Point3F(0, 0, 1)).normalize(); Point3F bitangent0 = point0.cross(tangent0).normalize(); Point3F bitangent1 = point0.cross(tangent0).normalize(); points[point].point = point0; points[point].uv = uv0; points[point].normal = point0; points[point].tangent = tangent0; points[point].bitangent = bitangent0; point ++; points[point].point = point1; points[point].uv = uv1; points[point].normal = point1; points[point].tangent = tangent1; points[point].bitangent = bitangent1; point ++; } } //Generate a buffer glGenBuffers(1, &renderBuffer); glBindBuffer(GL_ARRAY_BUFFER, renderBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * point, points, GL_STATIC_DRAW); delete [] points; }
Point2F BiQuadToSqr::transform( const Point2F &p ) const { Point2F kA = m_kP00 - p; F32 fAB = mDotPerp( kA, m_kB ); F32 fAC = mDotPerp( kA, m_kC); // 0 = ac*bc+(bc^2+ac*bd-ab*cd)*s+bc*bd*s^2 = k0 + k1*s + k2*s^2 F32 fK0 = fAC*m_fBC; F32 fK1 = m_fBC*m_fBC + fAC*m_fBD - fAB*m_fCD; F32 fK2 = m_fBC*m_fBD; if (mFabs(fK2) > POINT_EPSILON) { // s-equation is quadratic F32 fInv = 0.5f/fK2; F32 fDiscr = fK1*fK1 - 4.0f*fK0*fK2; F32 fRoot = mSqrt( mFabs(fDiscr) ); Point2F kResult0( 0, 0 ); kResult0.x = (-fK1 - fRoot)*fInv; kResult0.y = fAB/(m_fBC + m_fBD*kResult0.x); F32 fDeviation0 = deviation(kResult0); if ( fDeviation0 == 0.0f ) return kResult0; Point2F kResult1( 0, 0 ); kResult1.x = (-fK1 + fRoot)*fInv; kResult1.y = fAB/(m_fBC + m_fBD*kResult1.x); F32 fDeviation1 = deviation(kResult1); if ( fDeviation1 == 0.0f ) return kResult1; if (fDeviation0 <= fDeviation1) { if ( fDeviation0 < POINT_EPSILON ) return kResult0; } else { if ( fDeviation1 < POINT_EPSILON ) return kResult1; } } else { // s-equation is linear Point2F kResult( 0, 0 ); kResult.x = -fK0/fK1; kResult.y = fAB/(m_fBC + m_fBD*kResult.x); F32 fDeviation = deviation(kResult); if ( fDeviation < POINT_EPSILON ) return kResult; } // point is outside the quadrilateral, return invalid return Point2F(F32_MAX,F32_MAX); }
void Scene::loop() { //Basic movement glm::mat4x4 delta = glm::mat4x4(1); if (movement[4]) pitch -= keyCameraSpeed; if (movement[5]) pitch += keyCameraSpeed; if (movement[6]) yaw -= keyCameraSpeed; if (movement[7]) yaw += keyCameraSpeed; delta = glm::rotate(delta, -yaw, glm::vec3(0, 0, 1)); float speed = movementSpeed; if (mouseButtons[1]) speed *= 2.f; Point2F move = Point2F(); if (movement[0]) move.x -= speed; if (movement[1]) move.x += speed; if (movement[2]) move.y -= speed; if (movement[3]) move.y += speed; #ifdef BUILD_PHYSICS glm::vec3 torque = glm::vec3(glm::translate(delta, glm::vec3(move.x, move.y, 0))[3]); delta = glm::rotate(delta, -pitch, glm::vec3(1, 0, 0)); sphere->applyTorque(Point3F(torque.x, torque.y, torque.z) * 20); if (sphere->getColliding()) { Point3F normal = sphere->getCollisionNormal(); if (movement[8] && normal.dot(Point3F(0, 0, 1)) > 0.1) sphere->applyImpulse((normal + Point3F(0, 0, 1)) / 2.f, Point3F(0, 0, -1)); } else { sphere->applyImpulse(Point3F(torque.y, -torque.x, torque.z) / 4.f, Point3F(0, 0, 0)); } Point3F pos = sphere->getPosition(); cameraPosition = glm::vec3(pos.x, pos.y, pos.z); cameraPosition += glm::vec3(glm::translate(delta, glm::vec3(0, -2.5, 0))[3]); if (sphere->getPosition().z < difs[0]->interior[0]->boundingBox.getMin().x) { sphere->setPosition(Point3F(0, 30, 60)); } #else /* BUILD_PHYSICS */ move *= 3; if (movement[8]) move *= 2; delta = glm::rotate(delta, -pitch, glm::vec3(1, 0, 0)); delta = glm::translate(delta, glm::vec3(move.y, -move.x, 0)); cameraPosition += glm::vec3(delta[3]); #endif /* BUILD_PHYSICS */ }
Point2F ITR3DMImport::power2Size(const Point2F& ts) { // Find smallest 2^n size that bounds givin size. static int table[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256 }; int x = 0, y = 0; for (; x < sizeof(table) * sizeof(*table); x++) if (ts.x <= table[x]) break; for (; y < sizeof(table) * sizeof(*table); y++) if (ts.y <= table[y]) break; return Point2F(table[x],table[y]); };
bool BaseFeatureLayer::Initialize() { RETURN_FALSE_IF_FALSE(ILayer::Initialize()); TextureButton* returnButton = NodeFactory::Instance().CreateTextureButton("Close.png", "CloseSelected.png"); returnButton->OnTap += Bind(&BaseFeatureLayer::OnReturn,this); returnButton->SetDock(DockPoint::LeftTop); returnButton->SetAnchor(0.f, 1.f); AddChild(returnButton); TextureButton* refreshButton = NodeFactory::Instance().CreateTextureButton("Refresh.png", "RefreshSelected.png"); refreshButton->OnTap += Bind(&BaseFeatureLayer::OnRefresh, this); refreshButton->SetDock(DockPoint::MiddleBottom); refreshButton->SetAnchor(0.5f, 0.f); AddChild(refreshButton); float xPadding = refreshButton->Size().Width*0.5f + 100.f; TextureButton* leftButton = NodeFactory::Instance().CreateTextureButton("Left.png", "LeftSelected.png"); leftButton->OnTap += Bind(&BaseFeatureLayer::OnLeft, this); leftButton->SetDock(DockPoint::MiddleBottom); leftButton->SetAnchor(0.5f, 0.f); leftButton->SetRelativePosition(Point2F(-xPadding, 0.f)); AddChild(leftButton); TextureButton* rightButton = NodeFactory::Instance().CreateTextureButton("Left.png", "LeftSelected.png"); rightButton->OnTap += Bind(&BaseFeatureLayer::OnRight, this); rightButton->SetDock(DockPoint::MiddleBottom); rightButton->SetAnchor(0.5f, 0.f); rightButton->SetRelativePosition(Point2F(xPadding, 0.f)); rightButton->SetFlipX(true); AddChild(rightButton); return true; }
// Used to build potential target list static void _scanCallback( SceneObject* object, void* data ) { AITurretShape* turret = (AITurretShape*)data; ShapeBase* shape = dynamic_cast<ShapeBase*>(object); if (shape && shape->getDamageState() == ShapeBase::Enabled) { Point3F targetPos = shape->getBoxCenter(); // Put target position into the scan node's space turret->mScanWorkspaceScanWorldMat.mulP(targetPos); // Is the target within scanning distance if (targetPos.lenSquared() > turret->getMaxScanDistanceSquared()) return; // Make sure the target is in front and within the maximum // heading range Point2F targetXY(targetPos.x, targetPos.y); targetXY.normalizeSafe(); F32 headingDot = mDot(Point2F(0, 1), targetXY); F32 heading = mAcos(headingDot); if (headingDot < 0 || heading > turret->getMaxScanHeading()) return; // Make sure the target is in front and within the maximum // pitch range Point2F targetZY(targetPos.z, targetPos.y); targetZY.normalizeSafe(); F32 pitchDot = mDot(Point2F(0, 1), targetZY); F32 pitch = mAcos(pitchDot); if (pitchDot < 0 || pitch > turret->getMaxScanPitch()) return; turret->addPotentialTarget(shape); } }
void SmoothSlopeAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type) { if(!sel->size()) return; if(selChanged) { // Perform simple 2d linear regression on x&z and y&z: // b = (Avg(xz) - Avg(x)Avg(z))/(Avg(x^2) - Avg(x)^2) Point2F prod(0.f, 0.f); // mean of product for covar Point2F avgSqr(0.f, 0.f); // mean sqr of x, y for var Point2F avgPos(0.f, 0.f); F32 avgHeight = 0.f; F32 z; Point2F pos; for(U32 k = 0; k < sel->size(); k++) { mTerrainEditor->getUndoSel()->add((*sel)[k]); pos = Point2F((*sel)[k].mGridPoint.gridPos.x, (*sel)[k].mGridPoint.gridPos.y); z = (*sel)[k].mHeight; prod += pos * z; avgSqr += pos * pos; avgPos += pos; avgHeight += z; } prod /= sel->size(); avgSqr /= sel->size(); avgPos /= sel->size(); avgHeight /= sel->size(); Point2F avgSlope = (prod - avgPos*avgHeight)/(avgSqr - avgPos*avgPos); F32 goalHeight; for(U32 i = 0; i < sel->size(); i++) { goalHeight = avgHeight + ((*sel)[i].mGridPoint.gridPos.x - avgPos.x)*avgSlope.x + ((*sel)[i].mGridPoint.gridPos.y - avgPos.y)*avgSlope.y; (*sel)[i].mHeight += (goalHeight - (*sel)[i].mHeight) * (*sel)[i].mWeight; mTerrainEditor->setGridInfo((*sel)[i]); } mTerrainEditor->scheduleGridUpdate(); } }
void waterFind( SceneObject *obj, void *key ) { PROFILE_SCOPE( waterFind ); // This is called for each WaterObject the ShapeBase object is overlapping. ContainerQueryInfo *info = static_cast<ContainerQueryInfo*>(key); WaterObject *water = dynamic_cast<WaterObject*>(obj); AssertFatal( water != NULL, "containerQuery - waterFind(), passed object was not of class WaterObject!"); // Get point at the bottom/center of the box. Point3F testPnt = info->box.getCenter(); testPnt.z = info->box.minExtents.z; F32 coverage = water->getWaterCoverage(info->box); // Since a WaterObject can have global bounds we may get this call // even though we have zero coverage. If so we want to early out and // not save the water properties. if ( coverage == 0.0f ) return; // Add in flow force. Would be appropriate to try scaling it by coverage // thought. Or perhaps have getFlow do that internally and take // the box parameter. info->appliedForce += water->getFlow( testPnt ); // Only save the following properties for the WaterObject with the // greatest water coverage for this ShapeBase object. if ( coverage < info->waterCoverage ) return; info->waterCoverage = coverage; info->liquidType = water->getLiquidType(); info->waterViscosity = water->getViscosity(); info->waterDensity = water->getDensity(); info->waterHeight = water->getSurfaceHeight( Point2F(testPnt.x,testPnt.y) ); info->waterObject = water; }
void SoftSelectAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type type) { TerrainBlock *terrBlock = mTerrainEditor->getActiveTerrain(); if ( !terrBlock ) return; // allow process of current selection Selection tmpSel; if(sel == mTerrainEditor->getCurrentSel()) { tmpSel = *sel; sel = &tmpSel; } if(type == Begin || type == Process) mFilter.set(1, &mTerrainEditor->mSoftSelectFilter); // if(selChanged) { F32 radius = mTerrainEditor->mSoftSelectRadius; if(radius == 0.f) return; S32 squareSize = terrBlock->getSquareSize(); U32 offset = U32(radius / F32(squareSize)) + 1; for(U32 i = 0; i < sel->size(); i++) { GridInfo & info = (*sel)[i]; info.mPrimarySelect = true; info.mWeight = mFilter.getValue(0); if(!mTerrainEditor->getCurrentSel()->add(info)) mTerrainEditor->getCurrentSel()->setInfo(info); Point2F infoPos((F32)info.mGridPoint.gridPos.x, (F32)info.mGridPoint.gridPos.y); // for(S32 x = info.mGridPoint.gridPos.x - offset; x < info.mGridPoint.gridPos.x + (offset << 1); x++) for(S32 y = info.mGridPoint.gridPos.y - offset; y < info.mGridPoint.gridPos.y + (offset << 1); y++) { // Point2F pos((F32)x, (F32)y); F32 dist = Point2F(pos - infoPos).len() * F32(squareSize); if(dist > radius) continue; F32 weight = mFilter.getValue(dist / radius); // GridInfo gInfo; GridPoint gridPoint = info.mGridPoint; gridPoint.gridPos.set(x, y); if(mTerrainEditor->getCurrentSel()->getInfo(Point2I(x, y), gInfo)) { if(gInfo.mPrimarySelect) continue; if(gInfo.mWeight < weight) { gInfo.mWeight = weight; mTerrainEditor->getCurrentSel()->setInfo(gInfo); } } else { Vector<GridInfo> gInfos; mTerrainEditor->getGridInfos(gridPoint, gInfos); for (U32 z = 0; z < gInfos.size(); z++) { gInfos[z].mWeight = weight; gInfos[z].mPrimarySelect = false; mTerrainEditor->getCurrentSel()->add(gInfos[z]); } } } } } }
void TerrainBlock::_updateBaseTexture(bool writeToCache) { if ( !mBaseShader && !_initBaseShader() ) return; // This can sometimes occur outside a begin/end scene. const bool sceneBegun = GFX->canCurrentlyRender(); if ( !sceneBegun ) GFX->beginScene(); GFXDEBUGEVENT_SCOPE( TerrainBlock_UpdateBaseTexture, ColorI::GREEN ); PROFILE_SCOPE( TerrainBlock_UpdateBaseTexture ); GFXTransformSaver saver; const U32 maxTextureSize = GFX->getCardProfiler()->queryProfile( "maxTextureSize", 1024 ); U32 baseTexSize = getNextPow2( mBaseTexSize ); baseTexSize = getMin( maxTextureSize, baseTexSize ); Point2I destSize( baseTexSize, baseTexSize ); // Setup geometry GFXVertexBufferHandle<GFXVertexPT> vb; { F32 copyOffsetX = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.x; F32 copyOffsetY = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.y; GFXVertexPT points[4]; points[0].point = Point3F(1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0); points[0].texCoord = Point2F(1.0, 1.0f); points[1].point = Point3F(1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0); points[1].texCoord = Point2F(1.0, 0.0f); points[2].point = Point3F(-1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0); points[2].texCoord = Point2F(0.0, 1.0f); points[3].point = Point3F(-1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0); points[3].texCoord = Point2F(0.0, 0.0f); vb.set( GFX, 4, GFXBufferTypeVolatile ); GFXVertexPT *ptr = vb.lock(); if(ptr) { dMemcpy( ptr, points, sizeof(GFXVertexPT) * 4 ); vb.unlock(); } } GFXTexHandle blendTex; // If the base texture is already a valid render target then // use it to render to else we create one. if ( mBaseTex.isValid() && mBaseTex->isRenderTarget() && mBaseTex->getFormat() == GFXFormatR8G8B8A8 && mBaseTex->getWidth() == destSize.x && mBaseTex->getHeight() == destSize.y ) blendTex = mBaseTex; else blendTex.set( destSize.x, destSize.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, "" ); GFX->pushActiveRenderTarget(); // Set our shader stuff GFX->setShader( mBaseShader ); GFX->setShaderConstBuffer( mBaseShaderConsts ); GFX->setStateBlock( mBaseShaderSB ); GFX->setVertexBuffer( vb ); mBaseTarget->attachTexture( GFXTextureTarget::Color0, blendTex ); GFX->setActiveRenderTarget( mBaseTarget ); GFX->clear( GFXClearTarget, ColorI(0,0,0,255), 1.0f, 0 ); GFX->setTexture( 0, mLayerTex ); mBaseShaderConsts->setSafe( mBaseLayerSizeConst, (F32)mLayerTex->getWidth() ); for ( U32 i=0; i < mBaseTextures.size(); i++ ) { GFXTextureObject *tex = mBaseTextures[i]; if ( !tex ) continue; GFX->setTexture( 1, tex ); F32 baseSize = mFile->mMaterials[i]->getDiffuseSize(); F32 scale = 1.0f; if ( !mIsZero( baseSize ) ) scale = getWorldBlockSize() / baseSize; // A mistake early in development means that texture // coords are not flipped correctly. To compensate // we flip the y scale here. mBaseShaderConsts->setSafe( mBaseTexScaleConst, Point2F( scale, -scale ) ); mBaseShaderConsts->setSafe( mBaseTexIdConst, (F32)i ); GFX->drawPrimitive( GFXTriangleStrip, 0, 2 ); } mBaseTarget->resolve(); GFX->setShader( NULL ); //GFX->setStateBlock( NULL ); // WHY NOT? GFX->setShaderConstBuffer( NULL ); GFX->setVertexBuffer( NULL ); GFX->popActiveRenderTarget(); // End it if we begun it... Yeehaw! if ( !sceneBegun ) GFX->endScene(); /// Do we cache this sucker? if (mBaseTexFormat == NONE || !writeToCache) { // We didn't cache the result, so set the base texture // to the render target we updated. This should be good // for realtime painting cases. mBaseTex = blendTex; } else if (mBaseTexFormat == DDS) { String cachePath = _getBaseTexCacheFileName(); FileStream fs; if ( fs.open( _getBaseTexCacheFileName(), Torque::FS::File::Write ) ) { // Read back the render target, dxt compress it, and write it to disk. GBitmap blendBmp( destSize.x, destSize.y, false, GFXFormatR8G8B8A8 ); blendTex.copyToBmp( &blendBmp ); /* // Test code for dumping uncompressed bitmap to disk. { FileStream fs; if ( fs.open( "./basetex.png", Torque::FS::File::Write ) ) { blendBmp.writeBitmap( "png", fs ); fs.close(); } } */ blendBmp.extrudeMipLevels(); DDSFile *blendDDS = DDSFile::createDDSFileFromGBitmap( &blendBmp ); DDSUtil::squishDDS( blendDDS, GFXFormatDXT1 ); // Write result to file stream blendDDS->write( fs ); delete blendDDS; } fs.close(); } else { FileStream stream; if (!stream.open(_getBaseTexCacheFileName(), Torque::FS::File::Write)) { mBaseTex = blendTex; return; } GBitmap bitmap(blendTex->getWidth(), blendTex->getHeight(), false, GFXFormatR8G8B8); blendTex->copyToBmp(&bitmap); bitmap.writeBitmap(formatToExtension(mBaseTexFormat), stream); } }
bool SceneCullingState::isOccludedByTerrain( SceneObject* object ) const { PROFILE_SCOPE( SceneCullingState_isOccludedByTerrain ); // Don't try to occlude globally bounded objects. if( object->isGlobalBounds() ) return false; const Vector< SceneObject* >& terrains = getSceneManager()->getContainer()->getTerrains(); const U32 numTerrains = terrains.size(); for( U32 terrainIdx = 0; terrainIdx < numTerrains; ++ terrainIdx ) { TerrainBlock* terrain = dynamic_cast< TerrainBlock* >( terrains[ terrainIdx ] ); if( !terrain ) continue; MatrixF terrWorldTransform = terrain->getWorldTransform(); Point3F localCamPos = getCameraState().getViewPosition(); terrWorldTransform.mulP(localCamPos); F32 height; terrain->getHeight( Point2F( localCamPos.x, localCamPos.y ), &height ); bool aboveTerrain = ( height <= localCamPos.z ); // Don't occlude if we're below the terrain. This prevents problems when // looking out from underground bases... if( !aboveTerrain ) continue; const Box3F& oBox = object->getObjBox(); F32 minSide = getMin(oBox.len_x(), oBox.len_y()); if (minSide > 85.0f) continue; const Box3F& rBox = object->getWorldBox(); Point3F ul(rBox.minExtents.x, rBox.minExtents.y, rBox.maxExtents.z); Point3F ur(rBox.minExtents.x, rBox.maxExtents.y, rBox.maxExtents.z); Point3F ll(rBox.maxExtents.x, rBox.minExtents.y, rBox.maxExtents.z); Point3F lr(rBox.maxExtents.x, rBox.maxExtents.y, rBox.maxExtents.z); terrWorldTransform.mulP(ul); terrWorldTransform.mulP(ur); terrWorldTransform.mulP(ll); terrWorldTransform.mulP(lr); Point3F xBaseL0_s = ul - localCamPos; Point3F xBaseL0_e = lr - localCamPos; Point3F xBaseL1_s = ur - localCamPos; Point3F xBaseL1_e = ll - localCamPos; static F32 checkPoints[3] = {0.75, 0.5, 0.25}; RayInfo rinfo; for( U32 i = 0; i < 3; i ++ ) { Point3F start = (xBaseL0_s * checkPoints[i]) + localCamPos; Point3F end = (xBaseL0_e * checkPoints[i]) + localCamPos; if (terrain->castRay(start, end, &rinfo)) continue; terrain->getHeight(Point2F(start.x, start.y), &height); if ((height <= start.z) == aboveTerrain) continue; start = (xBaseL1_s * checkPoints[i]) + localCamPos; end = (xBaseL1_e * checkPoints[i]) + localCamPos; if (terrain->castRay(start, end, &rinfo)) continue; Point3F test = (start + end) * 0.5; if (terrain->castRay(localCamPos, test, &rinfo) == false) continue; return true; } } return false; }
//----------------------------------------------------------------------------- // Draw Rectangle Fill //----------------------------------------------------------------------------- void GFXDrawUtil::drawRectFill( const RectF &rect, const ColorI &color ) { drawRectFill(rect.point, Point2F(rect.extent.x + rect.point.x - 1, rect.extent.y + rect.point.y - 1), color ); }
void EditTSCtrl::renderGrid() { if( !isOrthoDisplayType() ) return; GFXDEBUGEVENT_SCOPE( Editor_renderGrid, ColorI::WHITE ); // Calculate the displayed grid size based on view F32 drawnGridSize = mGridPlaneSize; F32 gridPixelSize = projectRadius(1.0f, mGridPlaneSize); if(gridPixelSize < mGridPlaneSizePixelBias) { U32 counter = 1; while(gridPixelSize < mGridPlaneSizePixelBias) { drawnGridSize = mGridPlaneSize * counter * 10.0f; gridPixelSize = projectRadius(1.0f, drawnGridSize); ++counter; // No infinite loops here if(counter > 1000) break; } } F32 minorTickSize = 0; F32 gridSize = drawnGridSize; U32 minorTickMax = mGridPlaneMinorTicks + 1; if(minorTickMax > 0) { minorTickSize = drawnGridSize; gridSize = drawnGridSize * minorTickMax; } // Build the view-based origin VectorF dir; smCamMatrix.getColumn( 1, &dir ); Point3F gridPlanePos = smCamPos + dir; Point2F size(mOrthoWidth + 2 * gridSize, mOrthoHeight + 2 * gridSize); GFXStateBlockDesc desc; desc.setBlend( true ); desc.setZReadWrite( true, false ); GFXDrawUtil::Plane plane = GFXDrawUtil::PlaneXY; switch( getDisplayType() ) { case DisplayTypeTop: case DisplayTypeBottom: plane = GFXDrawUtil::PlaneXY; break; case DisplayTypeLeft: case DisplayTypeRight: plane = GFXDrawUtil::PlaneYZ; break; case DisplayTypeFront: case DisplayTypeBack: plane = GFXDrawUtil::PlaneXZ; break; default: break; } GFX->getDrawUtil()->drawPlaneGrid( desc, gridPlanePos, size, Point2F( minorTickSize, minorTickSize ), mGridPlaneMinorTickColor, plane ); GFX->getDrawUtil()->drawPlaneGrid( desc, gridPlanePos, size, Point2F( gridSize, gridSize ), mGridPlaneColor, plane ); }
void ClipMap::calculateClipMapLevels(const F32 near, const F32 far, const RectF &texBounds, S32 &outStartLevel, S32 &outEndLevel) { PROFILE_START(ClipMap_calculateClipMapLevels); // We also have to deal w/ the available data. So let's figure out if our // desired TCs are in the loaded textureset. // Adjust the specified TC range into a texel range. F32 ftexsize = F32(mTextureSize); RectF tcR(Point2F(texBounds.point.y * ftexsize, texBounds.point.x * ftexsize), ftexsize * texBounds.extent); // If we're tiling, make sure we're only insetting away from the clipmap bounds. // This avoids making bad LOD selections at clipmap boundaries. // Note: compress several compares into one since a*b=0 iff a==0 or b==0 bool doInset = true;//mTile || (tcR.point.x * tcR.point.y * (tcR.extent.x+tcR.point.x-mTextureSize) * (tcR.extent.y+tcR.point.y-mTextureSize) != 0); if(doInset) tcR.inset(-1, -1); // Put some safe defaults in for starters. outEndLevel = mClipStackDepth-1; outStartLevel = getMax(outEndLevel-3, S32(0)); // Now iterate over every clipstack entry and find the smallest that contains // the relevant TCs. S32 minLevelOverlap = mClipStackDepth - 1; S32 maxLevelOverlap = mClipStackDepth - 1; for(S32 i=mClipStackDepth-2; i>=0; i--) { // Find region for entry at this level. RectF r; F32 biti = F32(BIT(i)); F32 biticms = F32(BIT(i) * mClipMapSize); r.point = Point2F( biti * mLevels[i].mToroidalOffset.x, biti * mLevels[i].mToroidalOffset.y); r.extent.set(biticms,biticms); // Is our tex region fully contained? if(r.contains(tcR)) { // If we're fully contained, then this is our new max. maxLevelOverlap = i; minLevelOverlap = i; continue; } // Or else maybe we've got overlap? if (!r.overlaps(tcR)) break; // If we're overlapping then this is our new min... minLevelOverlap = getMin(minLevelOverlap, i); } // Given our level range, do a best fit. We ALWAYS have to have // enough for the minimum detail, so we fit that constraint then // do our best to give additional detail on top of that. // bias the minimum detail to allow smooth transitions to work properly, // this avoids a LOT of texture popping. maxLevelOverlap++; outEndLevel = mClamp(maxLevelOverlap, 0, mClipStackDepth-1); outStartLevel = mClamp(minLevelOverlap, outEndLevel - 3, outEndLevel - 1); // Make sure we're not exceeding our max delta. const S32 delta = outEndLevel - outStartLevel; AssertFatal(delta >= 1 && delta <= 4, "ClipMap::calculateClipMapLevels - range in levels outside of 2..4 range!"); PROFILE_END(); }
void ScatterSky::_render( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) { if ( overrideMat || (!mShader && !_initShader()) ) return; GFXTransformSaver saver; if ( mVB.isNull() || mPrimBuffer.isNull() ) _initVBIB(); GFX->setShader( mShader ); GFX->setShaderConstBuffer( mShaderConsts ); Point4F sphereRadii( mSphereOuterRadius, mSphereOuterRadius * mSphereOuterRadius, mSphereInnerRadius, mSphereInnerRadius * mSphereInnerRadius ); Point4F scatteringCoeffs( mRayleighScattering * mSkyBrightness, mRayleighScattering4PI, mMieScattering * mSkyBrightness, mMieScattering4PI ); Point4F invWavelength( 1.0f / mWavelength4[0], 1.0f / mWavelength4[1], 1.0f / mWavelength4[2], 1.0f ); Point3F camPos( 0, 0, smViewerHeight ); Point4F miscParams( camPos.z, camPos.z * camPos.z, mScale, mScale / mRayleighScaleDepth ); Frustum frust = state->getFrustum(); frust.setFarDist( smEarthRadius + smAtmosphereRadius ); MatrixF proj( true ); frust.getProjectionMatrix( &proj ); Point3F camPos2 = state->getCameraPosition(); MatrixF xfm(true); xfm.setPosition(camPos2);//-Point3F( 0, 0, 200000.0f)); GFX->multWorld(xfm); MatrixF xform(proj);//GFX->getProjectionMatrix()); xform *= GFX->getViewMatrix(); xform *= GFX->getWorldMatrix(); mShaderConsts->setSafe( mModelViewProjSC, xform ); mShaderConsts->setSafe( mMiscSC, miscParams ); mShaderConsts->setSafe( mSphereRadiiSC, sphereRadii ); mShaderConsts->setSafe( mScatteringCoefficientsSC, scatteringCoeffs ); mShaderConsts->setSafe( mCamPosSC, camPos ); mShaderConsts->setSafe( mLightDirSC, mLightDir ); mShaderConsts->setSafe( mSunDirSC, mSunDir ); mShaderConsts->setSafe( mNightColorSC, mNightColor ); mShaderConsts->setSafe( mInverseWavelengthSC, invWavelength ); mShaderConsts->setSafe( mNightInterpolantAndExposureSC, Point2F( mExposure, mNightInterpolant ) ); mShaderConsts->setSafe( mColorizeSC, mColorize*mColorizeAmt ); if ( GFXDevice::getWireframe() ) { GFXStateBlockDesc desc( mStateBlock->getDesc() ); desc.setFillModeWireframe(); GFX->setStateBlockByDesc( desc ); } else GFX->setStateBlock( mStateBlock ); if ( mUseNightCubemap && mNightCubemap ) { mShaderConsts->setSafe( mUseCubemapSC, 1.0f ); if ( !mNightCubemap->mCubemap ) mNightCubemap->createMap(); GFX->setCubeTexture( 0, mNightCubemap->mCubemap ); } else { GFX->setCubeTexture( 0, NULL ); mShaderConsts->setSafe( mUseCubemapSC, 0.0f ); } GFX->setPrimitiveBuffer( mPrimBuffer ); GFX->setVertexBuffer( mVB ); GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, mVertCount, 0, mPrimCount ); }
void PlaneReflector::updateReflection( const ReflectParams ¶ms ) { PROFILE_SCOPE(PlaneReflector_updateReflection); GFXDEBUGEVENT_SCOPE( PlaneReflector_updateReflection, ColorI::WHITE ); mIsRendering = true; S32 texDim = mDesc->texSize; texDim = getMax( texDim, 32 ); // Protect against the reflection texture being bigger // than the current game back buffer. texDim = getMin( texDim, params.viewportExtent.x ); texDim = getMin( texDim, params.viewportExtent.y ); bool texResize = ( texDim != mLastTexSize ); mLastTexSize = texDim; const Point2I texSize( texDim, texDim ); if ( texResize || reflectTex.isNull() || reflectTex->getFormat() != REFLECTMGR->getReflectFormat() ) reflectTex = REFLECTMGR->allocRenderTarget( texSize ); GFXTexHandle depthBuff = LightShadowMap::_getDepthTarget( texSize.x, texSize.y ); // store current matrices GFXTransformSaver saver; Point2I viewport(params.viewportExtent); if(GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide) { viewport.x *= 0.5f; } F32 aspectRatio = F32( viewport.x ) / F32( viewport.y ); Frustum frustum; frustum.set(false, params.query->fov, aspectRatio, params.query->nearPlane, params.query->farPlane); // Manipulate the frustum for tiled screenshots const bool screenShotMode = gScreenShot && gScreenShot->isPending(); if ( screenShotMode ) gScreenShot->tileFrustum( frustum ); GFX->setFrustum( frustum ); // Store the last view info for scoring. mLastDir = params.query->cameraMatrix.getForwardVector(); mLastPos = params.query->cameraMatrix.getPosition(); setGFXMatrices( params.query->cameraMatrix ); // Adjust the detail amount F32 detailAdjustBackup = TSShapeInstance::smDetailAdjust; TSShapeInstance::smDetailAdjust *= mDesc->detailAdjust; if(reflectTarget.isNull()) reflectTarget = GFX->allocRenderToTextureTarget(); reflectTarget->attachTexture( GFXTextureTarget::Color0, reflectTex ); reflectTarget->attachTexture( GFXTextureTarget::DepthStencil, depthBuff ); GFX->pushActiveRenderTarget(); GFX->setActiveRenderTarget( reflectTarget ); U32 objTypeFlag = -1; SceneCameraState reflectCameraState = SceneCameraState::fromGFX(); LIGHTMGR->registerGlobalLights( &reflectCameraState.getFrustum(), false ); // Since we can sometime be rendering a reflection for 1 or 2 frames before // it gets updated do to the lag associated with getting the results from // a HOQ we can sometimes see into parts of the reflection texture that // have nothing but clear color ( eg. under the water ). // To make this look less crappy use the ambient color of the sun. // // In the future we may want to fix this instead by having the scatterSky // render a skirt or something in its lower half. // ColorF clearColor = gClientSceneGraph->getAmbientLightColor(); GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, clearColor, 1.0f, 0 ); if(GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide) { // Store previous values RectI originalVP = GFX->getViewport(); Point2F projOffset = GFX->getCurrentProjectionOffset(); Point3F eyeOffset = GFX->getStereoEyeOffset(); // Render left half of display RectI leftVP = originalVP; leftVP.extent.x *= 0.5; GFX->setViewport(leftVP); MatrixF leftWorldTrans(true); leftWorldTrans.setPosition(Point3F(eyeOffset.x, eyeOffset.y, eyeOffset.z)); MatrixF leftWorld(params.query->cameraMatrix); leftWorld.mulL(leftWorldTrans); Frustum gfxFrustum = GFX->getFrustum(); gfxFrustum.setProjectionOffset(Point2F(projOffset.x, projOffset.y)); GFX->setFrustum(gfxFrustum); setGFXMatrices( leftWorld ); SceneCameraState cameraStateLeft = SceneCameraState::fromGFX(); SceneRenderState renderStateLeft( gClientSceneGraph, SPT_Reflect, cameraStateLeft ); renderStateLeft.setSceneRenderStyle(SRS_SideBySide); renderStateLeft.setSceneRenderField(0); renderStateLeft.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); renderStateLeft.setDiffuseCameraTransform( params.query->cameraMatrix ); renderStateLeft.disableAdvancedLightingBins(true); gClientSceneGraph->renderSceneNoLights( &renderStateLeft, objTypeFlag ); // Render right half of display RectI rightVP = originalVP; rightVP.extent.x *= 0.5; rightVP.point.x += rightVP.extent.x; GFX->setViewport(rightVP); MatrixF rightWorldTrans(true); rightWorldTrans.setPosition(Point3F(-eyeOffset.x, eyeOffset.y, eyeOffset.z)); MatrixF rightWorld(params.query->cameraMatrix); rightWorld.mulL(rightWorldTrans); gfxFrustum = GFX->getFrustum(); gfxFrustum.setProjectionOffset(Point2F(-projOffset.x, projOffset.y)); GFX->setFrustum(gfxFrustum); setGFXMatrices( rightWorld ); SceneCameraState cameraStateRight = SceneCameraState::fromGFX(); SceneRenderState renderStateRight( gClientSceneGraph, SPT_Reflect, cameraStateRight ); renderStateRight.setSceneRenderStyle(SRS_SideBySide); renderStateRight.setSceneRenderField(1); renderStateRight.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); renderStateRight.setDiffuseCameraTransform( params.query->cameraMatrix ); renderStateRight.disableAdvancedLightingBins(true); gClientSceneGraph->renderSceneNoLights( &renderStateRight, objTypeFlag ); // Restore previous values gfxFrustum.clearProjectionOffset(); GFX->setFrustum(gfxFrustum); GFX->setViewport(originalVP); } else { SceneRenderState reflectRenderState ( gClientSceneGraph, SPT_Reflect, SceneCameraState::fromGFX() ); reflectRenderState.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); reflectRenderState.setDiffuseCameraTransform( params.query->cameraMatrix ); reflectRenderState.disableAdvancedLightingBins(true); gClientSceneGraph->renderSceneNoLights( &reflectRenderState, objTypeFlag ); } LIGHTMGR->unregisterAllLights(); // Clean up. reflectTarget->resolve(); GFX->popActiveRenderTarget(); // Restore detail adjust amount. TSShapeInstance::smDetailAdjust = detailAdjustBackup; mIsRendering = false; }
bool DecalManager::clipDecal( DecalInstance *decal, Vector<Point3F> *edgeVerts, const Point2F *clipDepth ) { PROFILE_SCOPE( DecalManager_clipDecal ); // Free old verts and indices. _freeBuffers( decal ); ClippedPolyList clipper; clipper.mNormal.set( Point3F( 0, 0, 0 ) ); clipper.mPlaneList.setSize(6); F32 halfSize = decal->mSize * 0.5f; // Ugly hack for ProjectedShadow! F32 halfSizeZ = clipDepth ? clipDepth->x : halfSize; F32 negHalfSize = clipDepth ? clipDepth->y : halfSize; Point3F decalHalfSize( halfSize, halfSize, halfSize ); Point3F decalHalfSizeZ( halfSizeZ, halfSizeZ, halfSizeZ ); MatrixF projMat( true ); decal->getWorldMatrix( &projMat ); const VectorF &crossVec = decal->mNormal; const Point3F &decalPos = decal->mPosition; VectorF newFwd, newRight; projMat.getColumn( 0, &newRight ); projMat.getColumn( 1, &newFwd ); VectorF objRight( 1.0f, 0, 0 ); VectorF objFwd( 0, 1.0f, 0 ); VectorF objUp( 0, 0, 1.0f ); // See above re: decalHalfSizeZ hack. clipper.mPlaneList[0].set( ( decalPos + ( -newRight * halfSize ) ), -newRight ); clipper.mPlaneList[1].set( ( decalPos + ( -newFwd * halfSize ) ), -newFwd ); clipper.mPlaneList[2].set( ( decalPos + ( -crossVec * decalHalfSizeZ ) ), -crossVec ); clipper.mPlaneList[3].set( ( decalPos + ( newRight * halfSize ) ), newRight ); clipper.mPlaneList[4].set( ( decalPos + ( newFwd * halfSize ) ), newFwd ); clipper.mPlaneList[5].set( ( decalPos + ( crossVec * negHalfSize ) ), crossVec ); clipper.mNormal = -decal->mNormal; Box3F box( -decalHalfSizeZ, decalHalfSizeZ ); projMat.mul( box ); DecalData *decalData = decal->mDataBlock; PROFILE_START( DecalManager_clipDecal_buildPolyList ); getContainer()->buildPolyList( box, decalData->clippingMasks, &clipper ); PROFILE_END(); clipper.cullUnusedVerts(); clipper.triangulate(); clipper.generateNormals(); if ( clipper.mVertexList.empty() ) return false; #ifdef DECALMANAGER_DEBUG mDebugPlanes.clear(); mDebugPlanes.merge( clipper.mPlaneList ); #endif decal->mVertCount = clipper.mVertexList.size(); decal->mIndxCount = clipper.mIndexList.size(); Vector<Point3F> tmpPoints; tmpPoints.push_back(( objFwd * decalHalfSize ) + ( objRight * decalHalfSize )); tmpPoints.push_back(( objFwd * decalHalfSize ) + ( -objRight * decalHalfSize )); tmpPoints.push_back(( -objFwd * decalHalfSize ) + ( -objRight * decalHalfSize )); Point3F lowerLeft(( -objFwd * decalHalfSize ) + ( objRight * decalHalfSize )); projMat.inverse(); _generateWindingOrder( lowerLeft, &tmpPoints ); BiQuadToSqr quadToSquare( Point2F( lowerLeft.x, lowerLeft.y ), Point2F( tmpPoints[0].x, tmpPoints[0].y ), Point2F( tmpPoints[1].x, tmpPoints[1].y ), Point2F( tmpPoints[2].x, tmpPoints[2].y ) ); Point2F uv( 0, 0 ); Point3F vecX(0.0f, 0.0f, 0.0f); // Allocate memory for vert and index arrays _allocBuffers( decal ); Point3F vertPoint( 0, 0, 0 ); for ( U32 i = 0; i < clipper.mVertexList.size(); i++ ) { const ClippedPolyList::Vertex &vert = clipper.mVertexList[i]; vertPoint = vert.point; // Transform this point to // object space to look up the // UV coordinate for this vertex. projMat.mulP( vertPoint ); // Clamp the point to be within the quad. vertPoint.x = mClampF( vertPoint.x, -decalHalfSize.x, decalHalfSize.x ); vertPoint.y = mClampF( vertPoint.y, -decalHalfSize.y, decalHalfSize.y ); // Get our UV. uv = quadToSquare.transform( Point2F( vertPoint.x, vertPoint.y ) ); const RectF &rect = decal->mDataBlock->texRect[decal->mTextureRectIdx]; uv *= rect.extent; uv += rect.point; // Set the world space vertex position. decal->mVerts[i].point = vert.point; decal->mVerts[i].texCoord.set( uv.x, uv.y ); decal->mVerts[i].normal = clipper.mNormalList[i]; decal->mVerts[i].normal.normalize(); if( mFabs( decal->mVerts[i].normal.z ) > 0.8f ) mCross( decal->mVerts[i].normal, Point3F( 1.0f, 0.0f, 0.0f ), &vecX ); else if ( mFabs( decal->mVerts[i].normal.x ) > 0.8f ) mCross( decal->mVerts[i].normal, Point3F( 0.0f, 1.0f, 0.0f ), &vecX ); else if ( mFabs( decal->mVerts[i].normal.y ) > 0.8f ) mCross( decal->mVerts[i].normal, Point3F( 0.0f, 0.0f, 1.0f ), &vecX ); decal->mVerts[i].tangent = mCross( decal->mVerts[i].normal, vecX ); } U32 curIdx = 0; for ( U32 j = 0; j < clipper.mPolyList.size(); j++ ) { // Write indices for each Poly ClippedPolyList::Poly *poly = &clipper.mPolyList[j]; AssertFatal( poly->vertexCount == 3, "Got non-triangle poly!" ); decal->mIndices[curIdx] = clipper.mIndexList[poly->vertexStart]; curIdx++; decal->mIndices[curIdx] = clipper.mIndexList[poly->vertexStart + 1]; curIdx++; decal->mIndices[curIdx] = clipper.mIndexList[poly->vertexStart + 2]; curIdx++; } if ( !edgeVerts ) return true; Point3F tmpHullPt( 0, 0, 0 ); Vector<Point3F> tmpHullPts; for ( U32 i = 0; i < clipper.mVertexList.size(); i++ ) { const ClippedPolyList::Vertex &vert = clipper.mVertexList[i]; tmpHullPt = vert.point; projMat.mulP( tmpHullPt ); tmpHullPts.push_back( tmpHullPt ); } edgeVerts->clear(); U32 verts = _generateConvexHull( tmpHullPts, edgeVerts ); edgeVerts->setSize( verts ); projMat.inverse(); for ( U32 i = 0; i < edgeVerts->size(); i++ ) projMat.mulP( (*edgeVerts)[i] ); return true; }
Point2F Square::RB() const { return Point2F(center.GetX() + maxDistance, center.GetY() + maxDistance); }
void PSSMLightShadowMap::_calcPlanesCullForShadowCasters(Vector< Vector<PlaneF> > &out, const Frustum &viewFrustum, const Point3F &_ligthDir) { #define ENABLE_CULL_ASSERT PROFILE_SCOPE(PSSMLightShadowMap_render_getCullFrustrum); Point3F ligthDir = _ligthDir; PlaneF lightFarPlane, lightNearPlane; MatrixF lightFarPlaneMat(true); MatrixF invLightFarPlaneMat(true); // init data { ligthDir.normalize(); Point3F viewDir = viewFrustum.getTransform().getForwardVector(); viewDir.normalize(); const Point3F viewPosition = viewFrustum.getPosition(); const F32 viewDistance = viewFrustum.getBounds().len(); lightNearPlane = PlaneF(viewPosition + (viewDistance * -ligthDir), ligthDir); const Point3F lightFarPlanePos = viewPosition + (viewDistance * ligthDir); lightFarPlane = PlaneF(lightFarPlanePos, -ligthDir); lightFarPlaneMat = MathUtils::createOrientFromDir(-ligthDir); lightFarPlaneMat.setPosition(lightFarPlanePos); lightFarPlaneMat.invertTo(&invLightFarPlaneMat); } Vector<Point2F> projVertices; //project all frustum vertices into plane // all vertices are 2d and local to far plane projVertices.setSize(8); for (int i = 0; i < 8; ++i) // { const Point3F &point = viewFrustum.getPoints()[i]; #ifdef ENABLE_CULL_ASSERT AssertFatal( PlaneF::Front == lightNearPlane.whichSide(point), "" ); AssertFatal( PlaneF::Front == lightFarPlane.whichSide(point), "" ); #endif Point3F localPoint(lightFarPlane.project(point)); invLightFarPlaneMat.mulP(localPoint); projVertices[i] = Point2F(localPoint.x, localPoint.z); } //create hull arround projected proints Vector<Point2F> hullVerts; MathUtils::mBuildHull2D(projVertices, hullVerts); Vector<PlaneF> planes; planes.push_back(lightNearPlane); planes.push_back(lightFarPlane); //build planes for (int i = 0; i < (hullVerts.size() - 1); ++i) { Point2F pos2D = (hullVerts[i] + hullVerts[i + 1]) / 2; Point3F pos3D(pos2D.x, 0, pos2D.y); Point3F pos3DA(hullVerts[i].x, 0, hullVerts[i].y); Point3F pos3DB(hullVerts[i + 1].x, 0, hullVerts[i + 1].y); // move hull points to 3d space lightFarPlaneMat.mulP(pos3D); lightFarPlaneMat.mulP(pos3DA); lightFarPlaneMat.mulP(pos3DB); PlaneF plane(pos3D, MathUtils::mTriangleNormal(pos3DB, pos3DA, (pos3DA - ligthDir))); planes.push_back(plane); } //recalculate planes for each splits for (int split = 0; split < mNumSplits; ++split) { Frustum subFrustum(viewFrustum); subFrustum.cropNearFar(mSplitDist[split], mSplitDist[split + 1]); subFrustum.setFarDist(getMin(subFrustum.getFarDist()*2.5f, viewFrustum.getFarDist())); subFrustum.update(); Vector<PlaneF> subPlanes = planes; for (int planeIdx = 0; planeIdx < subPlanes.size(); ++planeIdx) { PlaneF &plane = subPlanes[planeIdx]; F32 minDist = 0; //calculate near vertex distance for (int vertexIdx = 0; vertexIdx < 8; ++vertexIdx) { Point3F point = subFrustum.getPoints()[vertexIdx]; minDist = getMin(plane.distToPlane(point), minDist); } // move plane to near vertex Point3F newPos = plane.getPosition() + (plane.getNormal() * minDist); plane = PlaneF(newPos, plane.getNormal()); #ifdef ENABLE_CULL_ASSERT for(int x = 0; x < 8; ++x) { AssertFatal( PlaneF::Back != plane.whichSide( subFrustum.getPoints()[x] ), ""); } #endif } out.push_back(subPlanes); } #undef ENABLE_CULL_ASSERT }
bool TerrainBlock::castRayI(const Point3F &start, const Point3F &end, RayInfo *info, bool collideEmpty) { lineCount = 0; lineStart = start; lineEnd = end; info->object = this; if(start.x == end.x && start.y == end.y) { if (end.z == start.z) return false; F32 height; if(!getNormalAndHeight(Point2F(start.x, start.y), &info->normal, &height, true)) return false; F32 t = (height - start.z) / (end.z - start.z); if(t < 0 || t > 1) return false; info->t = t; return true; } F32 invBlockWorldSize = 1 / F32(mSquareSize * BlockSquareWidth); Point3F pStart(start.x * invBlockWorldSize, start.y * invBlockWorldSize, start.z); Point3F pEnd(end.x * invBlockWorldSize, end.y * invBlockWorldSize, end.z); int blockX = (S32)mFloor(pStart.x); int blockY = (S32)mFloor(pStart.y); int dx, dy; F32 invDeltaX; if(pEnd.x == pStart.x) { calcInterceptX = calcInterceptNone; invDeltaX = 0; dx = 0; } else { invDeltaX = 1 / (pEnd.x - pStart.x); calcInterceptX = calcInterceptV; if(pEnd.x < pStart.x) dx = -1; else dx = 1; } F32 invDeltaY; if(pEnd.y == pStart.y) { calcInterceptY = calcInterceptNone; invDeltaY = 0; dy = 0; } else { invDeltaY = 1 / (pEnd.y - pStart.y); calcInterceptY = calcInterceptV; if(pEnd.y < pStart.y) dy = -1; else dy = 1; } F32 startT = 0; for(;;) { F32 nextXInt = calcInterceptX(pStart.x, invDeltaX, (F32)(blockX + (dx == 1))); F32 nextYInt = calcInterceptY(pStart.y, invDeltaY, (F32)(blockY + (dy == 1))); F32 intersectT = 1; if(nextXInt < intersectT) intersectT = nextXInt; if(nextYInt < intersectT) intersectT = nextYInt; if(castRayBlock(pStart, pEnd, Point2I(blockX * BlockSquareWidth, blockY * BlockSquareWidth), BlockShift, invDeltaX, invDeltaY, startT, intersectT, info, collideEmpty)) { info->normal.z *= BlockSquareWidth * mSquareSize; info->normal.normalize(); return true; } startT = intersectT; if(intersectT >= 1) break; if(nextXInt < nextYInt) blockX += dx; else if(nextYInt < nextXInt) blockY += dy; else { blockX += dx; blockY += dy; } } return false; }
void Sun::_renderCorona( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) { // Calculate Billboard Radius (in world units) to be constant, independent of distance. // Takes into account distance, viewport size, and specified size in editor F32 BBRadius = mCoronaWorldRadius; mMatrixSet->restoreSceneViewProjection(); if ( state->isReflectPass() ) mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() ); //mMatrixSet->setWorld( MatrixF::Identity ); // Initialize points with basic info Point3F points[4]; points[0] = Point3F(-BBRadius, 0.0, -BBRadius); points[1] = Point3F( -BBRadius, 0.0, BBRadius); points[2] = Point3F( BBRadius, 0.0, BBRadius); points[3] = Point3F( BBRadius, 0.0, -BBRadius); static const Point2F sCoords[4] = { Point2F( 0.0f, 0.0f ), Point2F( 0.0f, 1.0f ), Point2F( 1.0f, 1.0f ), Point2F( 1.0f, 0.0f ) }; // Get info we need to adjust points const MatrixF &camView = state->getCameraTransform(); // Finalize points for(S32 i = 0; i < 4; i++) { // align with camera camView.mulV(points[i]); // offset points[i] += mLightWorldPos; } ColorF vertColor; if ( mCoronaUseLightColor ) vertColor = mLightColor; else vertColor = mCoronaTint; GFXVertexBufferHandle< GFXVertexPCT > vb; vb.set( GFX, 4, GFXBufferTypeVolatile ); GFXVertexPCT *pVert = vb.lock(); if(!pVert) return; for ( S32 i = 0; i < 4; i++ ) { pVert->color.set( vertColor ); pVert->point.set( points[i] ); pVert->texCoord.set( sCoords[i].x, sCoords[i].y ); pVert++; } vb.unlock(); // Setup SceneData struct. SceneData sgData; sgData.wireframe = GFXDevice::getWireframe(); sgData.visibility = 1.0f; // Draw it while ( mCoronaMatInst->setupPass( state, sgData ) ) { mCoronaMatInst->setTransforms( *mMatrixSet, state ); mCoronaMatInst->setSceneInfo( state, sgData ); GFX->setVertexBuffer( vb ); GFX->drawPrimitive( GFXTriangleFan, 0, 2 ); } }
void GFXDrawUtil::drawRectFill( const Point2I &upperLeft, const Point2I &lowerRight, const ColorI &color ) { drawRectFill(Point2F((F32)upperLeft.x, (F32)upperLeft.y), Point2F((F32)lowerRight.x, (F32)lowerRight.y), color); }
void ScatterSky::_renderMoon( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) { if ( !mMoonMatInst ) return; Point3F moonlightPosition = state->getCameraPosition() - /*mLight->getDirection()*/ mMoonLightDir * state->getFarPlane() * 0.9f; F32 dist = (moonlightPosition - state->getCameraPosition()).len(); // worldRadius = screenRadius * dist / worldToScreen // screenRadius = worldRadius / dist * worldToScreen // F32 screenRadius = GFX->getViewport().extent.y * mMoonScale * 0.5f; F32 worldRadius = screenRadius * dist / state->getWorldToScreenScale().y; // Calculate Billboard Radius (in world units) to be constant, independent of distance. // Takes into account distance, viewport size, and specified size in editor F32 BBRadius = worldRadius; mMatrixSet->restoreSceneViewProjection(); if ( state->isReflectPass() ) mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() ); mMatrixSet->setWorld( MatrixF::Identity ); // Initialize points with basic info Point3F points[4]; points[0] = Point3F(-BBRadius, 0.0, -BBRadius); points[1] = Point3F( -BBRadius, 0.0, BBRadius); points[2] = Point3F( BBRadius, 0.0, BBRadius); points[3] = Point3F( BBRadius, 0.0, -BBRadius); static const Point2F sCoords[4] = { Point2F( 0.0f, 0.0f ), Point2F( 0.0f, 1.0f ), Point2F( 1.0f, 1.0f ), Point2F( 1.0f, 0.0f ) }; // Get info we need to adjust points const MatrixF &camView = state->getCameraTransform(); // Finalize points for(int i = 0; i < 4; i++) { // align with camera camView.mulV(points[i]); // offset points[i] += moonlightPosition; } // Vertex color. ColorF moonVertColor( 1.0f, 1.0f, 1.0f, mNightInterpolant ); // Copy points to buffer. GFXVertexBufferHandle< GFXVertexPCT > vb; vb.set( GFX, 4, GFXBufferTypeVolatile ); GFXVertexPCT *pVert = vb.lock(); for ( S32 i = 0; i < 4; i++ ) { pVert->color.set( moonVertColor ); pVert->point.set( points[i] ); pVert->texCoord.set( sCoords[i].x, sCoords[i].y ); pVert++; } vb.unlock(); // Setup SceneData struct. SceneData sgData; sgData.wireframe = GFXDevice::getWireframe(); sgData.visibility = 1.0f; // Draw it while ( mMoonMatInst->setupPass( state, sgData ) ) { mMoonMatInst->setTransforms( *mMatrixSet, state ); mMoonMatInst->setSceneInfo( state, sgData ); GFX->setVertexBuffer( vb ); GFX->drawPrimitive( GFXTriangleFan, 0, 2 ); } }
void DecalRoad::_captureVerts() { PROFILE_SCOPE( DecalRoad_captureVerts ); //Con::warnf( "%s - captureVerts", isServerObject() ? "server" : "client" ); if ( isServerObject() ) { //Con::errorf( "DecalRoad::_captureVerts - called on the server side!" ); return; } if ( mEdges.size() == 0 ) return; // // Construct ClippedPolyList objects for each pair // of roadEdges. // Use them to capture Terrain verts. // SphereF sphere; RoadEdge *edge = NULL; RoadEdge *nextEdge = NULL; mTriangleCount = 0; mVertCount = 0; Vector<ClippedPolyList> clipperList; for ( U32 i = 0; i < mEdges.size() - 1; i++ ) { Box3F box; edge = &mEdges[i]; nextEdge = &mEdges[i+1]; box.minExtents = edge->p1; box.maxExtents = edge->p1; box.extend( edge->p0 ); box.extend( edge->p2 ); box.extend( nextEdge->p0 ); box.extend( nextEdge->p1 ); box.extend( nextEdge->p2 ); box.minExtents.z -= 5.0f; box.maxExtents.z += 5.0f; sphere.center = ( nextEdge->p1 + edge->p1 ) * 0.5f; sphere.radius = 100.0f; // NOTE: no idea how to calculate this ClippedPolyList clipper; clipper.mNormal.set(0.0f, 0.0f, 0.0f); VectorF n; PlaneF plane0, plane1; // Construct Back Plane n = edge->p2 - edge->p0; n.normalize(); n = mCross( n, edge->uvec ); plane0.set( edge->p0, n ); clipper.mPlaneList.push_back( plane0 ); // Construct Front Plane n = nextEdge->p2 - nextEdge->p0; n.normalize(); n = -mCross( edge->uvec, n ); plane1.set( nextEdge->p0, -n ); //clipper.mPlaneList.push_back( plane1 ); // Test if / where the planes intersect. bool discardLeft = false; bool discardRight = false; Point3F iPos; VectorF iDir; if ( plane0.intersect( plane1, iPos, iDir ) ) { Point2F iPos2F( iPos.x, iPos.y ); Point2F cPos2F( edge->p1.x, edge->p1.y ); Point2F rVec2F( edge->rvec.x, edge->rvec.y ); Point2F iVec2F = iPos2F - cPos2F; F32 iLen = iVec2F.len(); iVec2F.normalize(); if ( iLen < edge->width * 0.5f ) { F32 dot = mDot( rVec2F, iVec2F ); // The clipping planes intersected on the right side, // discard the right side clipping plane. if ( dot > 0.0f ) discardRight = true; // The clipping planes intersected on the left side, // discard the left side clipping plane. else discardLeft = true; } } // Left Plane if ( !discardLeft ) { n = ( nextEdge->p0 - edge->p0 ); n.normalize(); n = mCross( edge->uvec, n ); clipper.mPlaneList.push_back( PlaneF(edge->p0, n) ); } else { nextEdge->p0 = edge->p0; } // Right Plane if ( !discardRight ) { n = ( nextEdge->p2 - edge->p2 ); n.normalize(); n = -mCross( n, edge->uvec ); clipper.mPlaneList.push_back( PlaneF(edge->p2, -n) ); } else { nextEdge->p2 = edge->p2; } n = nextEdge->p2 - nextEdge->p0; n.normalize(); n = -mCross( edge->uvec, n ); plane1.set( nextEdge->p0, -n ); clipper.mPlaneList.push_back( plane1 ); // We have constructed the clipping planes, // now grab/clip the terrain geometry getContainer()->buildPolyList( PLC_Decal, box, TerrainObjectType, &clipper ); clipper.cullUnusedVerts(); clipper.triangulate(); clipper.generateNormals(); // If we got something, add it to the ClippedPolyList Vector if ( !clipper.isEmpty() && !( smDiscardAll && ( discardRight || discardLeft ) ) ) { clipperList.push_back( clipper ); mVertCount += clipper.mVertexList.size(); mTriangleCount += clipper.mPolyList.size(); } } // // Set the roadEdge height to be flush with terrain // This is not really necessary but makes the debug spline rendering better. // for ( U32 i = 0; i < mEdges.size() - 1; i++ ) { edge = &mEdges[i]; _getTerrainHeight( edge->p0.x, edge->p0.y, edge->p0.z ); _getTerrainHeight( edge->p2.x, edge->p2.y, edge->p2.z ); } // // Allocate the RoadBatch(s) // // If we captured no verts, then we can return here without // allocating any RoadBatches or the Vert/Index Buffers. // PreprenderImage will not allocate a render instance while // mBatches.size() is zero. U32 numClippers = clipperList.size(); if ( numClippers == 0 ) return; mBatches.clear(); // Allocate the VertexBuffer and PrimitiveBuffer mVB.set( GFX, mVertCount, GFXBufferTypeStatic ); mPB.set( GFX, mTriangleCount * 3, 0, GFXBufferTypeStatic ); // Lock the VertexBuffer GFXVertexPNTBT *vertPtr = mVB.lock(); if(!vertPtr) return; U32 vertIdx = 0; // // Fill the VertexBuffer and vertex data for the RoadBatches // Loop through the ClippedPolyList Vector // RoadBatch *batch = NULL; F32 texStart = 0.0f; F32 texEnd; for ( U32 i = 0; i < clipperList.size(); i++ ) { ClippedPolyList *clipper = &clipperList[i]; RoadEdge &edge = mEdges[i]; RoadEdge &nextEdge = mEdges[i+1]; VectorF segFvec = nextEdge.p1 - edge.p1; F32 segLen = segFvec.len(); segFvec.normalize(); F32 texLen = segLen / mTextureLength; texEnd = texStart + texLen; BiQuadToSqr quadToSquare( Point2F( edge.p0.x, edge.p0.y ), Point2F( edge.p2.x, edge.p2.y ), Point2F( nextEdge.p2.x, nextEdge.p2.y ), Point2F( nextEdge.p0.x, nextEdge.p0.y ) ); // if ( i % mSegmentsPerBatch == 0 ) { mBatches.increment(); batch = &mBatches.last(); batch->bounds.minExtents = clipper->mVertexList[0].point; batch->bounds.maxExtents = clipper->mVertexList[0].point; batch->startVert = vertIdx; } // Loop through each ClippedPolyList for ( U32 j = 0; j < clipper->mVertexList.size(); j++ ) { // Add each vert to the VertexBuffer Point3F pos = clipper->mVertexList[j].point; vertPtr[vertIdx].point = pos; vertPtr[vertIdx].normal = clipper->mNormalList[j]; Point2F uv = quadToSquare.transform( Point2F(pos.x,pos.y) ); vertPtr[vertIdx].texCoord.x = uv.x; vertPtr[vertIdx].texCoord.y = -(( texEnd - texStart ) * uv.y + texStart); vertPtr[vertIdx].tangent = mCross( segFvec, clipper->mNormalList[j] ); vertPtr[vertIdx].binormal = segFvec; vertIdx++; // Expand the RoadBatch bounds to contain this vertex batch->bounds.extend( pos ); } batch->endVert = vertIdx - 1; texStart = texEnd; } // Unlock the VertexBuffer, we are done filling it. mVB.unlock(); // Lock the PrimitiveBuffer U16 *idxBuff; mPB.lock(&idxBuff); U32 curIdx = 0; U16 vertOffset = 0; batch = NULL; S32 batchIdx = -1; // Fill the PrimitiveBuffer // Loop through each ClippedPolyList in the Vector for ( U32 i = 0; i < clipperList.size(); i++ ) { ClippedPolyList *clipper = &clipperList[i]; if ( i % mSegmentsPerBatch == 0 ) { batchIdx++; batch = &mBatches[batchIdx]; batch->startIndex = curIdx; } for ( U32 j = 0; j < clipper->mPolyList.size(); j++ ) { // Write indices for each Poly ClippedPolyList::Poly *poly = &clipper->mPolyList[j]; AssertFatal( poly->vertexCount == 3, "Got non-triangle poly!" ); idxBuff[curIdx] = clipper->mIndexList[poly->vertexStart] + vertOffset; curIdx++; idxBuff[curIdx] = clipper->mIndexList[poly->vertexStart + 1] + vertOffset; curIdx++; idxBuff[curIdx] = clipper->mIndexList[poly->vertexStart + 2] + vertOffset; curIdx++; } batch->endIndex = curIdx - 1; vertOffset += clipper->mVertexList.size(); } // Unlock the PrimitiveBuffer, we are done filling it. mPB.unlock(); // Generate the object/world bounds // Is the union of all batch bounding boxes. Box3F box; for ( U32 i = 0; i < mBatches.size(); i++ ) { const RoadBatch &batch = mBatches[i]; if ( i == 0 ) box = batch.bounds; else box.intersect( batch.bounds ); } Point3F pos = getPosition(); mWorldBox = box; resetObjectBox(); // Make sure we are in the correct bins given our world box. if( getSceneManager() != NULL ) getSceneManager()->notifyObjectDirty( this ); }
//----------------------------------------------------------------------------- // Draw Bitmaps //----------------------------------------------------------------------------- void GFXDrawUtil::drawBitmap( GFXTextureObject* texture, const Point2I &in_rAt, const GFXBitmapFlip in_flip, const GFXTextureFilterType filter , bool in_wrap /*= true*/ ) { drawBitmap(texture,Point2F((F32)in_rAt.x,(F32)in_rAt.y),in_flip,filter,in_wrap); }
void GFXDrawUtil::drawBitmapSR( GFXTextureObject* texture, const Point2I &in_rAt, const RectI &srcRect, const GFXBitmapFlip in_flip, const GFXTextureFilterType filter , bool in_wrap /*= true*/ ) { drawBitmapSR(texture,Point2F((F32)in_rAt.x,(F32)in_rAt.y),RectF((F32)srcRect.point.x,(F32)srcRect.point.y,(F32)srcRect.extent.x,(F32)srcRect.extent.y),in_flip,filter,in_wrap); }
DecalInstance* DecalManager::raycast( const Point3F &start, const Point3F &end, bool savedDecalsOnly ) { if ( !mData ) return NULL; const Vector<DecalSphere*> &grid = mData->getGrid(); DecalInstance *inst = NULL; SphereF worldSphere( Point3F( 0, 0, 0 ), 1.0f ); Vector<DecalInstance*> hitDecals; for ( U32 i = 0; i < grid.size(); i++ ) { DecalSphere *decalSphere = grid[i]; if ( !decalSphere->mWorldSphere.intersectsRay( start, end ) ) continue; const Vector<DecalInstance*> &items = decalSphere->mItems; for ( U32 n = 0; n < items.size(); n++ ) { inst = items[n]; if ( !inst ) continue; if ( savedDecalsOnly && !(inst->mFlags & SaveDecal) ) continue; worldSphere.center = inst->mPosition; worldSphere.radius = inst->mSize; if ( !worldSphere.intersectsRay( start, end ) ) continue; RayInfo ri; bool containsPoint = false; if ( gServerContainer.castRayRendered( start, end, STATIC_COLLISION_MASK, &ri ) ) { Point2F poly[4]; poly[0].set( inst->mPosition.x - (inst->mSize / 2), inst->mPosition.y + (inst->mSize / 2)); poly[1].set( inst->mPosition.x - (inst->mSize / 2), inst->mPosition.y - (inst->mSize / 2)); poly[2].set( inst->mPosition.x + (inst->mSize / 2), inst->mPosition.y - (inst->mSize / 2)); poly[3].set( inst->mPosition.x + (inst->mSize / 2), inst->mPosition.y + (inst->mSize / 2)); if ( MathUtils::pointInPolygon( poly, 4, Point2F(ri.point.x, ri.point.y) ) ) containsPoint = true; } if( !containsPoint ) continue; hitDecals.push_back( inst ); } } if ( hitDecals.empty() ) return NULL; gSortPoint = start; dQsort( hitDecals.address(), hitDecals.size(), sizeof(DecalInstance*), cmpDecalDistance ); return hitDecals[0]; }
void Scene::render() { #ifdef GL_33 //Light glUniform3fv(lightDirectionLocation, 1, &lightDirection.x); glUniform4fv(lightColorLocation, 1, &lightColor.red); glUniform4fv(ambientColorLocation, 1, &ambientColor.red); glUniform3fv(sunPositionLocation, 1, &sunPosition.x); glUniform1f(sunPowerLocation, sunPower); glUniform1f(specularExponentLocation, specularExponent); //Camera viewMatrix = glm::mat4x4(1); viewMatrix = glm::rotate(viewMatrix, pitch, glm::vec3(1, 0, 0)); viewMatrix = glm::rotate(viewMatrix, yaw, glm::vec3(0, 1, 0)); viewMatrix = glm::rotate(viewMatrix, -90.0f, glm::vec3(1, 0, 0)); viewMatrix = glm::translate(viewMatrix, -cameraPosition); //Model modelMatrix = glm::mat4x4(1); //Combined glm::mat4x4 mvpMat = projectionMatrix * viewMatrix * modelMatrix; glm::mat3x3 mv3Mat = glm::mat3(viewMatrix * modelMatrix); //Send to OpenGL glUniformMatrix4fv(mvpMatrixLocation, 1, GL_FALSE, &mvpMat[0][0]); glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]); glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]); glUniformMatrix3fv(modelView3Location, 1, GL_FALSE, &mv3Mat[0][0]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glEnable(GL_CULL_FACE); glEnable(GL_ALPHA); glEnable(GL_MULTISAMPLE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for (U32 index = 0; index < difCount; index ++) { difs[index]->render(); } #ifdef BUILD_PHYSICS Point3F pos = sphere->getPosition(); AngAxisF rot = sphere->getRotation(); //Model modelMatrix = glm::mat4x4(1); modelMatrix = glm::translate(modelMatrix, glm::vec3(pos.x, pos.y, pos.z)); modelMatrix = glm::rotate(modelMatrix, rot.angle * (F32)(180.0f / M_PI), glm::vec3(rot.axis.x, rot.axis.y, rot.axis.z)); //Combined mvpMat = projectionMatrix * viewMatrix * modelMatrix; //Send to OpenGL glUniformMatrix4fv(mvpMatrixLocation, 1, GL_FALSE, &mvpMat[0][0]); glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]); glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]); sphere->render(ColorF(1, 1, 0, 1)); #endif #else //Load the model matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_CULL_FACE); glEnable(GL_ALPHA); glEnable(GL_MULTISAMPLE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Camera viewMatrix = glm::mat4x4(1); viewMatrix = glm::rotate(viewMatrix, pitch, glm::vec3(1, 0, 0)); viewMatrix = glm::rotate(viewMatrix, yaw, glm::vec3(0, 1, 0)); viewMatrix = glm::rotate(viewMatrix, -90.0f, glm::vec3(1, 0, 0)); // viewMatrix = glm::translate(viewMatrix, -cameraPosition); viewMatrix = glm::translate(viewMatrix, cameraPosition); glLoadMatrixf(&modelviewMatrix[0][0]); //Clear glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glLightfv(GL_LIGHT0, GL_POSITION, gLightDirection); Point3F offset = {0.f, 0.f, 0.f}; if (listNeedsDisplay) { displayList = glGenLists(1); glNewList(displayList, GL_COMPILE_AND_EXECUTE); for (U32 index = 0; index < difCount; index ++) { difs[index]->render(); } glEndList(); listNeedsDisplay = false; } else { glCallList(displayList); } sphere->render(ColorF(1, 1, 0, 1)); glDisable(GL_CULL_FACE); if (selection.hasSelection) { Surface surface = selection.interior->surface[selection.surfaceIndex]; TexGenEq texGenEq = selection.interior->texGenEq[surface.texGenIndex]; Point3F normal = selection.interior->normal[selection.interior->plane[surface.planeIndex].normalIndex]; Point3F first = selection.interior->point[selection.interior->index[surface.windingStart]]; F32 len = 0; glBegin(GL_TRIANGLE_STRIP); for (U32 i = 0; i < surface.windingCount; i ++) { Point3F vert = selection.interior->point[selection.interior->index[surface.windingStart + i]]; glVertex3f(vert.x, vert.y, vert.z); Point2F point = point3F_project_plane(vert, normal, first); F32 distance = point.length(); len = (distance > len ? distance : len); } glEnd(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(-1, 1, -1, 1, -100, 100); glMatrixMode(GL_MODELVIEW); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glLoadIdentity(); Texture *texture = selection.interior->texture[surface.textureIndex]; if (texture) { if (!texture->generated) { texture->generateBuffer(); } texture->activate(); } glBegin(GL_TRIANGLE_STRIP); int w, h; SDL_GetWindowSize(window, &w, &h); GLfloat aspect = (GLfloat)w / (GLfloat)h; for (U32 i = 0; i < surface.windingCount; i ++) { Point3F vert = selection.interior->point[selection.interior->index[surface.windingStart + i]]; Point2F texuv = Point2F(planeF_distance_to_point(texGenEq.planeX, vert), planeF_distance_to_point(texGenEq.planeY, vert)); glTexCoord2fv(&texuv.x); Point2F point = point3F_project_plane(vert, (surface.planeFlipped ? normal * -1 : normal), first); glVertex3f(point.x / len / aspect, point.y / len, 0); } glEnd(); if (texture) texture->deactivate(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glPopMatrix(); } #endif }