Пример #1
0
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;
}
Пример #2
0
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;
  }
}
Пример #3
0
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);
  }
}
Пример #4
0
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();
*/
}
Пример #5
0
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;
}
Пример #6
0
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();
  }
}
Пример #7
0
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])));
}
Пример #8
0
void nuiPath::StopPath()
{
  AddVertex(nuiPoint(nuiPointTypeStop));
}