TriangleNode* CollisionManager::getTriangle(const Vector3& point, FloorMesh* floor) { /*PathGraph* graph = node->getPathGraph(); FloorMesh* floor = graph->getFloorMesh();*/ AABBTree* aabbTree = floor->getAABBTree(); //Vector3 nodePosition = node->getPosition(); Vector3 rayOrigin(point.getX(), point.getZ() + 0.5, point.getY()); //Vector3 rayOrigin(point.getX(), point.getY(), point.getZ() + 0.2); Vector3 direction(0, -1, 0); Ray ray(rayOrigin, direction); float intersectionDistance = 0; Triangle* triangle = NULL; aabbTree->intersects(ray, 4, intersectionDistance, triangle, true); TriangleNode* triangleNode = dynamic_cast<TriangleNode*>(triangle); if (triangleNode == NULL) { //System::out << "CollisionManager::getTriangle triangleNode NULL" << endl; return floor->findNearestTriangle(rayOrigin); } return triangleNode; }
/* * 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); }
void rayFactory(std::vector<Ray*> &rays, Camera &c, ViewPlane &v) { c.calcUVW(); //Used for calculating Simple Perspective Camera if (c.distance > 0.0) { for (double i = ((v.height/2)-(v.pixelsize/2)); i >= (((v.height/2) * -1)); i -= v.pixelsize) { for (double j = (((v.width/2) * -1)+(v.pixelsize/2)); j <=((v.width/2)); j += v.pixelsize) { Vec3 rayOrigin(c.center); Vec3 direction = (j * c.u + i *c.v) - c.distance * c.w; direction.normalize(); Ray *addRay = new Ray(rayOrigin, direction); rays.push_back(addRay); } } } //Used for calculating Perspective Camera if (c.angle > 0.0) { c.distance =(v.width/2.0)/(sin(DEG2RAD(c.angle)))/cos((DEG2RAD(c.angle))); for (double i = ((v.height/2)-(v.pixelsize/2)); i >= (((v.height/2) * -1)); i -= v.pixelsize) { for (double j = (((v.width/2) * -1)+(v.pixelsize/2)); j <=((v.width/2)); j += v.pixelsize) { Vec3 rayOrigin(c.center); Vec3 direction = (j * c.u + i *c.v) - c.distance * c.w; direction.normalize(); Ray *addRay = new Ray(rayOrigin, direction); rays.push_back(addRay); } } } //Used for calculating Orthographic Camera if (c.angle == 0.0 && c.distance == 0.0) { for (double i = ((v.height/2)-(v.pixelsize/2)); i >= (((v.height/2) * -1)); i -= v.pixelsize) { for (double j = (((v.width/2) * -1)+(v.pixelsize/2)); j <=((v.width/2)); j += v.pixelsize) { Vec3 rayOrigin(j,i, c.center.z()); Ray *addRay = new Ray(rayOrigin, c.direction); rays.push_back(addRay); } } } }
static Eigen::Vector3d mapToSphere( Eigen::Matrix4d invProjMatrix, Eigen::Vector2d const p, Eigen::Vector3d viewSphereCenter, double viewSpaceRadius) { Eigen::Vector4d viewP = invProjMatrix * Eigen::Vector4d(p(0), p(1), -1.0, 1.0); //viewP(0) /= viewP(3); //viewP(1) /= viewP(3); //viewP(2) /= viewP(3); Eigen::Vector3d rayOrigin(0.0, 0.0, 0.0); Eigen::Vector3d rayDir(viewP(0), viewP(1), viewP(2)); rayDir.normalize(); Eigen::Vector3d CO = rayOrigin - viewSphereCenter; double a = 1.0; double bPrime = CO.dot(rayDir); double c = CO.dot(CO) - viewSpaceRadius * viewSpaceRadius; double delta = bPrime * bPrime - a * c; if (delta < 0.0) { double t = -CO.z() / rayDir.z(); Eigen::Vector3d point = rayOrigin + t * rayDir; Eigen::Vector3d dir = point - viewSphereCenter; dir.normalize(); return viewSphereCenter + dir * viewSpaceRadius; } double root[2] = { (-bPrime - sqrt(delta)) / a, (-bPrime + sqrt(delta)) / a }; if (root[0] >= 0.0) { Eigen::Vector3d intersectionPoint = rayOrigin + root[0] * rayDir; return intersectionPoint; } else if (root[1] >= 0.0) { Eigen::Vector3d intersectionPoint = rayOrigin + root[1] * rayDir; return intersectionPoint; } else { double t = -CO.z() / rayDir.z(); Eigen::Vector3d point = rayOrigin + t * rayDir; Eigen::Vector3d dir = point - viewSphereCenter; dir.normalize(); return viewSphereCenter + dir * viewSpaceRadius; } }
void SimpleVolumeRenderer::draw() { float t = GLFWTime::getCurrentTime(); Camera& c = RenderManager::getInstance().getMainCamera(); mat4 p = c.getProjection(); mat4 mv = c.getModelview(); vec3 eyePos = c.getEyePosition() + _eyeOffset; float fov = c.getFieldOfView(); float s = 2.0f; mat4 xform = glm::scale(vec3(s, s, s)); mv = mv * xform; eyePos = vec3(glm::inverse(mv) * vec4(eyePos, 1.0f)); mv = mv * glm::rotate(GLFWTime::getCurrentTime()*0.5f, vec3(0, 1, 0)); GLUtil::clear(true, true, false); GLUtil::setDepthTest(false); GLUtil::cullBackFaces(); GLUtil::cullOn(); GLUtil::setBlend(true); GLUtil::setBlendFuncToComposite(); _shader->bind(); _shader->setUniform("ModelviewProjection", p*mv); _shader->setUniform("Modelview", mv); _shader->setUniform("ViewMatrix", mv); _shader->setUniform("ProjectionMatrix", p); _shader->setUniform("RayStartPoints", 1); _shader->setUniform("RayStopPoints", 2); _shader->setUniform("EyePosition", eyePos); vec4 rayOrigin(glm::transpose(mv) * vec4(eyePos,1)); _shader->setUniform("RayOrigin", vec3(rayOrigin)); float focalLength = 1.0f / tan(fov / 2); _shader->setUniform("FocalLength", focalLength); _shader->setUniform("WindowSize", _screenDim.x, _screenDim.y); _mesh->drawBuffers(); _shader->unbind(); }
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); } }
// ray-sphere intersection test from Graphics Gems p.388 // **NOTE** There is a bug in this Graphics Gem. If the origin // of the ray is *inside* the sphere being tested, it reports the // wrong intersection location. This code has a fix for the bug. bool SBM_rayIntersectsSphere(const float *point,const float *direction,const float *_center,float radius,float &t) { bool ret = false; NxVec3 rayOrigin(point); NxVec3 dir(direction); NxVec3 center(_center); // notation: // point E = rayOrigin // point O = sphere center NxVec3 EO = center - rayOrigin; NxVec3 V = dir; float dist2 = EO.x*EO.x + EO.y*EO.y + EO.z * EO.z; float r2 = radius*radius; // Bug Fix For Gem, if origin is *inside* the sphere, invert the // direction vector so that we get a valid intersection location. if ( dist2 < r2 ) V*=-1; float v = EO.dot(V); float disc = r2 - (EO.magnitudeSquared() - v*v); if (disc > 0.0f) { t = sqrtf(disc); ret = true; } return ret; }
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); }
int generateHeightmapChunk(void* threadData) { HeightmapThreadData* data = (HeightmapThreadData*)threadData; Vector3 rayOrigin(0, data->rayHeight, 0); const Vector3& rayDirection = *data->rayDirection; const std::vector<Mesh*>& meshes = *data->meshes; float* heights = data->heights; Vector3 intersectionPoint; float minHeight = FLT_MAX; float maxHeight = -FLT_MAX; int index = data->heightIndex; int zi = 0; for (float z = data->minZ; zi < data->height; z += data->stepZ, ++zi) { LOG(1, "\r\t%d%%", (int)(((float)__processedHeightmapScanLines / __totalHeightmapScanlines) * 100.0f)); rayOrigin.z = z; int xi = 0; for (float x = data->minX; xi < data->width; x += data->stepX, ++xi) { float h = -FLT_MAX; rayOrigin.x = x; for (unsigned int i = 0, count = meshes.size(); i < count; ++i) { // Pick the highest intersecting Y value of all meshes Mesh* mesh = meshes[i]; // Perform a quick ray/bounding box test to quick-out if (!intersect(rayOrigin, rayDirection, mesh->bounds.min, mesh->bounds.max)) continue; // Compute the intersection point of ray with mesh if (intersect(rayOrigin, rayDirection, mesh->vertices, mesh->parts, &intersectionPoint)) { if (intersectionPoint.y > h) { h = intersectionPoint.y; // Update min/max height values if (h < minHeight) minHeight = h; if (h > maxHeight) maxHeight = h; } } } // Update the glboal height array heights[index++] = h; if (h == -FLT_MAX) ++__failedRayCasts; } ++__processedHeightmapScanLines; } // Update min/max height for this thread data data->minHeight = minHeight; data->maxHeight = maxHeight; return 0; }
//-------------------------------------------------------------------------------- void CObjCHAR_Collision::GetCollisionStateAvatar ( void ) //-------------------------------------------------------------------------------- { CollisionSphere * sp; HNODE hNode; const float MAX_DISTANCE_SQUARE = 2000.0f*2000.0f; D3DXVECTOR3 prevCenter, closestCenter; float distance_ , distanceLimit, distanceLimitBody; D3DXVECTOR3 DIRECTION_DOWN(0, 0, -1) ,DIRECTION_MOVE; D3DXVECTOR3 rayOrigin(m_vFoot.x,m_vFoot.y, 1.8f*(75.0f)+m_vFoot.z) ; D3DXVECTOR3 rayOriginBody(m_vPrevious.x, m_vPrevious.y,m_vPrevious.z+1.5f*(75.0f)); bool BodyRay = false; bool SphereResetOnOff = false; distanceLimit =1.8f*(75.0f); DIRECTION_MOVE = m_vFoot - m_vPrevious; distanceLimitBody = D3DXVec3Length(&DIRECTION_MOVE); if(distanceLimitBody >0.001f) { DIRECTION_MOVE /= distanceLimitBody; BodyRay = true; } bool isFalling = (m_vVelocity.x == 0) && (m_vVelocity.y == 0); // not moving forward if(isFalling == true) isFalling = true; m_State = CollisionState::CS_NONE; for (std::vector<CollisionSphere>::iterator it = m_Spheres.begin(); it != m_Spheres.end(); ++it) { sp = &(*it); prevCenter = sp->center - m_vVelocity; if(sp->state == CollisionState::CS_FOOT_FRONT && SphereResetOnOff) sp->center.z = m_vFoot.z; for (std::vector<HNODE>::iterator itnode = m_ContactNodes.begin(); itnode != m_ContactNodes.end(); ++itnode) { hNode = (*itnode); if (sp->state == CollisionState::CS_BODY_FRONT) { if (isFalling) continue; if (::intersectNodeTriSphere( hNode, sp->center,sp->radius)) { if (getHeightCollisionLevelOnOff(hNode)) { SphereResetOnOff = CollisionResponseBodyHeight(hNode); continue; } if(m_hCollisionBlockNode != NULL) { CollisionResponseBody_Avatar(); break; } else { sp->collided.push_back( hNode ); m_State = CollisionState::CS_BODY_FRONT; LogString(LOG_DEBUG, "CS_BODY_FRONT\n"); return; } } if(BodyRay) { distance_ = ::shootRayVec3( hNode, 1 /* nearest */, rayOriginBody, DIRECTION_MOVE ); if(distance_ < distanceLimitBody) { if (getHeightCollisionLevelOnOff(hNode)) { SphereResetOnOff = CollisionResponseBodyHeight(hNode); continue; } if(m_hCollisionBlockNode != NULL) { CollisionResponseBody_Avatar(); break; } else { sp->collided.push_back( hNode ); m_State = CollisionState::CS_BODY_FRONT; LogString(LOG_DEBUG, "CS_BODY_FRONT\n"); return; } } } } else if (sp->state == CollisionState::CS_FOOT_FRONT) { if (::intersectNodeTriSphere( hNode, sp->center,sp->radius)) { if (getHeightCollisionLevelOnOff(hNode)) { SphereResetOnOff = CollisionResponseBodyHeight(hNode); continue; } if(m_hCollisionBlockNode != NULL) { CollisionResponseBody_Avatar(); break; } else { sp->collided.push_back( hNode ); m_State = CollisionState::CS_BODY_FRONT; LogString(LOG_DEBUG, "CS_BODY_FRONT\n"); return; } } } else if (sp->state == CollisionState::CS_FOOT) { sp->collided.push_back( hNode ); if (isFalling && ::intersectNodeTriSphere( hNode, sp->center,sp->radius)) { m_State = CollisionState::CS_FOOT; if (getHeightCollisionLevelOnOff(hNode)) m_footCollisionPass = true; } else if (::intersectNodeTriSphere( hNode, sp->center, sp->radius )) { m_State = CollisionState::CS_FOOT; if (getHeightCollisionLevelOnOff(hNode)) m_footCollisionPass = true; } else{ distance_ = ::shootRayVec3( hNode, 1 /* nearest */, rayOrigin, DIRECTION_DOWN ); if(distance_ < distanceLimit) { m_State = CollisionState::CS_FOOT; if (getHeightCollisionLevelOnOff(hNode)) m_footCollisionPass = true; } } continue; } else { LogString( LOG_DEBUG, "error: Cannot reach here. CObjCHAR_Collision.cpp" ); // cannot reach here } } } }