This commit is contained in:
Federico Ponchio 2005-02-21 18:26:37 +00:00
parent 31ac4bbe6f
commit 901a4bba37
2 changed files with 230 additions and 0 deletions

177
apps/nexus/normalscone.cpp Normal file
View File

@ -0,0 +1,177 @@
#include "normalscone.h"
#include <iostream>
using namespace std;
using namespace vcg;
using namespace nxs;
ANCone3f::ANCone3f() {
scaledNormal = Point3f(0,0,0);
frontAnchor = Point3f(0,0,0);
backAnchor = Point3f(0,0,0);
}
bool ANCone3f::Frontface(const Point3f &viewPoint) {
Point3f d = frontAnchor - viewPoint; //Vector from viewPoint to frontAnchor.
float f = - d * scaledNormal;
if (f < 0.001 || f * f < d * d)
return false;
return true;
}
bool ANCone3f::Backface(const Point3f &viewPoint) {
Point3f d = backAnchor - viewPoint; //Vector from viewPoint to frontAnchor.
float f = d * scaledNormal;
if (f < 0.001 || f * f < d * d)
return false;
return true;
}
void ANCone3f::AddNormals(vector<Point3f> &normal, vector<float> &area, float threshold) {
assert(normal.size() == area.size());
scaledNormal = Point3f(0,0,0);
int count = 0;
vector<Point3f>::iterator i;
for(i = normal.begin(); i != normal.end(); i++) {
scaledNormal += *i;
count++;
}
scaledNormal /= count;
scaledNormal.Normalize();
double distr[50];
for(int k = 0; k < 50; k++)
distr[k] = 0;
double tot_area = 0;
vector<float>::iterator j;
for(i = normal.begin(), j = area.begin(); i != normal.end(); i++, j++) {
int pos = (int)(49.0 * Angle(scaledNormal, *i)/M_PI);
if(pos < 0) continue;
assert(pos >=0 && pos < 50);
distr[pos] += *j;
tot_area += *j;
}
float tot = 0;
int best;
for(best = 0; best < 50; best++) {
tot += distr[best];
if(tot > threshold * tot_area)
break;
}
double alpha = M_PI * (best + 1) / 50;
if(alpha > M_PI/ 2 - 0.1)
scaledNormal = Point3f(0,0,0);
else
scaledNormal /= cos(M_PI/2 - alpha);
}
void ANCone3f::AddNormals(vector<Point3f> &normal, float threshold) {
//assert(normal.size() > 0);
scaledNormal = Point3f(0,0,0);
int count = 0;
vector<Point3f>::iterator i;
for(i = normal.begin(); i != normal.end(); i++) {
Point3f norm = *i;
if(norm.Norm() < 0.00001) continue;
norm.Normalize();
scaledNormal += norm;
count++;
}
scaledNormal /= count;
scaledNormal.Normalize();
int distr[50];
for(int k = 0; k < 50; k++)
distr[k] =0;
for(i = normal.begin(); i != normal.end(); i++) {
int pos = (int)(50.0 * Angle(scaledNormal, *i)/M_PI);
distr[pos]++;
}
int tot = 0;
int best;
// cerr << "Distr: ";
for(best = 0; best < 50; best++) {
// cerr << distr[best] << " ";
tot += distr[best];
if(tot >= threshold * normal.size())
break;
}
double alpha = M_PI * (best +1) / 50;
// cerr << "best: " << best << " alpha: " << alpha << endl;
if(alpha > M_PI/ 2) {
scaledNormal = Point3f(0,0,0);
} else {
scaledNormal /= cos(M_PI/2 - alpha);
}
}
void ANCone3f::AddAnchors(vector<Point3f> &anchors) {
assert(anchors.size() > 0);
frontAnchor = anchors[0];
backAnchor = anchors[0];
float fa = frontAnchor * scaledNormal;
float fb = -backAnchor * scaledNormal;
vector<Point3f>::iterator i;
for(i = anchors.begin(); i != anchors.end(); i++) {
Point3f &anchor = *i;
float na = anchor * scaledNormal;
if(na < fa) {
frontAnchor = anchor;
fa = na;
}
if(-na < fb) {
backAnchor = anchor;
fb = -na;
}
}
}
void NCone3s::Import(const ANCone3f &c) {
Point3f normal = c.scaledNormal;
float len = normal.Norm();
if(len != 0)
normal /= len;
assert(normal[0] <= 1 && normal[1] <= 1 && normal[2] <= 1);
assert(normal[0] >= -1 && normal[1] >= -1 && normal[2] >= -1);
n[0] = (short)(normal[0] * 32766);
n[1] = (short)(normal[1] * 32766);
n[2] = (short)(normal[2] * 32766);
//i want to rapresent number from 1 to 10
if(len > 10.0f) len = 10.0f;
if(len < -10.0f) len = -10.0f;
n[3] = (short)(len * 3276);
}
bool NCone3s::Backface(const vcg::Sphere3f &sphere,
const vcg::Point3f &view) const {
vcg::Point3f norm(n[0]/32766.0f, n[1]/32766.0f, n[2]/32766.0f);
vcg::Point3f d = (sphere.Center() + norm * sphere.Radius()) - view;
norm *= n[3]/3276.0f;
float f = d * norm;
if (f < 0.001 || f * f < d * d)
return false;
return true;
}
bool NCone3s::Frontface(const vcg::Sphere3f &sphere,
const vcg::Point3f &view) const {
vcg::Point3f norm(n[0]/32766.0f, n[1]/32766.0f, n[2]/32766.0f);
vcg::Point3f d = (sphere.Center() - norm * sphere.Radius()) - view;
norm *= n[3]/3276.0f;
float f = -d * norm;
if (f < 0.001 || f * f < d * d)
return false;
return true;
}

53
apps/nexus/normalscone.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef NXS_NORMALS_CONE_H
#define NXS_NORMALS_CONE_H
#include <vector>
#include <vcg/space/point3.h>
#include <vcg/space/sphere3.h>
namespace nxs {
//anchored normal cone.
class ANCone3f {
public:
ANCone3f();
bool Frontface(const vcg::Point3f &viewPoint);
bool Backface(const vcg::Point3f &viewPoint);
//threshold [0, 1]: percentage of normals to left out
void AddNormals(std::vector<vcg::Point3f> &normals,
float threshold = 1.0f);
void AddNormals(std::vector<vcg::Point3f> &normals,
std::vector<float> &areas,
float threshold = 1.0f);
void AddAnchors(std::vector<vcg::Point3f> &anchors);
protected:
vcg::Point3f scaledNormal;
vcg::Point3f frontAnchor;
vcg::Point3f backAnchor;
friend class NCone3s;
};
//this is not anchored... need a bounding sphere to report something
class NCone3s {
public:
void Import(const ANCone3f &c);
bool Backface(const vcg::Sphere3f &sphere,
const vcg::Point3f &view) const;
bool Frontface(const vcg::Sphere3f &sphere,
const vcg::Point3f &view) const;
//encode normal and sin(alpha) in n[3]
short n[4];
};
}
#endif