nuiArc::nuiArc(float cX, float cY, float rX, float rY, float Theta1, float Theta2, float Phi) { // use -Theta1 and -Theta2 to reverse around the Y axis float T1 = (float)(-(M_PI * Theta1)/180.0); float T2 = (float)(-(M_PI * Theta2)/180.0); nuiVector start(rX * cos(T1), rY * sin(T1), 0.0f) , stop(rX * cos(T2), rY * sin(T2), 0.0f); nuiMatrix m; m.SetRotation(Phi, 0.0f, 0.0f, 1.0f); mXRadius = rX; mYRadius = rY; mStartVertex = nuiPoint(m * start); mStopVertex = nuiPoint(m * stop); mStartVertex.Elt[0] += cX; mStartVertex.Elt[1] += cY; mStopVertex.Elt[0] += cX; mStopVertex.Elt[1] += cY; float DT = Theta1 - Theta2; mLargeArc = (DT > 180); mSweep = (DT > 0); mAngle = Phi; }
void nuiOutliner::AddCap(const nuiPoint& rFirstPoint, const nuiPoint& rLastPoint, nuiPath& rPoints) const { switch (mLineCap) { case nuiLineCapBut: // Nothing special to do rPoints.AddVertexOptim(rFirstPoint); rPoints.AddVertexOptim(rLastPoint); break; case nuiLineCapRound: { nuiArc arc(rFirstPoint, rLastPoint, mRealLineWidth, mRealLineWidth, 0, true, true); arc.Tessellate(rPoints, 0.5f); //rPoints.AddVertexOptim(rFirstPoint); } break; case nuiLineCapSquare: { nuiVector vec = rLastPoint - rFirstPoint; vec.Normalize(); float tmp = vec[0]; vec[0] = vec[1]; vec[1] = -tmp; vec *= mLineWidth * 0.5f; rPoints.AddVertexOptim(nuiPoint(rFirstPoint+vec)); rPoints.AddVertexOptim(nuiPoint(rLastPoint+vec)); } break; } }
void nuiDrawContext::DrawLine(float x1, float y1, float x2, float y2) { if (x1 == x2 && y1 == y2) { DrawPoint(x1, y1); } else { nuiShape shp; shp.LineTo(nuiPoint(x1, y1)); shp.LineTo(nuiPoint(x2, y2)); DrawShape(&shp, eStrokeShape); } }
void render_handler_nui::draw_line_strip(const void* coords, int vertex_count) // Draw the line strip formed by the sequence of points. { // Set up current style. m_current_styles[LINE_STYLE].apply(); nuiShape shp; nuiContour* pContour = new nuiContour(); std::list<nuiPoint> lines; for (uint i = 0; i < vertex_count; i++) lines.push_back(nuiPoint(coords[i*2], coords[i*2+1])); pContour->AddLines(lines); shp.AddContour(pContour); mpContext->PushMatrix(); apply_matrix(m_current_matrix); if (mMasking) { mpContext->AddClipShape(shp); } else { mpContext->DrawShape(&shp, nuiShapeMode::eStrokeShape); } mpContext->PopMatrix(); /* glMatrixMode(GL_MODELVIEW); glPushMatrix(); apply_matrix(m_current_matrix); // Send the line-strip to OpenGL glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_SHORT, sizeof(Sint16) * 2, coords); glDrawArrays(GL_LINE_STRIP, 0, vertex_count); glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); */ }
bool nuiArc::Tessellate(nuiPath& rVertices, float Quality) const { // I shamelessly stole this code from svgl double x1, y1, x2, y2; x1 = mStartVertex.Elt[0]; y1 = mStartVertex.Elt[1]; x2 = mStopVertex.Elt[0]; y2 = mStopVertex.Elt[1]; double angle = mAngle; double xr, yr; xr = mXRadius; yr = mYRadius; rVertices.AddVertexOptim(nuiPoint((float)x1, (float)y1)); if ((x1 == x2) && (y1 == y2) && !mLargeArc) { return true; } // be sure mXRadius or mYRadius are non-zero if( mXRadius == 0 || mYRadius == 0) { rVertices.AddVertexOptim(nuiPoint((float)x2, (float)y2)); return true; } // make sure mXRadius and mYRadius are positive if(xr < 0) xr = -xr; if(yr < 0) yr = -yr; const double cosa = cos(angle * M_PI / 180.0); const double sina = sin(angle * M_PI / 180.0); // compute the center (see svg.pdf) const double xp1 = cosa * (x1 - x2) / 2.0 + sina * (y1 - y2) / 2.f; const double yp1 = -sina * (x1 - x2) / 2.0 + cosa * (y1 - y2) / 2.f; double rx2 = xr * xr, ry2 = yr * yr, xp12 = xp1 * xp1, yp12 = yp1 * yp1; // make sure xr and yr are large enough { double tmp = xp12 / rx2 + yp12 / ry2; if (tmp > 1) { rx2 *= tmp; ry2 *= tmp; tmp = sqrt(tmp); xr *= tmp; yr *= tmp; } } double fact = ( rx2 * ry2 / (rx2 * yp12 + ry2 * xp12)) - 1; if (fact < 0) { fact = 0; } fact = sqrt(fact); if (mLargeArc == mSweep) fact = -fact; double xpc = xr * yp1 / yr; double ypc = - yr * xp1 / xr; xpc *= fact; ypc *= fact; double xc = xpc * cosa - ypc * sina + (x1 + x2) / 2.f; double yc = xpc * sina + ypc * cosa + (y1 + y2) / 2.f; // determine t1 and t2, limits given by (x1, y1) (x2, y2) double t1; double deltat; // double t2; { double xv1 = (xp1 - xpc) / xr; double yv1 = (yp1 - ypc) / yr; double norm1 = xv1 * xv1 + yv1 * yv1; double cosangle1 = xv1 / sqrt(norm1); if (cosangle1 < -1.0f) cosangle1 = -1.0f; if (cosangle1 > 1.0f) cosangle1 = 1.0f; t1 = acos(cosangle1); if (yv1 < 0) t1 = -t1; double xv2 = (-xp1 - xpc) / xr; double yv2 = (-yp1 - ypc) / yr; double norm2 = xv2 * xv2 + yv2 * yv2; deltat = xv1 * xv2 + yv1 * yv2; deltat = deltat / sqrt(norm1 * norm2); if (deltat < -1.0) deltat = -1.0; if (deltat > 1.0) deltat = 1.0; deltat = acos(deltat); if ( (xv1 * yv2 - yv1 * xv2) < 0) deltat = -deltat; if (!mSweep && (deltat > 0)) deltat -= 2.0 * M_PI; if (mSweep && (deltat < 0)) deltat += 2.0 * M_PI; } // compute vertices /* fast incremental cos and sin generation cos(a+dt) = cos(a) cos(dt) - sin(a) sin(dt); sin(a+dt) = cos(a) sin(dt) + cos(dt) sin(a); <=> cos(a+2*dt) = cos(a + dt) cos(dt) - sin(a + dt) sin(dt) sin(a+2*dt) = cos(a + dt) sin(dt) + cos(a + dt) sin(a) */ const int nb = ToBelow(M_PI * (xr + yr) * Quality); const double dt = deltat / nb; const double cosdt = cos(dt); const double sindt = sin(dt); double cost1_plus_ndt = cos(t1 + dt); double sint1_plus_ndt = sin(t1 + dt); for (int i = 0; i < nb; ++i) { /* ellipsoid: x(t) = xr.cos(t) y(t) = yr.cos(t) */ double x = xr * cost1_plus_ndt; double y = yr * sint1_plus_ndt; { // compute cos and sin double tmp = cost1_plus_ndt * cosdt - sint1_plus_ndt * sindt; sint1_plus_ndt = cost1_plus_ndt * sindt + sint1_plus_ndt * cosdt; cost1_plus_ndt = tmp; } // rotate // angle = -angle, I don't know why... { double tmp = x * cosa - y * sina; y = x * sina + y * cosa; x = tmp; } // translate x += xc; y += yc; rVertices.AddVertexOptim(nuiPoint((float)x, (float)y)); } return true; }
void nuiOutliner::Tessellate(nuiPath& rPoints, const nuiPath& rVertices, uint offset, int count, float Quality) const { nuiPath Left; nuiPath Right; NGL_ASSERT(count); const nuiPoint& rstart = rVertices[offset]; const nuiPoint& rstop = rVertices[offset + count - 1]; bool closed = rstart == rstop; int segments = count; if (!closed) segments--; int i; // Create four outlined vertex per segment: for (i = 0; i < segments; i++) { int p1 = i; int p2 = (p1+1); p1 += offset; p2 += offset; const nuiPoint& rPoint = rVertices[p1]; const nuiPoint& rNextPoint = rVertices[p2]; if (!(rPoint == rNextPoint)) { nuiVector vec(rNextPoint - rPoint); vec.Normalize(); vec *= mRealLineWidth; float tmp = vec[0]; vec[0] = vec[1]; vec[1] = -tmp; Left.AddVertexOptim(nuiPoint(rPoint + vec)); Left.AddVertexOptim(nuiPoint(rNextPoint + vec)); Right.AddVertexOptim(nuiPoint(rPoint - vec)); Right.AddVertexOptim(nuiPoint(rNextPoint - vec)); } } Right.Reverse(); if (!Left.GetCount() || !Right.GetCount()) // Case of a path where all points have the same coordinates { switch (mLineCap) { case nuiLineCapBut: // The result is empty. break; case nuiLineCapRound: { const double CIRCLE_FACTOR = (1.0/3.5); const double X = rstart[0]; const double Y = rstart[1]; uint count = ToAbove((double)(2.0 * M_PI * (double)mRealLineWidth * (double)CIRCLE_FACTOR)); float step = 2.0f * (float)M_PI / (float)count; for (uint i = 0; i <= count; i++) { float angle = step * (float) i; float x = (float)(X + sin(angle) * mRealLineWidth); float y = (float)(Y + cos(angle) * mRealLineWidth); rPoints.AddVertexOptim(nuiPoint(x, y, 0)); } } break; case nuiLineCapSquare: { const float x = rstart[0]; const float y = rstart[1]; rPoints.AddVertexOptim(nuiPoint(x - mRealLineWidth, y - mRealLineWidth)); rPoints.AddVertexOptim(nuiPoint(x + mRealLineWidth, y - mRealLineWidth)); rPoints.AddVertexOptim(nuiPoint(x + mRealLineWidth, y + mRealLineWidth)); rPoints.AddVertexOptim(nuiPoint(x - mRealLineWidth, y + mRealLineWidth)); rPoints.AddVertexOptim(nuiPoint(x - mRealLineWidth, y - mRealLineWidth)); } break; } } else if (closed && Left.GetCount() >= 2 && Right.GetCount() >= 2) // Case of a closed path (make sure that is at least a segment). { // Left: int ndx1 = 0; int ndx2 = 0; for (i = 0; i < segments-1; i++) { ndx1 = i * 2; ndx2 = ndx1 + 2; AddJoin(Left[ndx1], Left[ndx1+1], Left[ndx2], Left[ndx2+1], rPoints); } if (mLineJoin == nuiLineJoinBevel) rPoints.AddVertexOptim(rPoints.Front()); else rPoints.Back() = rPoints.Front(); rPoints.StopPath(); // Right: for (i = 0; i < segments; i++) { ndx1 = i * 2; ndx2 = ndx1 + 2; AddJoin(Right[ndx1], Right[ndx1+1], Right[ndx2], Right[ndx2+1], rPoints); } rPoints.StopPath(); } else { NGL_ASSERT(!Left.IsEmpty()); NGL_ASSERT(!Right.IsEmpty()); int cnt = segments - 1; // Left: rPoints.AddVertexOptim(Left.Front()); int ndx1 = 0; int ndx2 = 0; for (i = 0; i < cnt; i++) { ndx1 = i * 2; ndx2 = ndx1 + 2; AddJoin(Left[ndx1], Left[ndx1+1], Left[ndx2], Left[ndx2+1], rPoints); } AddCap(Left.Back(), Right.Front(), rPoints); // Right: for (i = 0; i < cnt; i++) { ndx1 = i * 2; ndx2 = ndx1 + 2; AddJoin(Right[ndx1], Right[ndx1+1], Right[ndx2], Right[ndx2+1], rPoints); } AddCap(Right.Back(), Left.Front(), rPoints); rPoints.Front() = rPoints.Back(); rPoints.StopPath(); } }
void nuiTessellator::InternalTessCombine(GLdouble coords[3], void *vertex_data[4], GLfloat weight[4], void **outData) { //printf("Combine %f %f\n", coords[0], coords[1]); *outData = (void*)mTempPoints.AddVertex(nuiPoint((float)(coords[0]), (float)(coords[1]), (float)(coords[2]))); }
void nuiPath::StopPath() { AddVertex(nuiPoint(nuiPointTypeStop)); }