bool Terrain::intersectAdvanced(const Ray &ray, const Vector3D &aBox, const Vector3D &bBox,double pMax, Vector3D &resu, bool& isBox) const { double step=pas; isBox=false; resu=ray.getOrigine(); Vector3D in; Vector3D out; int pointsBox = ray.intersectsBox(aBox, bBox, in, out); if(pointsBox == 0) { return false; } double distInOut = in.distanceToPoint(out); Vector3D dir=ray.getDirection(); Ray r(in,dir); for(double tt = 0; tt <= distInOut+pas; tt+= step) { Vector3D pointTemp=r.getPoint(tt); double dz=pointTemp.y()-getHauteur(Vector2D(pointTemp.x(),pointTemp.z())); if(dz<=0){ resu=r.getPoint(tt-pas/2); if(tt==0){ isBox=true; } return true; } step=max(pas,dz/pMax); } return false; }
bool Terrain::inOut(const vec3& pointXYZ) const { if(pointXYZ.z < 0) return false; float h = getHauteur(pointXYZ.x, pointXYZ.y); return h != HAUTEUR_HORS_MAP && pointXYZ.z <= h; // }
float Terrain::distance(const glm::vec3& p) const { float dist = box.distance(p); if(dist > 0) return dist+0.1f; //on essaye de rentrer dans la box else return (p.z-getHauteur(p))*0.3f; }
void EntiteBase::effacer(){ for(int ligne=positionLigne; ligne<positionLigne+getHauteur(); ligne++){ for(int colonne=positionColonne; colonne<positionColonne+getLargeur(); colonne++){ if(ligne>=0 && ligne<=25 && colonne>=0 && colonne<=80) espace->setEntiteVide(ligne, colonne); } } }
Vector3D Terrain::norm(const Vector2D &p) const { Vector2D px(p.x()+epsilon,p.y()); Vector2D pxminus(p.x()-epsilon, p.y()); Vector2D py(p.x(),p.y()+epsilon); Vector2D pyminus(p.x(),p.y()-epsilon); double hpx=getHauteur(px); double hpxminus = getHauteur(pxminus); double hpy=getHauteur(py); double hpyminus = getHauteur(pyminus); Vector3D resu(-(hpx-hpxminus),2*epsilon,-(hpy-hpyminus)); resu.normalize(); return resu; }
void EntiteBase::dessiner(){ for(int ligne=getPositionLigne(); ligne<getPositionLigne()+getHauteur(); ligne++){ for(int colonne=getPositionColonne(); colonne<getPositionColonne()+getLargeur(); colonne++){ espace->setEntite(this, ligne, colonne); ecran->afficherCaractere(ligne, colonne, couleur, espace->getCouleurArPlanAt(ligne, colonne), *(affichage + (ligne-positionLigne)*largeur +(colonne-positionColonne))); } } }
Vector3D Terrain::norm(const Vector2D &p) { /* Vector2D px(p.x()+epsilon,p.y()); Vector2D py(p.x(),p.y()+epsilon); double hp=getHauteur(p); double hpx=getHauteur(px); double hpy=getHauteur(py); Vector3D vp(p.x(),p.y(),(double)hp); Vector3D vpx(px.x(),px.y(),(double)hpx); Vector3D vpy(py.x(),py.y(),(double)hpy); Vector3D u=vpx-vp; Vector3D v=vpy-vp; Vector3D n(-u.z()/u.x(),1.0f,-v.z()/v.y()); n.normalize(); return n;*/ //std::cout<<p.x()<<" "<<p.x()+epsilon<<std::endl; Vector2D px(p.x()+epsilon,p.y()); Vector2D pxminus(p.x()-epsilon, p.y()); Vector2D py(p.x(),p.y()+epsilon); Vector2D pyminus(p.x(),p.y()-epsilon); double hpx=getHauteur(px); double hpxminus = getHauteur(pxminus); double hpy=getHauteur(py); double hpyminus = getHauteur(pyminus); //std::cout<<hpx<<" "<<hpxminus<<std::endl; Vector3D resu(-(hpx-hpxminus),2*epsilon,-(hpy-hpyminus)); resu.normalize(); return resu; }
void Terrain::getColor(float& r, float& g, float& b, float x, float y) const { float hauteur = getHauteur(x,y); hauteur /= box.diffZ(); vec3 normale = getNormal(x,y); float pente = 1-dot(normale, vec3(0,0,1)); float roche = 3 + NoiseGenerator::perlinNoiseGradiant2(x, y, 1000) + NoiseGenerator::perlinNoiseGradiant2(x+30, y-60, 103) + NoiseGenerator::perlinNoiseGradiant2(x,y, 3); roche *= 0.25f+pente*0.75f; roche *= 0.3f; float herbe = 3 + NoiseGenerator::perlinNoiseGradiant2(x+10100, y+10100, 1234) + NoiseGenerator::perlinNoiseGradiant2(x-100,y-50, 123) + NoiseGenerator::perlinNoiseGradiant2(x-1, y-30,2); herbe *= 0.25f+(1-hauteur)*(1-hauteur)*0.75f; herbe *= 0.25f; float neige = 3 + NoiseGenerator::perlinNoiseGradiant2(x+555, y+1010, 1324) + NoiseGenerator::perlinNoiseGradiant2(x-200,y-54, 223) + NoiseGenerator::perlinNoiseGradiant2(x-10, y+12,0.5); neige *= 0.1f+hauteur*hauteur*0.9f; neige *= 0.25f; /*float sr = roche*1/0.39f+neige, sg = roche*1/0.36f+herbe+neige, sb = roche*1/0.29f+neige;*/ /* r = (roche*0.39f+neige)/sr; g = (roche*0.36f+herbe+neige)/sg; b = (roche*0.29f+neige)/sb; */ if(herbe > roche && herbe > neige) { if(herbe > 1) herbe = 1; r = 0; g = herbe; b = 0; } else if(roche > herbe && roche > neige) { if(roche > 1) roche = 1; r = roche*0.36f; g = roche*0.24f; b = roche*0.07f; } else { if(neige > 1) neige = 1; r = neige; g = neige; b = neige; } }
float TerrainNoise::maxElevation() const{ float hMax = FLT_MIN; float hauteur; #pragma omp parallel for schedule(dynamic,1) for(int y = 0 ; y<(int)longueur; y++){ for(int x = 0; x<largeur; x++){ hauteur = getHauteur(x,y); if(hauteur>hMax)hMax=hauteur; } } return hMax; }
bool Terrain::intersect(const Rayon& rayon, float &coeffDistance, int &i) const { float dmin; float dmax; if(!box.intersect(rayon, dmin, dmax )) return false; //à modifier à cause de la précision des floats, mais c'est bizarre que ça marche comme un gant. faire attention que le point de départ ne soit pas en dehors de la box. //dmin = 0.0; //dmax = 3000.0; coeffDistance = dmin; for(i = 0; i<128; i++) { vec3 pos = rayon.getOrigine() + coeffDistance*rayon.getDirection(); float h = getHauteur( pos ); if(h == HAUTEUR_HORS_MAP) { if(i == 0) { coeffDistance += 0.01f; continue; } else break; } h = fabsf(pos.z - h); if( h <(0.002 * coeffDistance) ) { return true; }else if(coeffDistance > dmax ) break; coeffDistance += 0.3*h; } return false; }
float Terrain::getHauteur(const vec3& pointXYZ) const { return getHauteur(pointXYZ.x, pointXYZ.y); }
float Terrain::getHauteur(const vec2& pointXY) const { return getHauteur(pointXY.x, pointXY.y); }
double Terrain::getHauteurNormale(const Vector2D &p, Vector3D &n) { n=norm(p); double resu=getHauteur(p); return resu; }
float Terrain::getHauteur(const Vector3f& pointXYZ) const { return getHauteur(pointXYZ(0), pointXYZ(1)); }
bool Terrain::isIn(const Vector3D &p) const { Vector2D p2(p.x(),p.z()); return p.y()<=getHauteur(p2); }
bool Terrain::inOut(const Eigen::Vector3f& pointXYZ) const { return (pointXYZ(2) <= getHauteur(pointXYZ(0), pointXYZ(1))); }
bool Terrain::isOut(const Vector3D &p) { Vector2D p2(p.x(),p.z()); return p.y()>getHauteur(p2); }
float Terrain::getHauteur(const Vector2f& pointXY) const { return getHauteur(pointXY(0), pointXY(1)); }