Я вторые сутки схожу с ума. А сдавать завтра. Задача: раскрасить полигон с двух сторон, в зависимости от того, какая сторона видна. Безо всяких опенджлей и директиксов. Есть набор точек (поверхность). Создаю треугольники, определяю направление обхода, затем нахожу нормаль, скалярное произведение между вектором наблюдателя и нормалью и... не работает! То есть работает, но косячно:  Такое ощущение, что неправильно считается направление обхода! Вот сорцы (извиняюсь за адовъ ###код, но времени совсем нет). | Код |
double dotProduct(double *a, double *b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }
double troj(Vertice *a, Vertice *b, Vertice *c) { double first = a->getX() * (b->getY() * c->getZ() - c->getY() * b->getZ()); double second = a->getY() * (b->getX() * c->getZ() - c->getX() * b->getZ()); double third = a->getZ() * (b->getX() * c->getY() - c->getX() * b->getY()); return first - second + third; } //--------------------------------------------------------------------------- // Lifecycle //--------------------------------------------------------------------------- BezierSurface::BezierSurface(const unsigned rows, const unsigned cols, const unsigned detalization, const bool _gridHidden) : gridHidden(_gridHidden), ptsPerUnit(detalization) {
// Генерация точек поверхности // ...
// Создание треугольников for(unsigned i = 0; i < ptsPerUnit; ++i) { for(unsigned j = 0; j < ptsPerUnit; ++j) {
// Первый треугольник GraphicObject *triangle1 = new GraphicObject;
Vertice *vert1 = points[i][j]; Vertice *vert2 = points[i][j + 1]; Vertice *vert3 = points[i + 1][j]; Vertice *vert4 = points[i + 1][j + 1];
Vertice *a, *b, *c; Vertice *verts[3] = {vert1, vert2, vert3};
a = verts[0]; b = verts[1]; c = verts[2];
// Определяем направление обхода и меняем точки B и С местами do { triangle1->trojka = troj(a, b, c);
if(triangle1->trojka > 0) { Vertice *t = b; b = c; c = t; } } while (triangle1->trojka > 0);
triangle1->a = new Vertice(*a); triangle1->b = new Vertice(*b); triangle1->c = new Vertice(*c);
surface.push_back(triangle1);
// Второй треугольник
GraphicObject *triangle2 = new GraphicObject;
Vertice *verts2[3] = {vert2, vert3, vert4};
a = verts2[0]; b = verts2[1]; c = verts2[2];
// Определяем направление обхода и меняем точки B и С местами do { triangle2->trojka = troj(a, b, c);
if(triangle2->trojka > 0) { Vertice *t = b; b = c; c = t; } } while (triangle2->trojka > 0);
surface.push_back(triangle2); } } } //--------------------------------------------------------------------------- // Custom methods //---------------------------------------------------------------------------
#define X 0 #define Y 1 #define Z 2
double *getVec(double *a, double *b) { double *c = new double[3]; c[0] = b[0] - a[0]; c[1] = b[1] - a[1]; c[2] = b[2] - a[2]; return c; }
double *crossProduct(double *a, double *b) { double *cross = new double[3]; cross[X] = a[Y] * b[Z] - a[Z] * b[Y]; cross[Y] = -a[X] * b[Z] + a[Z] * b[X]; cross[Z] = a[X] * b[Y] - a[Y] * b[X]; return cross; }
// Нормализация вектора void normalize(double *v) { double mag = sqrt (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); mag = (mag) ? mag : 0.01; v[0] /= mag; v[1] /= mag; v[2] /= mag; }
// Приведенные координаты с началом координат в центре экрана void normalized(TPoint center, double &x, double &y) { x = center.x + x * scale; y = center.y - y * scale; }
void BezierSurface::drawTriangle(const GraphicObject *triangle, TCanvas *canvas, TColor color) { TPoint canvasCenter = canvas->ClipRect.CenterPoint(); double cent[3] = {canvasCenter.x, canvasCenter.y, 0};
// Вектор наблюдателя double look[3] = {cent[0], cent[1], 100};
// head = A double head[3] = {triangle->a->getX(), triangle->a->getY(), triangle->a->getZ() };
normalized(canvasCenter, head[0], head[1]);
// second = B double second[3] = {triangle->b->getX(), triangle->b->getY(), triangle->b->getZ() };
normalized(canvasCenter, second[0], second[1]);
// third = C double third[3] = {triangle->c->getX(), triangle->c->getY(), triangle->c->getZ() };
normalized(canvasCenter, third[0], third[1]);
// Векторы AB и AC double *vecAB; double *vecAC;
vecAB = getVec(head, second); vecAC = getVec(head, third);
double *cross = crossProduct(vecAB, vecAC);
normalize(cross);
bool isVisible = dotProduct(cross, look) >= 0;
delete [] vecAB; delete [] vecAC; delete [] cross; }
|
Это сообщение отредактировал(а) efpies - 24.4.2012, 18:17
|