//============================================================================= Obb3::Obb3 (const Point3 & center, const Vector3 & x, const Vector3 & y, const Vector3 & z) : center(center) { u[0] = x; u[1] = y; u[2] = z; for (uint i = 0; i < 3; ++i) extent[i] = Normalize2(u[i]); }
//============================================================================= Obb2::Obb2 ( const Point2 & center, const Vector2 & x, const Vector2 & y ) : center(center) { u[0] = x; u[1] = y; for (uint i = 0; i < 2; ++i) extent[i] = Normalize2(u[i]); }
/* draw a given stroke in 2d */ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int offsx, int offsy, int winx, int winy) { /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better * - 'smooth' opengl lines are also required if Image Editor 'image-based' stroke */ if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) ) { bGPDspoint *pt; int i; glBegin(GL_LINE_STRIP); for (i=0, pt=points; i < totpoints && pt; i++, pt++) { if (sflag & GP_STROKE_2DSPACE) { glVertex2f(pt->x, pt->y); } else if (sflag & GP_STROKE_2DIMAGE) { const float x= (pt->x * winx) + offsx; const float y= (pt->y * winy) + offsy; glVertex2f(x, y); } else { const float x= (pt->x / 100 * winx); const float y= (pt->y / 100 * winy); glVertex2f(x, y); } } glEnd(); } /* tesselation code - draw stroke as series of connected quads with connection * edges rotated to minimise shrinking artifacts, and rounded endcaps */ else { bGPDspoint *pt1, *pt2; float pm[2]; int i; glShadeModel(GL_FLAT); glBegin(GL_QUADS); for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) { float s0[2], s1[2]; /* segment 'center' points */ float t0[2], t1[2]; /* tesselated coordinates */ float m1[2], m2[2]; /* gradient and normal */ float mt[2], sc[2]; /* gradient for thickness, point for end-cap */ float pthick; /* thickness at segment point */ /* get x and y coordinates from points */ if (sflag & GP_STROKE_2DSPACE) { s0[0]= pt1->x; s0[1]= pt1->y; s1[0]= pt2->x; s1[1]= pt2->y; } else if (sflag & GP_STROKE_2DIMAGE) { s0[0]= (pt1->x * winx) + offsx; s0[1]= (pt1->y * winy) + offsy; s1[0]= (pt2->x * winx) + offsx; s1[1]= (pt2->y * winy) + offsy; } else { s0[0]= (pt1->x / 100 * winx); s0[1]= (pt1->y / 100 * winy); s1[0]= (pt2->x / 100 * winx); s1[1]= (pt2->y / 100 * winy); } /* calculate gradient and normal - 'angle'=(ny/nx) */ m1[1]= s1[1] - s0[1]; m1[0]= s1[0] - s0[0]; Normalize2(m1); m2[1]= -m1[0]; m2[0]= m1[1]; /* always use pressure from first point here */ pthick= (pt1->pressure * thickness); /* if the first segment, start of segment is segment's normal */ if (i == 0) { /* draw start cap first * - make points slightly closer to center (about halfway across) */ mt[0]= m2[0] * pthick * 0.5f; mt[1]= m2[1] * pthick * 0.5f; sc[0]= s0[0] - (m1[0] * pthick * 0.75f); sc[1]= s0[1] - (m1[1] * pthick * 0.75f); t0[0]= sc[0] - mt[0]; t0[1]= sc[1] - mt[1]; t1[0]= sc[0] + mt[0]; t1[1]= sc[1] + mt[1]; glVertex2fv(t0); glVertex2fv(t1); /* calculate points for start of segment */ mt[0]= m2[0] * pthick; mt[1]= m2[1] * pthick; t0[0]= s0[0] - mt[0]; t0[1]= s0[1] - mt[1]; t1[0]= s0[0] + mt[0]; t1[1]= s0[1] + mt[1]; /* draw this line twice (first to finish off start cap, then for stroke) */ glVertex2fv(t1); glVertex2fv(t0); glVertex2fv(t0); glVertex2fv(t1); } /* if not the first segment, use bisector of angle between segments */ else { float mb[2]; /* bisector normal */ float athick, dfac; /* actual thickness, difference between thicknesses */ /* calculate gradient of bisector (as average of normals) */ mb[0]= (pm[0] + m2[0]) / 2; mb[1]= (pm[1] + m2[1]) / 2; Normalize2(mb); /* calculate gradient to apply * - as basis, use just pthick * bisector gradient * - if cross-section not as thick as it should be, add extra padding to fix it */ mt[0]= mb[0] * pthick; mt[1]= mb[1] * pthick; athick= Vec2Length(mt); dfac= pthick - (athick * 2); if ( ((athick * 2) < pthick) && (IS_EQ(athick, pthick)==0) ) { mt[0] += (mb[0] * dfac); mt[1] += (mb[1] * dfac); } /* calculate points for start of segment */ t0[0]= s0[0] - mt[0]; t0[1]= s0[1] - mt[1]; t1[0]= s0[0] + mt[0]; t1[1]= s0[1] + mt[1]; /* draw this line twice (once for end of current segment, and once for start of next) */ glVertex2fv(t1); glVertex2fv(t0); glVertex2fv(t0); glVertex2fv(t1); } /* if last segment, also draw end of segment (defined as segment's normal) */ if (i == totpoints-2) { /* for once, we use second point's pressure (otherwise it won't be drawn) */ pthick= (pt2->pressure * thickness); /* calculate points for end of segment */ mt[0]= m2[0] * pthick; mt[1]= m2[1] * pthick; t0[0]= s1[0] - mt[0]; t0[1]= s1[1] - mt[1]; t1[0]= s1[0] + mt[0]; t1[1]= s1[1] + mt[1]; /* draw this line twice (once for end of stroke, and once for endcap)*/ glVertex2fv(t1); glVertex2fv(t0); glVertex2fv(t0); glVertex2fv(t1); /* draw end cap as last step * - make points slightly closer to center (about halfway across) */ mt[0]= m2[0] * pthick * 0.5f; mt[1]= m2[1] * pthick * 0.5f; sc[0]= s1[0] + (m1[0] * pthick * 0.75f); sc[1]= s1[1] + (m1[1] * pthick * 0.75f); t0[0]= sc[0] - mt[0]; t0[1]= sc[1] - mt[1]; t1[0]= sc[0] + mt[0]; t1[1]= sc[1] + mt[1]; glVertex2fv(t1); glVertex2fv(t0); } /* store stroke's 'natural' normal for next stroke to use */ Vec2Copyf(pm, m2); } glEnd(); } /* draw debug points of curve on top? (original stroke points) */ if (debug) { bGPDspoint *pt; int i; glBegin(GL_POINTS); for (i=0, pt=points; i < totpoints && pt; i++, pt++) { if (sflag & GP_STROKE_2DSPACE) { glVertex2f(pt->x, pt->y); } else if (sflag & GP_STROKE_2DIMAGE) { const float x= (float)((pt->x * winx) + offsx); const float y= (float)((pt->y * winy) + offsy); glVertex2f(x, y); } else { const float x= (float)(pt->x / 100 * winx); const float y= (float)(pt->y / 100 * winy); glVertex2f(x, y); } } glEnd(); } }
static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFace *activetf) { EditFace *efa; MTFace *tf; Image *ima= sima->image; float aspx, aspy, col[4], tf_uv[4][2]; ED_space_image_uv_aspect(sima, &aspx, &aspy); switch(sima->dt_uvstretch) { case SI_UVDT_STRETCH_AREA: { float totarea=0.0f, totuvarea=0.0f, areadiff, uvarea, area; for(efa= em->faces.first; efa; efa= efa->next) { tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); uv_copy_aspect(tf->uv, tf_uv, aspx, aspy); totarea += EM_face_area(efa); //totuvarea += tf_area(tf, efa->v4!=0); totuvarea += uv_area(tf_uv, efa->v4!=0); if(uvedit_face_visible(scene, ima, efa, tf)) { efa->tmp.p = tf; } else { if(tf == activetf) activetf= NULL; efa->tmp.p = NULL; } } if(totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) { col[0] = 1.0; col[1] = col[2] = 0.0; glColor3fv(col); for(efa= em->faces.first; efa; efa= efa->next) { if((tf=(MTFace *)efa->tmp.p)) { glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); } } } else { for(efa= em->faces.first; efa; efa= efa->next) { if((tf=(MTFace *)efa->tmp.p)) { area = EM_face_area(efa) / totarea; uv_copy_aspect(tf->uv, tf_uv, aspx, aspy); //uvarea = tf_area(tf, efa->v4!=0) / totuvarea; uvarea = uv_area(tf_uv, efa->v4!=0) / totuvarea; if(area < FLT_EPSILON || uvarea < FLT_EPSILON) areadiff = 1.0; else if(area>uvarea) areadiff = 1.0-(uvarea/area); else areadiff = 1.0-(area/uvarea); weight_to_rgb(areadiff, col, col+1, col+2); glColor3fv(col); glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); glVertex2fv(tf->uv[0]); glVertex2fv(tf->uv[1]); glVertex2fv(tf->uv[2]); if(efa->v4) glVertex2fv(tf->uv[3]); glEnd(); } } } break; } case SI_UVDT_STRETCH_ANGLE: { float uvang1,uvang2,uvang3,uvang4; float ang1,ang2,ang3,ang4; float av1[3], av2[3], av3[3], av4[3]; /* use for 2d and 3d angle vectors */ float a; col[3] = 0.5; /* hard coded alpha, not that nice */ glShadeModel(GL_SMOOTH); for(efa= em->faces.first; efa; efa= efa->next) { tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); if(uvedit_face_visible(scene, ima, efa, tf)) { efa->tmp.p = tf; uv_copy_aspect(tf->uv, tf_uv, aspx, aspy); if(efa->v4) { #if 0 /* Simple but slow, better reuse normalized vectors */ uvang1 = RAD2DEG(Vec2Angle3(tf_uv[3], tf_uv[0], tf_uv[1])); ang1 = RAD2DEG(VecAngle3(efa->v4->co, efa->v1->co, efa->v2->co)); uvang2 = RAD2DEG(Vec2Angle3(tf_uv[0], tf_uv[1], tf_uv[2])); ang2 = RAD2DEG(VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co)); uvang3 = RAD2DEG(Vec2Angle3(tf_uv[1], tf_uv[2], tf_uv[3])); ang3 = RAD2DEG(VecAngle3(efa->v2->co, efa->v3->co, efa->v4->co)); uvang4 = RAD2DEG(Vec2Angle3(tf_uv[2], tf_uv[3], tf_uv[0])); ang4 = RAD2DEG(VecAngle3(efa->v3->co, efa->v4->co, efa->v1->co)); #endif /* uv angles */ VECSUB2D(av1, tf_uv[3], tf_uv[0]); Normalize2(av1); VECSUB2D(av2, tf_uv[0], tf_uv[1]); Normalize2(av2); VECSUB2D(av3, tf_uv[1], tf_uv[2]); Normalize2(av3); VECSUB2D(av4, tf_uv[2], tf_uv[3]); Normalize2(av4); /* This is the correct angle however we are only comparing angles * uvang1 = 90-((NormalizedVecAngle2_2D(av1, av2) * 180.0/M_PI)-90);*/ uvang1 = NormalizedVecAngle2_2D(av1, av2)*180.0/M_PI; uvang2 = NormalizedVecAngle2_2D(av2, av3)*180.0/M_PI; uvang3 = NormalizedVecAngle2_2D(av3, av4)*180.0/M_PI; uvang4 = NormalizedVecAngle2_2D(av4, av1)*180.0/M_PI; /* 3d angles */ VECSUB(av1, efa->v4->co, efa->v1->co); Normalize(av1); VECSUB(av2, efa->v1->co, efa->v2->co); Normalize(av2); VECSUB(av3, efa->v2->co, efa->v3->co); Normalize(av3); VECSUB(av4, efa->v3->co, efa->v4->co); Normalize(av4); /* This is the correct angle however we are only comparing angles * ang1 = 90-((NormalizedVecAngle2(av1, av2) * 180.0/M_PI)-90);*/ ang1 = NormalizedVecAngle2(av1, av2)*180.0/M_PI; ang2 = NormalizedVecAngle2(av2, av3)*180.0/M_PI; ang3 = NormalizedVecAngle2(av3, av4)*180.0/M_PI; ang4 = NormalizedVecAngle2(av4, av1)*180.0/M_PI; glBegin(GL_QUADS); /* This simple makes the angles display worse then they really are ;) * 1.0-pow((1.0-a), 2) */ a = fabs(uvang1-ang1)/180.0; weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2); glColor3fv(col); glVertex2fv(tf->uv[0]); a = fabs(uvang2-ang2)/180.0; weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2); glColor3fv(col); glVertex2fv(tf->uv[1]); a = fabs(uvang3-ang3)/180.0; weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2); glColor3fv(col); glVertex2fv(tf->uv[2]); a = fabs(uvang4-ang4)/180.0; weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2); glColor3fv(col); glVertex2fv(tf->uv[3]); } else { #if 0 /* Simple but slow, better reuse normalized vectors */ uvang1 = RAD2DEG(Vec2Angle3(tf_uv[2], tf_uv[0], tf_uv[1])); ang1 = RAD2DEG(VecAngle3(efa->v3->co, efa->v1->co, efa->v2->co)); uvang2 = RAD2DEG(Vec2Angle3(tf_uv[0], tf_uv[1], tf_uv[2])); ang2 = RAD2DEG(VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co)); uvang3 = M_PI-(uvang1+uvang2); ang3 = M_PI-(ang1+ang2); #endif /* uv angles */ VECSUB2D(av1, tf_uv[2], tf_uv[0]); Normalize2(av1); VECSUB2D(av2, tf_uv[0], tf_uv[1]); Normalize2(av2); VECSUB2D(av3, tf_uv[1], tf_uv[2]); Normalize2(av3); /* This is the correct angle however we are only comparing angles * uvang1 = 90-((NormalizedVecAngle2_2D(av1, av2) * 180.0/M_PI)-90); */ uvang1 = NormalizedVecAngle2_2D(av1, av2)*180.0/M_PI; uvang2 = NormalizedVecAngle2_2D(av2, av3)*180.0/M_PI; uvang3 = NormalizedVecAngle2_2D(av3, av1)*180.0/M_PI; /* 3d angles */ VECSUB(av1, efa->v3->co, efa->v1->co); Normalize(av1); VECSUB(av2, efa->v1->co, efa->v2->co); Normalize(av2); VECSUB(av3, efa->v2->co, efa->v3->co); Normalize(av3); /* This is the correct angle however we are only comparing angles * ang1 = 90-((NormalizedVecAngle2(av1, av2) * 180.0/M_PI)-90); */ ang1 = NormalizedVecAngle2(av1, av2)*180.0/M_PI; ang2 = NormalizedVecAngle2(av2, av3)*180.0/M_PI; ang3 = NormalizedVecAngle2(av3, av1)*180.0/M_PI; /* This simple makes the angles display worse then they really are ;) * 1.0-pow((1.0-a), 2) */ glBegin(GL_TRIANGLES); a = fabs(uvang1-ang1)/180.0; weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2); glColor3fv(col); glVertex2fv(tf->uv[0]); a = fabs(uvang2-ang2)/180.0; weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2); glColor3fv(col); glVertex2fv(tf->uv[1]); a = fabs(uvang3-ang3)/180.0; weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2); glColor3fv(col); glVertex2fv(tf->uv[2]); } glEnd(); } else { if(tf == activetf) activetf= NULL; efa->tmp.p = NULL; } } glShadeModel(GL_FLAT); break; } } }