bool Obj::GroundCheck(IN OUT D3DXVECTOR3& groundPos) const { bool find = false; D3DXVECTOR3 rayStart(groundPos.x, 1000.0f, groundPos.z); D3DXVECTOR3 rayDirection(0, -1, 0); for (size_t i = 0; i < objGround.size(); i += 3) { float u, v, distance; find = D3DXIntersectTri( &objGround[i], &objGround[i + 1], &objGround[i + 2], &rayStart, &rayDirection, &u, &v, &distance) != 0; if (find == true) { groundPos.y = 1000.0f - distance; //groundPos = objGround[i] + ( ( objGround[i + 1] - objGround[i] ) * u ) + ( ( objGround[i + 2] - objGround[i] ) * v ); break; } } return find; }
virtual void renderScene(Scene* scene, RenderTarget* target, RayTracer* tracer) { RGBColor pixelColor; Ray ray; int recursionDepth = 0; Point2d samplePointUnit, samplePointPixel; float pixelSize = target->getPixelSize() / mZoom; ray.origin = mEyePosition; for(int r = 0; r < target->getHeight(); ++r) { for(int c = 0; c < target->getWidth(); ++c) { pixelColor = RGBColor(); for(int numSample = 0; numSample < mSampler->getSampleNumber(); ++numSample) { samplePointUnit = mSampler->getNextUnitSquareSample(); samplePointPixel.x = pixelSize * (c - 0.5 * target->getWidth() + samplePointUnit.x); samplePointPixel.y = pixelSize * (r - 0.5 * target->getHeight() + samplePointUnit.y); ray.direction = rayDirection(samplePointPixel); pixelColor += tracer->traceRay(&ray, scene); } pixelColor /= mSampler->getSampleNumber(); pixelColor *= mExposureTime; target->drawPixel(c, r, pixelColor); } } }
/* * This is our ray / bolt collision routine for now. * Basically, this is called on a ship unit to see if any ray or bolt given by some simple vectors collide with it * We should probably first check against shields and then against the colTree to see if we hit the shields first * Not sure yet if that would work though... more importantly, we might have to modify end in here in order * to tell calling code that the bolt should stop at a given point. */ Unit* Unit::rayCollide( const QVector &start, const QVector &end, Vector &norm, float &distance) { Unit *tmp; float rad = this->rSize(); if ( ( !SubUnits.empty() ) && graphicOptions.RecurseIntoSubUnitsOnCollision ) if ( ( tmp = *SubUnits.fastIterator() ) ) rad += tmp->rSize(); if ( !globQuerySphere( start, end, cumulative_transformation_matrix.p, rad ) ) return NULL; if (graphicOptions.RecurseIntoSubUnitsOnCollision) { if ( !SubUnits.empty() ) { un_fiter i( SubUnits.fastIterator() ); for (Unit *un; (un = *i); ++i) if ( ( tmp = un->rayCollide( start, end, norm, distance) ) != 0 ) return tmp; } } QVector st( InvTransform( cumulative_transformation_matrix, start ) ); QVector ed( InvTransform( cumulative_transformation_matrix, end ) ); static bool sphere_test = XMLSupport::parse_bool( vs_config->getVariable( "physics", "sphere_collision", "true" ) ); distance = querySphereNoRecurse( start, end ); if (distance > 0.0f || (this->colTrees&&this->colTrees->colTree( this, this->GetWarpVelocity() )&&!sphere_test)) { Vector coord; /* Set up points and ray to send to ray collider. */ Opcode::Point rayOrigin(st.i,st.j,st.k); Opcode::Point rayDirection(ed.i,ed.j,ed.k); Opcode::Ray boltbeam(rayOrigin,rayDirection); if(this->colTrees){ // Retrieve the correct scale'd collider from the unit's collide tree. csOPCODECollider *tmpCol = this->colTrees->colTree( this, this->GetWarpVelocity() ); QVector del(end-start); //Normalize(del); norm = ((start+del*distance)-Position()).Cast(); Normalize(norm); //RAY COLLIDE does not yet set normal, use that of the sphere center to current loc if (tmpCol==NULL) { return this; } if(tmpCol->rayCollide(boltbeam,norm,distance)){ // compute real distance distance = (end-start).Magnitude() * distance; // NOTE: Here is where we need to retrieve the point on the ray that we collided with the mesh, and set it to end, create the normal and set distance VSFileSystem::vs_dprintf(3,"Beam collide with %p, distance %f\n",this,distance); return(this); } } else {//no col trees = a sphere // compute real distance distance = (end-start).Magnitude() * distance; VSFileSystem::vs_dprintf(3,"Beam collide with %p, distance %f\n",this,distance); return(this); } } else { return (NULL); } return(NULL); }
bool HeightMap::OnTheGround(D3DXVECTOR3& pos, const D3DXVECTOR3& p0, const D3DXVECTOR3& p1, const D3DXVECTOR3& p2) { bool find = false; D3DXVECTOR3 rayStart(pos.x, 1000.0f, pos.z); D3DXVECTOR3 rayDirection(0, -1, 0); float u, v, distance; find = D3DXIntersectTri( &p0, &p1, &p2, &rayStart, &rayDirection, &u, &v, &distance) != 0; if (find == true) { pos.y = 1000.0f - distance; //pos = p0 + (p1 - p0) * u + (p2 - p0) * v; } return find; }
void Player::Raycast(const GameContext& gameContext) { GameScene* scene = GetScene(); XMFLOAT3 pos = GetTransform()->GetPosition(); XMFLOAT3 fw = GetTransform()->GetForward(); PxVec3 rayOrigin(pos.x,pos.y + 1.f,pos.z), rayDirection(fw.x,fw.y,fw.z); rayOrigin.x += fw.x * 2.5f; rayOrigin.z += fw.z * 2.5f; const PxU32 bufSize = 20; PxRaycastHit hit[bufSize]; PxRaycastBuffer buf(hit, bufSize); // [out] Blocking and touching hits will be stored here if(scene->GetPhysxProxy()->Raycast(rayOrigin, rayDirection, 5000, buf)) { for(PxU32 i = 0; i < buf.nbTouches; ++i) { BaseComponent* component = static_cast<BaseComponent*>(buf.touches[i].actor->userData); GameObject* go = component->GetGameObject(); string name = go->GetName(); cout << "RAYCAST OBJECT: " << name << endl; if(name == "Enemy") { Enemy* enemy = reinterpret_cast<Enemy*>(go); int dmg = 12.5f; enemy->Damage(dmg); } } PxVec3 vel = rayDirection * 1000; auto laser = new Laser(XMFLOAT3(vel.x, vel.y, vel.z)); AddChild(laser); } }
int FFDDistanceGridDiscreteIntersection::computeIntersection(Ray& e2, FFDDistanceGridCollisionElement& e1, OutputVector* contacts) { Vector3 rayOrigin(e2.origin()); Vector3 rayDirection(e2.direction()); const double rayLength = e2.l(); DistanceGrid* grid1 = e1.getGrid(); FFDDistanceGridCollisionModel::DeformedCube& c1 = e1.getCollisionModel()->getDeformCube(e1.getIndex()); // Center of the sphere const Vector3 center1 = c1.center; // Radius of the sphere const double radius1 = c1.radius; const Vector3 tmp = center1 - rayOrigin; double rayPos = tmp*rayDirection; const double dist2 = tmp.norm2() - (rayPos*rayPos); if (dist2 >= (radius1*radius1)) return 0; double l0 = rayPos - sqrt(radius1*radius1 - dist2); double l1 = rayPos + sqrt(radius1*radius1 - dist2); if (l0 < 0) l0 = 0; if (l1 > rayLength) l1 = rayLength; if (l0 > l1) return 0; // outside of ray //const double dist = sqrt(dist2); //double epsilon = grid1->getCellWidth().norm()*0.1f; c1.updateFaces(); DistanceGrid::Coord p1; const SReal cubesize = c1.invDP.norm(); for(int i=0; i<100; i++) { rayPos = l0 + (l1-l0)*(i*0.01); p1 = rayOrigin + rayDirection*rayPos; // estimate the barycentric coordinates DistanceGrid::Coord b = c1.undeform0(p1); // refine the estimate until we are very close to the p2 or we are sure p2 cannot intersect with the object int iter; //SReal err1 = 1000.0f; bool found = false; for(iter=0; iter<5; ++iter) { DistanceGrid::Coord pdeform = c1.deform(b); DistanceGrid::Coord diff = p1-pdeform; SReal err = diff.norm(); //if (iter>3) // sout << "Iter"<<iter<<": "<<err1<<" -> "<<err<<" b = "<<b<<" diff = "<<diff<<" d = "<<grid1->interp(c1.initpos(b))<<""<<sendl; SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f; if (b[0] < -berr || b[0] > 1+berr || b[1] < -berr || b[1] > 1+berr || b[2] < -berr || b[2] > 1+berr) break; // far from the cube if (err < 0.001f) { // we found the corresponding point, but is is only valid if inside the current cube if (b[0] > -0.1f && b[0] < 1.1f && b[1] > -0.1f && b[1] < 1.1f && b[2] > -0.1f && b[2] < 1.1f) { found = true; } break; } //err1 = err; b += c1.undeformDir( b, diff ); } if (found) { SReal d = grid1->interp(c1.initpos(b)); if (d < 0) { // intersection found contacts->resize(contacts->size()+1); DetectionOutput *detection = &*(contacts->end()-1); detection->point[0] = e2.origin() + e2.direction()*rayPos; detection->point[1] = c1.initpos(b); detection->normal = e2.direction(); // normal in global space from p1's surface detection->value = d; detection->elem.first = e2; detection->elem.second = e1; detection->id = e2.getIndex(); return 1; } } // else move along the ray //if (dot(Vector3(grid1->grad(c1.initpos(b))),rayDirection) < 0) // rayPos += 0.5*d; //else // rayPos -= 0.5*d; } return 0; }
void Mesh::generateHeightmap(const char* filename) { // Shoot rays down from a point just above the max Y position of the mesh. // Compute ray-triangle intersection tests against the ray and this mesh to // generate heightmap data. Vector3 rayOrigin(0, bounds.max.y + 10, 0); Vector3 rayDirection(0, -1, 0); Vector3 intersectionPoint; int minX = (int)ceil(bounds.min.x); int maxX = (int)floor(bounds.max.x); int minZ = (int)ceil(bounds.min.z); int maxZ = (int)floor(bounds.max.z); int width = maxX - minX + 1; int height = maxZ - minZ + 1; float* heights = new float[width * height]; int index = 0; float minHeight = FLT_MAX; float maxHeight = FLT_MIN; for (int z = minZ; z <= maxZ; z++) { rayOrigin.z = (float)z; for (int x = minX; x <= maxX; x++) { float h; rayOrigin.x = (float)x; if (intersect(rayOrigin, rayDirection, vertices, parts, &intersectionPoint)) { h = intersectionPoint.y; } else { h = 0; fprintf(stderr, "Warning: Heightmap triangle intersection failed for (%d, %d).\n", x, z); } if (h < minHeight) minHeight = h; if (h > maxHeight) maxHeight = h; heights[index++] = h; } } // Normalize the max height value maxHeight = maxHeight - minHeight; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep row = NULL; FILE* fp = fopen(filename, "wb"); if (fp == NULL) { fprintf(stderr, "Error: Failed to open file for writing: %s\n", filename); goto error; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "Error: Write struct creation failed: %s\n", filename); goto error; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "Error: Info struct creation failed: %s\n", filename); goto error; } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); // Allocate memory for a single row of image data row = (png_bytep)malloc(3 * width * sizeof(png_byte)); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Write height value normalized between 0-255 (between min and max height) float h = heights[y*width + x]; float nh = (h - minHeight) / maxHeight; png_byte b = (png_byte)(nh * 255.0f); int pos = x*3; row[pos] = row[pos+1] = row[pos+2] = b; } png_write_row(png_ptr, row); } png_write_end(png_ptr, NULL); DEBUGPRINT_VARG("> Saved heightmap: %s\n", filename); error: if (heights) delete[] heights; if (fp) fclose(fp); if (row) free(row); if (info_ptr) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); if (png_ptr) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); }
Ray PinholeCamera::getRayTo(Vector2 location) { return Ray(origin, rayDirection(location)); }