// *** RecalcMousePos3d void UserInput::RecalcMousePos3d() { // Get click ray Vector3 rayStart; Vector3 rayDir; g_app->m_camera->GetClickRay( g_target->X(), g_target->Y(), &rayStart, &rayDir ); ASSERT_VECTOR3_IS_SANE(rayStart); ASSERT_VECTOR3_IS_SANE(rayDir); rayStart += rayDir * 0.0f; bool landscapeHit = false; if (g_app->m_location) { landscapeHit = g_app->m_location->m_landscape.RayHit( rayStart, rayDir, &m_mousePos3d ); } else { // We are in the global world // So hit against the outer sphere Vector3 sphereCentre(0,0,0); float sphereRadius = 36000.0f; rayStart += rayDir * (sphereRadius * 4.0f); rayDir = -rayDir; landscapeHit = RaySphereIntersection(rayStart, rayDir, sphereCentre, sphereRadius, 1e10, &m_mousePos3d); return; } if (!landscapeHit) { // OK, we didn't hit against the landscape mesh, so hit against a sphere that // encloses the whole world Vector3 sphereCentre; sphereCentre.x = g_app->m_globalWorld->GetSize() * 0.5f; sphereCentre.y = 0.0f; sphereCentre.z = g_app->m_globalWorld->GetSize() * 0.5f; float sphereRadius = g_app->m_globalWorld->GetSize() * 40.0f; float dist = (rayStart - sphereCentre).Mag(); //DarwiniaDebugAssert(dist < sphereRadius); rayStart += rayDir * (sphereRadius * 4.0f); rayDir = -rayDir; landscapeHit = RaySphereIntersection(rayStart, rayDir, sphereCentre, sphereRadius, 1e10, &m_mousePos3d); //DarwiniaDebugAssert(landscapeHit); } }
void Renderer::Render(SDL_Surface* surface) { Ray tracingRay; // Shoot ray from every pixel and compute its intersetion for(int i = 0; i < m_scene.GetImageWidth(); ++i) { for(int j = 0; j < m_scene.GetImageHeight(); ++j) { // Cast Ray tracingRay = RayThruPixel(i, j); Sphere sphere(0, 0, 0, 1); if(RaySphereIntersection(tracingRay, sphere)) { unsigned randColor = SDL_MapRGB(surface->format, 255, 0, 0); PutPixelColor(surface, i, j, randColor); } //unsigned randColor = SDL_MapRGB(surface->format, 255, rand() % 255, rand() % 255); //PutPixelColor(surface, i, j, randColor); } } }
bool Entity::RayHit(Vector3 const &_rayStart, Vector3 const &_rayDir) { if (m_shape) { RayPackage package(_rayStart, _rayDir); Matrix34 mat(m_front, g_upVector, m_pos); return m_shape->RayHit(&package, mat); } else { return RaySphereIntersection(_rayStart, _rayDir, m_pos, 5.0); } }
bool Building::DoesRayHit(Vector3 const &_rayStart, Vector3 const &_rayDir, float _rayLen, Vector3 *_pos, Vector3 *norm ) { if (m_shape) { RayPackage ray(_rayStart, _rayDir, _rayLen); Matrix34 transform(m_front, m_up, m_pos); return m_shape->RayHit(&ray, transform, true); } else { return RaySphereIntersection(_rayStart, _rayDir, m_pos, m_radius, _rayLen); } }
void GlobePicker::Eval() { FPoint3 pos, dir; vtGetScene()->CameraRay(m_pos, pos, dir); // test whether we hit the globe FSphere sphere(FPoint3(0.0f, 0.0f, 0.0f), (float)m_fRadius); FPoint3 akPoint[2]; int riQuantity; m_bOnTerrain = RaySphereIntersection(pos, dir, sphere, riQuantity, akPoint); if (m_bOnTerrain) { // save result m_GroundPoint = akPoint[0]; // apply global position to target (which is not a child of the globe) vtTransform *pTarget = (vtTransform *) GetTarget(); if (pTarget) { pTarget->Identity(); pTarget->SetTrans(m_GroundPoint); pTarget->PointTowards(m_GroundPoint * 2.0f); pTarget->Scale(m_fTargetScale); } if (m_pGlobe) { // rotate to find position relative to globe's rotation vtTransform *xform = m_pGlobe->GetTop(); FMatrix4 rot; xform->GetTransform1(rot); FMatrix4 inverse; inverse.Invert(rot); FPoint3 newpoint; // work around SML bug: matrices flagged as identity but // will still transform by their components if (! inverse.IsIdentity()) { inverse.Transform(m_GroundPoint, newpoint); m_GroundPoint = newpoint; } } // Find corresponding geographic coordinates xyz_to_geo(m_fRadius, m_GroundPoint, m_EarthPos); } }
// se c'e' intersezione con almeno un elemento ritorna TRUE e restituisce il numero, il tipo e il punto di intersezione // con la prima navicella che c'e' nella direzione della telecamera, altrimenti ritorna FALSE GLboolean firstShip(SpaceShip *spSh, int *nShip,char *typeShip,Point3 *intersection){ Point3 me=g_camera.getPos(), tmp; GLfloat dist, minDist=MAX_DIST+1000; GLboolean anyIntersection=false; for(int i=0;i<NUM_ENEMY;i++){ if ( enemy[i].life>0 && (spSh->type!='e' || spSh->index!=i) && // per non far il controllo con la navetta stessa RaySphereIntersection(spSh->pos,me,enemy[i].pos,enemy[i].rad+spSh->rad+0.1, &tmp)) { dist=distance(spSh->pos,tmp); if(dist<minDist){ anyIntersection=true; minDist=dist; *nShip=i; *typeShip='e'; *intersection=tmp; } } } for(int i=0;i<NUM_POLICE;i++){ if ( police[i].life>0 && (spSh->type!='p' || spSh->index!=i) && // per non far il controllo con la navetta stessa RaySphereIntersection(spSh->pos,me,police[i].pos,police[i].rad+spSh->rad+0.1, &tmp)) { dist=distance(spSh->pos,tmp); if(dist<minDist){ anyIntersection=true; minDist=dist; *nShip=i; *typeShip='p'; *intersection=tmp; } } } return anyIntersection; }
int LocationEditor::DoesRayHitCameraMount(Vector3 const &rayStart, Vector3 const &rayDir) { Shape *camShape = g_app->m_resource->GetShape("camera.shp"); Vector3 centre = camShape->CalculateCentre(g_identityMatrix34); float radius = camShape->CalculateRadius(g_identityMatrix34, centre); for (int i = 0; i < g_app->m_location->m_levelFile->m_cameraMounts.Size(); ++i) { CameraMount *mount = g_app->m_location->m_levelFile->m_cameraMounts[i]; if (RaySphereIntersection(rayStart, rayDir, mount->m_pos, radius)) { return i; } } return -1; }
int LocationEditor::DoesRayHitInstantUnit(Vector3 const &rayStart, Vector3 const &rayDir) { Location *location = g_app->m_location; for (int i = 0; i < location->m_levelFile->m_instantUnits.Size(); i++) { if (!location->m_levelFile->m_instantUnits.ValidIndex(i)) continue; InstantUnit *iu = location->m_levelFile->m_instantUnits.GetData(i); Vector3 pos(iu->m_posX, 0, iu->m_posZ); pos.y = location->m_landscape.m_heightMap->GetValue(pos.x, pos.z); bool result = RaySphereIntersection(rayStart, rayDir, pos, iv_sqrt(iu->m_number) * INSTANT_UNIT_SIZE_FACTOR); if (result) { return i; } } return -1; }
/* * FUNZIONE CHE DATO IL PUNTATORE ALLA POSIZIONE E ALLA DIREZIONE ATTUALI * SETTA LA NUOVA POSIZIONE E LA NUOVA DIREZIONE */ GLvoid setPosDir(SpaceShip *spSh){ me=g_camera.getPos(); dist=distance(spSh->pos,me); GLfloat rad=spSh->rad; if(dist>35){ //if(dist>10){ spSh->move=true; int i=checkDistPlanet(spSh->pos); int j=checkDistSatellite(spSh->pos); Point3 *tmp=(Point3 *) malloc(sizeof(Point3)); /* ALGORITMO CHE PERMETTE ALLE NAVETTE SPAZIALI DI EVITARE PIANETI, SATELLITI E ALTRE NAVETTE */ if( (i!=-1) && (j==-1) && RaySphereIntersection(spSh->pos,me,posPlanet[i],radius[i]+rad+rad*0.1,tmp) ) { // se stiamo andando addosso ad un pianeta ma non c'e' un satellite nelle vicinanze // troviamo il nuovo punto verso cui dirigerci per evitare il pianeta *tmp=addPos(*tmp, radius[i]+rad); spSh->dir=directionRel(spSh->pos,*tmp); spSh->dirCorr=false; // perche' non ci stiamo muovendo verso la telecamera } // se stiamo andando addosso ad un satellite ma non siamo ancora nelle vicinanze di un pianeta else if( (i==-1) && (j!=-1) && RaySphereIntersection(spSh->pos,me,satellite[j].pos,satellite[j].rad+rad+rad*0.1,tmp) ) { *tmp=addPos(*tmp, satellite[j].rad); spSh->dir=directionRel(spSh->pos,*tmp); spSh->dirCorr=false; // perche' non ci stiamo muovendo verso la telecamera } // se siamo nelle vicinanze sia di un satellite che di un pianeta e vi e' intesersezione con almeno uno dei due else if( (i!=-1) && (j!=-1) && ( RaySphereIntersection(spSh->pos,me,satellite[j].pos,satellite[j].rad+rad+rad*0.1,tmp) || RaySphereIntersection(spSh->pos,me,posPlanet[i],radius[i]+rad+rad*0.1,tmp)) ) { Point3 *tmpSat=(Point3 *) malloc(sizeof(Point3)); Point3 *tmpPl=(Point3 *) malloc(sizeof(Point3)); bool intersectionSat=RaySphereIntersection(spSh->pos,me,satellite[j].pos,satellite[j].rad+rad+rad*0.1,tmpSat); bool intersectionPl=RaySphereIntersection(spSh->pos,me,posPlanet[i],radius[i]+rad+rad*0.1,tmpPl); float distPl=distance(spSh->pos,*tmpPl); float distSat=distance(spSh->pos,*tmpSat); // se interseca solo il pianeta, o se gli interseca entrambi, ma prima il pianeta if( (intersectionPl && !intersectionSat) || ((intersectionPl && intersectionSat) && distPl<distSat) ) { *tmpPl=addPos(*tmpPl, radius[i]+rad); spSh->dir=directionRel(spSh->pos,*tmpPl); spSh->dirCorr=false; // perche' non ci stiamo muovendo verso la telecamera } // se interseca solo il satellite, o se gli interseca entrambi, ma prima il satellite else if(!intersectionPl && intersectionSat || ((intersectionPl && intersectionSat) && distSat<=distPl) ) { *tmpSat=addPos(*tmpSat, satellite[j].rad); //*tmpSat=addPos(*tmpSat, satellite[j].rad+rad); spSh->dir=directionRel(spSh->pos,*tmpSat); spSh->dirCorr=false; // perche' non ci stiamo muovendo verso la telecamera } free(tmpPl); free(tmpSat); } else // se non c'e' rischio collisione ne con un satellite ne con un pianeta { // le variabili di tipo clock servono per non far "impazzire" il cambio di direzione delle navicelle //quando abbengono rapidi cambiamenti di posizione della telecamera int num; char type; Point3 intShip; GLboolean collision=firstShip(spSh,&num,&type,&intShip); // restituisce se esiste il numero e il tipo della prima navicella che c'e' nella direzione verso la telecamera if(collision && abs(clock()-pastClock)>=CLOCKS_PER_SEC*0.3) { // si controlla se c'e' un altra navetta sulla traiettoria pastClock=clock(); GLboolean mv; switch(type){ case 'p': mv=police[num].move; break; case 'e': mv=enemy[num].move; break; } // si settano queste variabili in modo che si mantenga la stessa direzione // finche' continua ad esserci insersezione con la stessa navetta if(!mv && type!=oldType && num!=oldNum) { // si trova la nuova direzione per evitarla oldType=type; oldNum=num; switch(type){ case 'p': *tmp=addPos(intShip, (spSh->rad+police[num].rad)); break; case 'e': *tmp=addPos(intShip, (spSh->rad+enemy[num].rad)); break; } spSh->dir= directionRel(spSh->pos,*tmp); spSh->dirCorr=false; } //else if(mv && abs(clock()-pastClock)>=CLOCKS_PER_SEC*0.3) else if(mv) { oldType=' '; oldNum=-1; switch(type){ case 'p': *tmp=addPos(intShip, (spSh->rad+police[num].rad)); break; case 'e': *tmp=addPos(intShip, (spSh->rad+enemy[num].rad)); break; } spSh->dir= directionRel(spSh->pos,*tmp); spSh->dirCorr=false; } } // se non ci sono ostacoli else if(!collision && abs(clock()-pastClock)>=CLOCKS_PER_SEC*0.3) //else { pastClock=clock(); oldType=' '; oldNum=-1; spSh->dir=directionRel(spSh->pos,me); // si aggiorna nella direzione tra oggetto e me spSh->dirCorr=true; // perche' ci stiamo muovendo verso la telecamera } } // ora che abbiamo trovato la direzione di movimento, muoviamo la navicella if (!freezeShip){ spSh->pos.x += spSh->dir.x*sp; spSh->pos.y += spSh->dir.y*sp; spSh->pos.z += spSh->dir.z*sp; glutPostRedisplay(); } free(tmp); } // se non ci si deve muovere, la direzione deve essere sempre rivolta verso la telecamera else if (!freezeShip){ spSh->move=false; spSh->dir=directionRel(spSh->pos,me); // si aggiorna nella direzione tra oggetto e me spSh->dirCorr=true; // perche' ci stiamo muovendo verso la telecamera } }
bool ResearchItem::DoesRayHit(Vector3 const &_rayStart, Vector3 const &_rayDir, double _rayLen, Vector3 *_pos, Vector3 *norm ) { return RaySphereIntersection(_rayStart, _rayDir, m_pos, m_radius, _rayLen); }