Sphere GLight::effectSphere(float cutoff) const { if (position.w == 0) { // Directional light return Sphere(Vector3::zero(), finf()); } else { // Avoid divide by zero cutoff = max(cutoff, 0.00001f); float maxIntensity = max(color.r, max(color.g, color.b)); float radius = finf(); if (attenuation[2] != 0) { // Solve I / attenuation.dot(1, r, r^2) < cutoff for r // // a[0] + a[1] r + a[2] r^2 > I/cutoff // float a = attenuation[2]; float b = attenuation[1]; float c = attenuation[0] - maxIntensity / cutoff; float discrim = square(b) - 4 * a * c; if (discrim >= 0) { discrim = sqrt(discrim); float r1 = (-b + discrim) / (2 * a); float r2 = (-b - discrim) / (2 * a); if (r1 < 0) { if (r2 > 0) { radius = r2; } } else if (r2 > 0) { radius = min(r1, r2); } else { radius = r1; } } } else if (attenuation[1] != 0) { // Solve I / attenuation.dot(1, r) < cutoff for r // // r * a[1] + a[0] = I / cutoff // r = (I / cutoff - a[0]) / a[1] float radius = (maxIntensity / cutoff - attenuation[0]) / attenuation[1]; radius = max(radius, 0.0f); } return Sphere(position.xyz(), radius); } }
bool ArticulatedViewer::onEvent(const GEvent& e, App* app) { if ((e.type == GEventType::MOUSE_BUTTON_DOWN) && (e.button.button == 0) && ! app->userInput->keyDown(GKey::LCTRL)) { // Intersect all tri lists with the ray from the camera const Ray& ray = app->activeCamera()->worldRay(e.button.x, e.button.y, app->renderDevice->viewport()); m_selectedPart = NULL; m_selectedMesh = NULL; m_selectedTriangleIndex = -1; Model::HitInfo hitInfo; float distance = finf(); const bool hit = m_model->intersect(ray, m_offset, ArticulatedModel::defaultPose(), distance, hitInfo); if (hit) { // shared_ptr<ArticulatedModel> model = dynamic_pointer_cast<ArticulatedModel>(hitInfo.model); // alwaysAssertM(notNull(model), "Not a model!"); m_selectedMesh = m_model->mesh(hitInfo.meshID); m_selectedTriangleIndex = hitInfo.primitiveIndex; } if (notNull(m_selectedMesh)) { m_selectedPart = m_selectedMesh->logicalPart; } return hit; } else if ((e.type == GEventType::KEY_DOWN) && (e.key.keysym.sym == 'r')) { onInit(m_filename); return true; } return false; }
Vector2 GFont::appendToCharVertexArrayWordWrap (Array<CPUCharVertex>& cpuCharArray, Array<int>& indexArray, RenderDevice* renderDevice, float maxWidth, const String& s, const Vector2& pos2D, float size, const Color4& color, const Color4& border, XAlign xalign, YAlign yalign, Spacing spacing) const { if (maxWidth == finf()) { return appendToCharVertexArray(cpuCharArray, indexArray, renderDevice, s, pos2D, size, color, border, xalign, yalign, spacing); } Vector2 bounds = Vector2::zero(); Point2 p = pos2D; String rest = s; String first = ""; while (! rest.empty()) { wordWrapCut(maxWidth, rest, first, size, spacing); Vector2 extent = appendToCharVertexArray(cpuCharArray, indexArray, renderDevice, first, p, size, color, border, xalign, yalign, spacing); bounds.x = max(bounds.x, extent.x); bounds.y += extent.y; p.y += iCeil(extent.y * 0.8f); } return bounds; }
void RayTracer::traceOnePixel(int x, int y, int threadID) { //used for constructing viewport Vector2 tmp(m_settings.width, m_settings.height); Ray primaryRay; // If one ray per pixel: (kinda debugging mode with blue color for places with no surfel hit if (m_settings.raysPerPixel == 1){ //Get the primary ray from the pixel x,y primaryRay = m_camera->worldRay(x + 0.5f, y + 0.5f, Rect2D(tmp)); //Get the first surfel hit. //Can't call L_i unfortunately because we want the blue background for debugging const shared_ptr<Surfel>& s = RayTracer::castRay(primaryRay, finf(), 0); //If there is a surfel hit, get the direct illumination value and apply to the pixel if (s){ //Call L_scatteredDirect to get direct illumination. Invert primaryRay to get the direction for incident light m_image->set(Point2int32(x,y), L_o(s, -primaryRay.direction(), m_settings.recursiveBounces, *(m_rnd[threadID]))); } else{ //Set the pixels with no surfel hit. Include this line so we could make it a specific color for debug purposes. m_image->set(Point2int32(x,y), Color3(0,0,1)); } } else { Radiance3 L(0,0,0); //If more than one ray, randomly generate required number of rays within the pixel for (int i = 0; i < m_settings.raysPerPixel; ++i){ primaryRay = m_camera->worldRay(x + m_rnd[threadID]->uniform(), y + m_rnd[threadID]->uniform(), Rect2D(tmp)); L += L_i(primaryRay.origin(), primaryRay.direction(), m_settings.recursiveBounces, *(m_rnd[threadID])); } m_image->set(Point2int32(x,y), L/m_settings.raysPerPixel); } }
Matrix4 Matrix4::perspectiveProjection( float left, float right, float bottom, float top, float nearval, float farval, float upDirection) { float x, y, a, b, c, d; x = (2.0f*nearval) / (right-left); y = (2.0f*nearval) / (top-bottom); a = (right+left) / (right-left); b = (top+bottom) / (top-bottom); if (farval >= finf()) { // Infinite view frustum c = -1.0f; d = -2.0f * nearval; } else { c = -(farval+nearval) / (farval-nearval); d = -(2.0f*farval*nearval) / (farval-nearval); } debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1"); y *= upDirection; b *= upDirection; return Matrix4( x, 0, a, 0, 0, y, b, 0, 0, 0, c, d, 0, 0, -1, 0); }
float Camera::worldToScreenSpaceArea(float area, float z, const Rect2D& viewport) const { (void)viewport; if (z >= 0) { return finf(); } return area * (float)square(-nearPlaneZ() / z); }
shared_ptr<Entity> Scene::intersectEyeRay(const shared_ptr<Camera>& camera, const Vector2& pixel, const Rect2D& viewport, const Vector2int16 guardBandThickness, bool hitMarkers, const Array<shared_ptr<Entity> >& exclude, Model::HitInfo& selectionInfo) const { const Ray& ray = camera->worldRay(pixel.x + guardBandThickness.x, pixel.y + guardBandThickness.y, Rect2D(Vector2(viewport.width() + 2 * guardBandThickness.x, viewport.height() + 2 * guardBandThickness.y))); // clear old selection info selectionInfo.clear(); float distance = finf(); return intersect(ray, distance, hitMarkers, exclude, selectionInfo); }
Radiance3 RayTracer::L_i(const Point3 P, const Vector3& wi, int bouncesLeft, Random& rnd) const{ //Get the surfel hit and call L_o to compute radiance at the surfel shared_ptr<Surfel> surfel = castRay(G3D::Ray(P,wi).bumpedRay(0.0001), finf(), 0); if (surfel){ return L_o(surfel, -wi, bouncesLeft, rnd); } else{ //No surfel, return black return Radiance3(0,0,0); } }
void App::onInit() { GApp::onInit(); renderDevice->setSwapBuffersAutomatically(true); logPrintf("App::onInit()\n"); createDeveloperHUD(); showRenderingStats = false; developerWindow->cameraControlWindow->setVisible(false); developerWindow->setVisible(false); developerWindow->videoRecordDialog->setCaptureGui(false); m_debugCamera->filmSettings().setBloomStrength(0.20f); m_debugCamera->filmSettings().setBloomRadiusFraction(0.017f); m_debugCamera->filmSettings().setAntialiasingEnabled(true); m_debugCamera->filmSettings().setCelluloidToneCurve(); if (! filename.empty()) { window()->setCaption(filenameBaseExt(filename) + " - G3D Viewer"); } lighting = shared_ptr<LightingEnvironment>(new LightingEnvironment()); lighting->lightArray.clear(); // The spot light is designed to just barely fit the 3D models. Note that it has no attenuation lighting->lightArray.append(Light::spotTarget("Light", Point3(40, 120, 80), Point3::zero(), 10 * units::degrees(), Power3(50.0f), 1, 0, 0, true, 8192)); lighting->lightArray.last()->shadowMap()->setBias(0.1f); Texture::Encoding e; e.readMultiplyFirst = Color4(Color3(0.5f)); e.format = ImageFormat::RGB32F(); lighting->environmentMapArray.append(Texture::fromFile(System::findDataFile("uffizi/uffizi-*.exr"), e, Texture::DIM_CUBE_MAP)); lighting->ambientOcclusionSettings.numSamples = 24; lighting->ambientOcclusionSettings.radius = 0.75f * units::meters(); lighting->ambientOcclusionSettings.intensity = 2.0f; lighting->ambientOcclusionSettings.bias = 0.06f * units::meters(); lighting->ambientOcclusionSettings.useDepthPeelBuffer = true; m_debugCamera->setFarPlaneZ(-finf()); m_debugCamera->setNearPlaneZ(-0.05f); // Don't clip to the near plane glDisable(GL_DEPTH_CLAMP); colorClear = Color3::white() * 0.9f; //modelController = ThirdPersonManipulator::create(); m_gbufferSpecification.encoding[GBuffer::Field::CS_POSITION_CHANGE].format = NULL; gbuffer()->setSpecification(m_gbufferSpecification); setViewer(filename); developerWindow->sceneEditorWindow->setVisible(false); logPrintf("Done App::onInit()\n"); }
QString MainWindowTask::getFileName(QString fileName) { QFileInfo finf(fileName); QFileDialog dialog(this,trUtf8("Открыть файл"),curDir, "("+finf.fileName()+")"); dialog.setAcceptMode(QFileDialog::AcceptOpen); if(!dialog.exec())return ""; QFileInfo fi(dialog.selectedFiles().first()); return dialog.selectedFiles().first(); };
bool PhysicsFrameSplineEditor::hitsSpline(const Ray& r) { int j = m_spline.control.size(); for (int i = 0; i < j; ++i) { const CFrame& c = m_spline.control[i]; if(r.intersectionTime(Sphere(c.translation, CONTROL_POINT_RADIUS), true) != finf()) { setSelectedControlPointIndex(i); return true; } } return false; }
float Ray::intersectionTime(const class Box& box) const { Vector3 dummy; float time = CollisionDetection::collisionTimeForMovingPointFixedBox( m_origin, m_direction, box, dummy); if ((time == finf()) && (box.contains(m_origin))) { return 0.0f; } else { return time; } }
float Ray::intersectionTime(const class AABox& box) const { Vector3 dummy; bool inside; float time = CollisionDetection::collisionTimeForMovingPointFixedAABox( m_origin, m_direction, box, dummy, inside); if ((time == finf()) && inside) { return 0.0f; } else { return time; } }
bool Sphere::culledBy( const class Plane* plane, int numPlanes, int& cullingPlane, const uint32 _inMask, uint32& childMask) const { if (radius == finf()) { // No plane can cull the infinite box return false; } uint32 inMask = _inMask; assert(numPlanes < 31); childMask = 0; // See if there is one plane for which all of the // vertices are in the negative half space. for (int p = 0; p < numPlanes; p++) { // Only test planes that are not masked if ((inMask & 1) != 0) { bool culledLow = ! plane[p].halfSpaceContainsFinite(center + plane[p].normal() * radius); bool culledHigh = ! plane[p].halfSpaceContainsFinite(center - plane[p].normal() * radius); if (culledLow) { // Plane p culled the sphere cullingPlane = p; // The caller should not recurse into the children, // since the parent is culled. If they do recurse, // make them only test against this one plane, which // will immediately cull the volume. childMask = 1 << p; return true; } else if (culledHigh) { // The bounding volume straddled the plane; we have // to keep testing against this plane childMask |= (1 << p); } } // Move on to the next bit. inMask = inMask >> 1; } // None of the planes could cull this box cullingPlane = -1; return false; }
void RayTracer::traceOnePhoton(int ignoreX, int ignoreY, int threadID) { ThreadData& threadData(m_threadData[threadID]); Photon photon; emitPhoton(*threadData.rnd, photon); const float MIN_POWER_THRESHOLD = 0.001f / m_settings.photon.numEmitted; float probabilityHint = 1.0; for (int numBounces = 0; (numBounces < m_settings.photon.numBounces) && (photon.power.sum() > MIN_POWER_THRESHOLD); ++numBounces) { // Find the first surface float distance = finf(); const shared_ptr<Surfel>& surfel = castRay(photon.position, -photon.wi, distance, false); if (isNull(surfel)) { return; } // Store the photon (if this is not the first bounce and it is // not a purely specular surface) if ((numBounces > 0) && surfel->nonZeroFiniteScattering()) { photon.effectRadius = photonEffectRadius(probabilityHint); // Update photon position. Store it slightly before it hit the surface // to improve filtering later. photon.position = surfel->position + photon.wi * min(photon.effectRadius, distance) / 4; // Store a copy of this photon m_photonList[threadID].append(photon); } // Scatter Color3 weight; Vector3 wo; float probabilityScale; surfel->scatter(PathDirection::SOURCE_TO_EYE, photon.wi, true, *threadData.rnd, weight, wo, probabilityScale); probabilityHint *= probabilityScale; // Update photon power and direction photon.power *= weight; photon.wi = -wo; photon.position = bump(surfel, wo); } }
Module::Module( const char *name, WCValSList<String> & enabled, WCValSList<String> & disabled ) //------------------------------------------------------------ { WCPtrOrderedVector<ComponentFile> components; FileInfo finf( name ); int i; MsgRetType ret; _dataFile = new ElfFile( name, false ); DwarfFileMerger merger( name, enabled, disabled ); if( !merger.upToDate() ) { if( !finf.exists() ) { merger.doMerge(); } else { if( enabled.entries() != 0 ) { ret = WMessageDialog::messagef( topWindow, MsgQuestion, MsgYesNo, "Source Browser", "Database %s is not consistent with module files.\n" "Merge the database now?", name ); if( ret == MsgRetYes ) { merger.doMerge(); } } } } _dataFile->initSections(); _dataFile->getEnabledComponents( &components ); for( i = 0; i < components.entries(); i += 1 ) { _enabledFiles.add( new WFileName( components[i]->name ) ); } components.clear(); _dataFile->getDisabledComponents( &components ); for( i = 0; i < components.entries(); i += 1 ) { _disabledFiles.add( new WFileName( components[i]->name ) ); } checkSourceTime(); _dbgInfo = DRDbgInit( this, _dataFile->getDRSizes(), false ); DRSetDebug( _dbgInfo ); }
void Matrix4::getPerspectiveProjectionParameters( float& left, float& right, float& bottom, float& top, float& nearval, float& farval, float upDirection) const { assert(abs(upDirection) == 1.0f, "upDirection must be -1 or +1"); float x = elt[0][0]; float y = elt[1][1] * upDirection; float a = elt[0][2]; float b = elt[1][2] * upDirection; float c = elt[2][2]; float d = elt[2][3]; assert(elt[3][2] == -1, "Not a projection matrix"); assert(elt[0][1] == 0, "Not a projection matrix"); assert(elt[0][3] == 0, "Not a projection matrix"); assert(elt[1][3] == 0, "Not a projection matrix"); assert(elt[3][3] == 0, "Not a projection matrix"); assert(elt[1][0] == 0, "Not a projection matrix"); assert(elt[2][0] == 0, "Not a projection matrix"); assert(elt[2][1] == 0, "Not a projection matrix"); assert(elt[3][0] == 0, "Not a projection matrix"); assert(elt[3][1] == 0, "Not a projection matrix"); if (c == -1) { farval = finf(); nearval = -d / 2.0f; } else { nearval = d * ((c - 1.0f) / (c + 1.0f) - 1.0f) / (-2.0f * (c - 1.0f) / (c + 1.0f)); farval = nearval * ((c - 1.0f) / (c + 1.0f)); } left = (a - 1.0f) * nearval / x; right = 2.0f * nearval / x + left; bottom = (b - 1.0f) * nearval / y; top = 2.0f * nearval / y + bottom; }
void Matrix4::getPerspectiveProjectionParameters( double& left, double& right, double& bottom, double& top, double& nearval, double& farval, float upDirection) const { debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1"); double x = elt[0][0]; double y = elt[1][1] * upDirection; double a = elt[0][2]; double b = elt[1][2] * upDirection; double c = elt[2][2]; double d = elt[2][3]; // Verify that this really is a projection matrix debugAssertM(elt[3][2] == -1, "Not a projection matrix"); debugAssertM(elt[0][1] == 0, "Not a projection matrix"); debugAssertM(elt[0][3] == 0, "Not a projection matrix"); debugAssertM(elt[1][3] == 0, "Not a projection matrix"); debugAssertM(elt[3][3] == 0, "Not a projection matrix"); debugAssertM(elt[1][0] == 0, "Not a projection matrix"); debugAssertM(elt[2][0] == 0, "Not a projection matrix"); debugAssertM(elt[2][1] == 0, "Not a projection matrix"); debugAssertM(elt[3][0] == 0, "Not a projection matrix"); debugAssertM(elt[3][1] == 0, "Not a projection matrix"); if (c == -1) { farval = finf(); nearval = -d / 2.0; } else { nearval = d * ((c - 1.0) / (c + 1.0) - 1.0) / (-2.0 * (c - 1.0) / (c + 1.0)); farval = nearval * ((c - 1.0) / (c + 1.0)); } left = (a - 1.0) * nearval / x; right = 2.0 * nearval / x + left; bottom = (b - 1.0) * nearval / y; top = 2.0 * nearval / y + bottom; }
float movingDiskFixedLineSegmentCollisionTime(Point2 center, float radius, Vector2 velocity, const LineSegment2D& segment, Point2& collisionLocation) { // Ridiculously implemented in terms of existing 3D functionality Point3 X; const float t = CollisionDetection::collisionTimeForMovingSphereFixedTriangle (Sphere(Point3(center, 0.0f), radius), Vector3(velocity, 0.0f), Triangle(Point3(segment.point(0), +1.0f), Point3(segment.point(0), -1.0f), Point3(segment.point(1), 0.0f)), X); if (t < finf()) { collisionLocation = X.xy(); } return t; }
Radiance3 RayTracer::L_in(const Point3& X, const Vector3& wi, ThreadData& threadData, int bouncesLeft) const { if (bouncesLeft == 0) { // We aren't allowed to trace farther, so estimate from the // environment map return BACKGROUND_RADIANCE; } // Surface hit by the primary ray (at X) float maxDistance = finf(); shared_ptr<Surfel> surfel(castRay(X, wi, maxDistance)); if (notNull(surfel)) { // Hit something return L_out(surfel, -wi, threadData, bouncesLeft); } else { // Hit background return BACKGROUND_RADIANCE; } }
void DirReader::recurseDir(const QString &path, int curDepth) { QDir dir(path); dir.setSorting(flags); dir.setFilter(QDir::AllDirs|QDir::Files); const QStringList files = dir.entryList(); foreach (QString f, files) { if (f == "." || f == "..") continue; QFileInfo finf(dir, f); fileHandler(finf); if (finf.isDir()) // && (finf.absoluteFilePath() != path)) { if (curDepth < maxDirDepth) { recurseDir(finf.absoluteFilePath(), curDepth+1); } } } }
bool App::onEvent(const GEvent& event) { if (GApp::onEvent(event)) { return true; } if (event.type == GEventType::VIDEO_RESIZE) { // Example GUI dynamic layout code. Resize the debugWindow to fill // the screen horizontally. debugWindow->setRect(Rect2D::xywh(0, 0, window()->width(), debugWindow->rect().height())); } if (! m_preventEntitySelect && (event.type == GEventType::MOUSE_BUTTON_DOWN) && (event.button.button == 0)) { // Left click: select by casting a ray through the center of the pixel const Ray& ray = defaultCamera.worldRay(event.button.x + 0.5f, event.button.y + 0.5f, renderDevice->viewport()); float distance = finf(); selectEntity(m_scene->intersect(ray, distance)); } if (! m_preventEntitySelect && (event.type == GEventType::GUI_ACTION) && (event.gui.control == m_entityList)) { // User clicked on dropdown list selectEntity(m_scene->entity(m_entityList->selectedValue().text())); } // If you need to track individual UI events, manage them here. // Return true if you want to prevent other parts of the system // from observing this specific event. // // For example, // if ((event.type == GEventType::GUI_ACTION) && (event.gui.control == m_button)) { ... return true;} // if ((event.type == GEventType::KEY_DOWN) && (event.key.keysym.sym == GKey::TAB)) { ... return true; } return false; }
void ElfFile::addComponentFile( const char * fileName, bool enable ) //------------------------------------------------------------------ { ComponentFile * comp; bool found = false; FileInfo finf( fileName ); // NYI -- use the WCVector find! for( int i = 0; i < _components->entries(); i += 1 ) { if( strcmp( (*_components)[i]->name, fileName ) == 0 ) { comp = (*_components)[ i ]; found = true; } } if( !found ) { comp = ComponentFile::createComponent( finf.st_mtime(), enable, fileName ); } if( !found ) { strcpy( comp->name, fileName ); _components->append( comp ); } }
void MeshAlg::computeBounds( const Array<Vector3>& vertexArray, AABox& box, Sphere& sphere) { Vector3 xmin, xmax, ymin, ymax, zmin, zmax; // FIRST PASS: find 6 minima/maxima points xmin.x = ymin.y = zmin.z = finf(); xmax.x = ymax.y = zmax.z = -finf(); for (int v = 0; v < vertexArray.size(); ++v) { const Vector3& vertex = vertexArray[v]; if (vertex.x < xmin.x) { xmin = vertex; } if (vertex.x > xmax.x) { xmax = vertex; } if (vertex.y < ymin.y) { ymin = vertex; } if (vertex.y > ymax.y) { ymax = vertex; } if (vertex.z < zmin.z) { zmin = vertex; } if (vertex.z > zmax.z) { zmax = vertex; } } // Set points dia1 & dia2 to the maximally separated pair Vector3 dia1 = xmin; Vector3 dia2 = xmax; { // Set xspan = distance between the 2 points xmin & xmax (squared) double xspan = (xmax - xmin).squaredMagnitude(); // Same for y & z spans double yspan = (ymax - ymin).squaredMagnitude(); double zspan = (zmax - zmin).squaredMagnitude(); double maxspan = xspan; if (yspan > maxspan) { maxspan = yspan; dia1 = ymin; dia2 = ymax; } if (zspan > maxspan) { maxspan = zspan; dia1 = zmin; dia2 = zmax; } } // dia1, dia2 is a diameter of initial sphere // calc initial center Vector3 center = (dia1 + dia2) / 2.0; // calculate initial radius^2 and radius Vector3 d = dia2 - sphere.center; double radSq = d.squaredMagnitude(); double rad = sqrt(radSq); // SECOND PASS: increment current sphere double old_to_p, old_to_new; for (int v = 0; v < vertexArray.size(); ++v) { const Vector3& vertex = vertexArray[v]; d = vertex - center; double old_to_p_sq = d.squaredMagnitude(); // do r^2 test first if (old_to_p_sq > radSq) { // this point is outside of current sphere old_to_p = sqrt(old_to_p_sq); // calc radius of new sphere rad = (rad + old_to_p) / 2.0; // for next r^2 compare radSq = rad * rad; old_to_new = old_to_p - rad; // calc center of new sphere center = (rad * center + old_to_new * vertex) / old_to_p; } } const Vector3 min(xmin.x, ymin.y, zmin.z); const Vector3 max(xmax.x, ymax.y, zmax.z); box = AABox(min, max); const float boxRadSq = (max - min).squaredMagnitude() * 0.25f; if (boxRadSq >= radSq){ if (isNaN(center.x) || ! isFinite(rad)) { sphere = Sphere(Vector3::zero(), finf()); } else { sphere = Sphere(center, rad); } } else { sphere = Sphere((max + min) * 0.5f, sqrt(boxRadSq)); } }
void ParticleSystemModel::init() { // Extract the fade in and out times. m_hasCoverageFadeTime = false; m_hasExpireTime = false; for (const shared_ptr<Emitter>& emitter : m_emitterArray) { const float fi = emitter->specification().coverageFadeInTime; const float fo = emitter->specification().coverageFadeOutTime; m_hasCoverageFadeTime = m_hasCoverageFadeTime || (fi > 0) || (fo > 0); m_coverageFadeTime.append(std::make_pair(fi, fo)); m_hasExpireTime = m_hasExpireTime || (emitter->specification().particleLifetimeMean < finf()); } }
void RayTracer::tracePhotons(Photon p, int bouncesLeft){ //Only trace the photon if more than one bounce if (bouncesLeft > 0){ //Get the intersected surface shared_ptr<UniversalSurfel> surfel = dynamic_pointer_cast<UniversalSurfel>(castRay(G3D::Ray(p.origin,p.direction).bumpedRay(0.0001), finf(), 0)); if (surfel){ p.origin = surfel->position; //Don't store for mirror surfaces if (!(surfel->glossyReflectionCoefficient.nonZero() && (surfel->glossyReflectionExponent == inf()))){ Vector3 D = p.origin - m_camera->frame().translation; //if (D.length() < 10){ if(castRay(G3D::Ray(m_camera->frame().translation,D).bumpedRay(0.0001), D.length(), 1)) { photons.insert(p); } //} } shared_ptr<Random> rnd = m_rnd[0]; Vector3 wo; Color3 weight; //scatter the photon using the method provided by G3D. Used to be a lot of lines which got deleted surfel->scatter(PathDirection::SOURCE_TO_EYE, -p.direction, true, *rnd, weight, wo); //If it scatters, continue tracing if (wo.magnitude() > 0){ p.direction = wo; p.power *= weight; tracePhotons(p, bouncesLeft - 1); } rnd.reset(); } } }
void Browse::positionEditor( char * fileName, ulong line, uint col, int hiliteLen ) //----------------------------------------------------------------- { FileInfo finf( fileName ); if( finf.exists() ) { if( optManager()->isEditorDLL() ) { if( _editorDLL->isInitialized() ) { if( _editorDLL->EDITConnect() ) { _editorDLL->EDITFile( fileName, "" ); _editorDLL->EDITLocate( line, col, hiliteLen ); _editorDLL->EDITShowWindow( EDIT_SHOWNORMAL ); } else { errMessage( "Unable to connect to editor" ); } } else { ASSERTION( 0 /* uh-oh -- the menu item should be grayed */ ); } } else { WString cmd( optManager()->getEditorName() ); WString editorParms( optManager()->getEditorParms() ); cmd.concat( ' ' ); // space after editor name before parms int parmsize = editorParms.size(); for( int i=0; i < parmsize; i++ ) { switch( editorParms[i] ) { case '%': switch( editorParms[i+1] ) { case 'f': // file name cmd.concat( fileName ); break; case 'r': // row to go to cmd.concatf( "%ld", line ); break; case 'c': // column to go to cmd.concatf( "%d", col ); break; case 'l': // length of hilight cmd.concatf( "%d", hiliteLen ); break; #if 0 case 'h': // helpid cmd.concat( x.stringAt( 5 ) ); break; case 'e': // error message cmd.concat( x.stringAt( 6 ) ); break; #endif case '%': // a real '%' cmd.concat( '%' ); break; default: // ignore the '%' and the character break; } i+=2; // skip % and following char default: cmd.concat( editorParms[i] ); break; } } WSystemService::sysExec( cmd, WWinStateShowNormal, 0 ); } } else { errMessage( "File \"%s\" not found", fileName ); } }
void ShadowMap::computeMatrices (const shared_ptr<Light>& light, AABox sceneBounds, CFrame& lightFrame, Projection& lightProjection, Matrix4& lightProjectionMatrix, float lightProjX, float lightProjY, float lightProjNearMin, float lightProjFarMax, float intensityCutoff) { if (! sceneBounds.isFinite() || sceneBounds.isEmpty()) { // Produce some reasonable bounds sceneBounds = AABox(Point3(-20, -20, -20), Point3(20, 20, 20)); } lightFrame = light->frame(); if (light->type() == Light::Type::DIRECTIONAL) { Point3 center = sceneBounds.center(); if (! center.isFinite()) { center = Point3::zero(); } // Move directional light away from the scene. It must be far enough to see all objects lightFrame.translation = -lightFrame.lookVector() * min(1e6f, max(sceneBounds.extent().length() / 2.0f, lightProjNearMin, 30.0f)) + center; } const CFrame& f = lightFrame; float lightProjNear = finf(); float lightProjFar = 0.0f; // TODO: for a spot light, only consider objects this light can see // Find nearest and farthest corners of the scene bounding box for (int c = 0; c < 8; ++c) { const Vector3& v = sceneBounds.corner(c); const float distance = -f.pointToObjectSpace(v).z; lightProjNear = min(lightProjNear, distance); lightProjFar = max(lightProjFar, distance); } // Don't let the near get too close to the source, and obey // the specified hint. lightProjNear = max(lightProjNearMin, lightProjNear); // Don't bother tracking shadows past the effective radius lightProjFar = min(light->effectSphere(intensityCutoff).radius, lightProjFar); lightProjFar = max(lightProjNear + 0.1f, min(lightProjFarMax, lightProjFar)); debugAssert(lightProjNear < lightProjFar); if (light->type() != Light::Type::DIRECTIONAL) { // TODO: Square spot // Spot light; we can set the lightProj bounds intelligently alwaysAssertM(light->spotHalfAngle() <= halfPi(), "Spot light with shadow map and greater than 180-degree bounds"); // The cutoff is half the angle of extent (See the Red Book, page 193) const float angle = light->spotHalfAngle(); lightProjX = tan(angle) * lightProjNear; // Symmetric in x and y lightProjY = lightProjX; lightProjectionMatrix = Matrix4::perspectiveProjection (-lightProjX, lightProjX, -lightProjY, lightProjY, lightProjNear, lightProjFar); } else if (light->type() == Light::Type::DIRECTIONAL) { // Directional light // Construct a projection and view matrix for the camera so we can // render the scene from the light's point of view // // Since we're working with a directional light, // we want to make the center of projection for the shadow map // be in the direction of the light but at a finite distance // to preserve z precision. lightProjectionMatrix = Matrix4::orthogonalProjection (-lightProjX, lightProjX, -lightProjY, lightProjY, lightProjNear, lightProjFar); } else { // Omni light. Nothing good can happen here, but at least we // generate something lightProjectionMatrix = Matrix4::perspectiveProjection (-lightProjX, lightProjX, -lightProjY, lightProjY, lightProjNear, lightProjFar); } float fov = atan2(lightProjX, lightProjNear) * 2.0f; lightProjection.setFieldOfView(fov, FOVDirection::HORIZONTAL); lightProjection.setNearPlaneZ(-lightProjNear); lightProjection.setFarPlaneZ(-lightProjFar); }
void PlayerEntity::slideMove(GameTime timeLeft) { static const float epsilon = 0.0001f; // Use constant velocity gravity (!) alwaysAssertM(((PhysicsScene*)m_scene)->gravity().x == 0.0f && ((PhysicsScene*)m_scene)->gravity().z == 0.0f, "We assume gravity points along the y axis to simplify implementation"); m_desiredOSVelocity.y = max( ((PhysicsScene*)m_scene)->gravity().y, m_desiredOSVelocity.y + ((PhysicsScene*)m_scene)->gravity().y); // Initial velocity Vector3 velocity = frame().vectorToWorldSpace(m_desiredOSVelocity) + ((PhysicsScene*)m_scene)->gravity(); Array<Tri> triArray; getConservativeCollisionTris(triArray, velocity, (float)timeLeft); // Trivial implementation that ignores collisions: # if 0 m_frame.translation += velocity * timeLeft; return; # endif // Keep simulating until we run out of time or velocity, at which point // no further movement is possible. # ifdef TRACE_COLLISIONS debugPrintf("================================\n"); debugPrintf("Initial velocity = %s; position = %s\n", velocity.toString().c_str(), m_frame.translation.toString().c_str()); # endif int iterations = 0; while ((timeLeft > epsilon) && (velocity.length() > epsilon)) { float stepTime = float(timeLeft); Vector3 collisionNormal; Point3 collisionPoint; const bool collided = findFirstCollision(triArray, velocity, stepTime, collisionNormal, collisionPoint); # ifdef TRACE_COLLISIONS debugPrintf(" stepTime = %f\n", stepTime); # endif // Advance to just before the collision stepTime = max(0.0f, stepTime - epsilon * 0.5f); m_frame.translation += velocity * stepTime; // Early out of loop when debugging //if (! runSimulation) { return; } if (collided) { # ifdef TRACE_COLLISIONS debugPrintf(" Collision C=%s, n=%s; position after=%s)\n", collisionPoint.toString().c_str(), collisionNormal.toString().c_str(), m_frame.translation.toString().c_str()); # endif if (collisionProxy().contains(collisionPoint)) { // Interpenetration. This is bad because the // rest of the code assumes no interpenetration and // uses that to rise up steps. Place the sphere // adjacent to the triangle and eliminate all velocity // towards the triangle. m_frame.translation = collisionPoint + collisionNormal * (m_collisionProxySphere.radius + epsilon * 2.0f); # ifdef TRACE_COLLISIONS debugPrintf(" Interpenetration detected. Position after = %s\n", m_frame.translation.toString().c_str()); # endif } // Constrain the velocity by subtracting the component // into the collision normal const Vector3& vPerp = collisionNormal * collisionNormal.dot(velocity); const Vector3& vPar = velocity - vPerp; # ifdef SHOW_COLLISIONS if (collisionNormal.y < 0.95f) { float duration = 1.0f; debugDraw(new ArrowShape(collisionPoint, velocity), duration, Color3::green()); debugDraw(new ArrowShape(collisionPoint, vPerp), duration, Color3::yellow()); debugDraw(new ArrowShape(collisionPoint, vPar), duration, Color3::blue()); if (duration == finf()) { // Pause so we can see the result runSimulation = false; } } # endif velocity = vPar; # ifdef TRACE_COLLISIONS debugPrintf(" velocity after collision = %s\n", velocity.toString().c_str()); # endif } # ifdef TRACE_COLLISIONS debugPrintf(" --------------\n"); # endif ++iterations; timeLeft -= stepTime; } //screenPrintf("%d collision iterations", iterations); }
bool imageViewer::openImage(QString &filename,QString start,bool ask,bool showMessage,bool emitSignal,bool fromCache) { QImage tempImage; QFile fi(filename); QFileInfo finf(filename); QString cacheFileName; jp2IO jp2; displayMBoxEvent *stmb=0; editorScene ed; bool success=false; bool cacheHit=false; if(activeMovie) { activeMovie=false; qm.stop(); } if (filename.isEmpty()&&!ask) return false; if(ask) { dirDialog dd((QWidget *)this,"Browse"); filename=dd.openFileName(start,"*"); } if(filename.isEmpty()) { imageFileName=""; return false; } if(fromCache) { cacheFileName=finf.absolutePath()+"/cache/"+finf.baseName()+finf.created().toString()+".png"; if(tempImage.load(cacheFileName)) { cacheHit=true; success=true; orgWidth=tempImage.text("orgWidth").toInt(); orgHeight=tempImage.text("orgHeight").toInt(); } } if(!success) { if(tempImage.load(filename)) { success=true; } else if(ed.load(fi)) { success=true; tempImage=QImage(ed.renderImage(0,0)->copy()); } else if(jp2.check(filename)) { tempImage=jp2.decode(filename); if(!tempImage.isNull()) { success=true; } } } if(!success) { if(showMessage) { stmb= new displayMBoxEvent("Image Loader",QString("Unable to load image:\n%1").arg(filename)); QApplication::postEvent( dispatcherPtr, stmb ); // Qt will delete it when done } validImage=false; imageFileName=""; return false; } if(fromCache) { sourceImage=QImage(); if(!cacheHit) { orgWidth=tempImage.width(); orgHeight=tempImage.height(); tempImage=tempImage.scaledToWidth(120, Qt::FastTransformation); // save cacheImage for next time tempImage.setText("orgWidth",QString::number(orgWidth)); tempImage.setText("orgHeight",QString::number(orgHeight)); tempImage.save(cacheFileName,"PNG"); } displayedImage=tempImage; } else { sourceImage=tempImage.convertToFormat(QImage::Format_ARGB32_Premultiplied); orgWidth=tempImage.width(); orgHeight=tempImage.height(); displayedImage=sourceImage; } imageFileName=filename; QFileInfo finfo(filename); if (finfo.suffix().toLower()=="gif") { //we will try a animated gif qm.setFileName(filename); if(qm.isValid()) { if(qm.frameCount()>1) { activeMovie=true; setMovie(&qm); qm.start(); displayedImage=QImage(); } else { displayImage(); // we have a single image gif } } } else { displayImage(); } validImage=true; if (emitSignal) emit imageChanged(); return true; }