public synchronized void curl(PointF curlPos,PointF curlDir,double radius){
  if (DRAW_CURL_POSITION) {
    mBufCurlPositionLines.position(0);
    mBufCurlPositionLines.put(curlPos.x);
    mBufCurlPositionLines.put(curlPos.y - 1.0f);
    mBufCurlPositionLines.put(curlPos.x);
    mBufCurlPositionLines.put(curlPos.y + 1.0f);
    mBufCurlPositionLines.put(curlPos.x - 1.0f);
    mBufCurlPositionLines.put(curlPos.y);
    mBufCurlPositionLines.put(curlPos.x + 1.0f);
    mBufCurlPositionLines.put(curlPos.y);
    mBufCurlPositionLines.put(curlPos.x);
    mBufCurlPositionLines.put(curlPos.y);
    mBufCurlPositionLines.put(curlPos.x + curlDir.x * 2);
    mBufCurlPositionLines.put(curlPos.y + curlDir.y * 2);
    mBufCurlPositionLines.position(0);
  }
  mBufVertices.position(0);
  mBufColors.position(0);
  if (DRAW_TEXTURE) {
    mBufTexCoords.position(0);
  }
  double curlAngle=Math.acos(curlDir.x);
  curlAngle=curlDir.y > 0 ? -curlAngle : curlAngle;
  mArrTempVertices.addAll(mArrRotatedVertices);
  mArrRotatedVertices.clear();
  for (int i=0; i < 4; ++i) {
    Vertex v=mArrTempVertices.remove(0);
    v.set(mRectangle[i]);
    v.translate(-curlPos.x,-curlPos.y);
    v.rotateZ(-curlAngle);
    int j=0;
    for (; j < mArrRotatedVertices.size(); ++j) {
      Vertex v2=mArrRotatedVertices.get(j);
      if (v.mPosX > v2.mPosX) {
        break;
      }
      if (v.mPosX == v2.mPosX && v.mPosY > v2.mPosY) {
        break;
      }
    }
    mArrRotatedVertices.add(j,v);
  }
  int lines[][]={{0,1},{0,2},{1,3},{2,3}};
{
    Vertex v0=mArrRotatedVertices.get(0);
    Vertex v2=mArrRotatedVertices.get(2);
    Vertex v3=mArrRotatedVertices.get(3);
    double dist2=Math.sqrt((v0.mPosX - v2.mPosX) * (v0.mPosX - v2.mPosX) + (v0.mPosY - v2.mPosY) * (v0.mPosY - v2.mPosY));
    double dist3=Math.sqrt((v0.mPosX - v3.mPosX) * (v0.mPosX - v3.mPosX) + (v0.mPosY - v3.mPosY) * (v0.mPosY - v3.mPosY));
    if (dist2 > dist3) {
      lines[1][1]=3;
      lines[2][1]=2;
    }
  }
  mVerticesCountFront=mVerticesCountBack=0;
  if (DRAW_SHADOW) {
    mArrTempShadowVertices.addAll(mArrDropShadowVertices);
    mArrTempShadowVertices.addAll(mArrSelfShadowVertices);
    mArrDropShadowVertices.clear();
    mArrSelfShadowVertices.clear();
  }
  double curlLength=Math.PI * radius;
  mArrScanLines.clear();
  if (mMaxCurlSplits > 0) {
    mArrScanLines.add((double)0);
  }
  for (int i=1; i < mMaxCurlSplits; ++i) {
    mArrScanLines.add((-curlLength * i) / (mMaxCurlSplits - 1));
  }
  mArrScanLines.add(mArrRotatedVertices.get(3).mPosX - 1);
  double scanXmax=mArrRotatedVertices.get(0).mPosX + 1;
  for (int i=0; i < mArrScanLines.size(); ++i) {
    double scanXmin=mArrScanLines.get(i);
    for (int j=0; j < mArrRotatedVertices.size(); ++j) {
      Vertex v=mArrRotatedVertices.get(j);
      if (v.mPosX >= scanXmin && v.mPosX <= scanXmax) {
        Vertex n=mArrTempVertices.remove(0);
        n.set(v);
        Array<Vertex> intersections=getIntersections(mArrRotatedVertices,lines,n.mPosX);
        if (intersections.size() == 1 && intersections.get(0).mPosY > v.mPosY) {
          mArrOutputVertices.addAll(intersections);
          mArrOutputVertices.add(n);
        }
 else         if (intersections.size() <= 1) {
          mArrOutputVertices.add(n);
          mArrOutputVertices.addAll(intersections);
        }
 else {
          mArrTempVertices.add(n);
          mArrTempVertices.addAll(intersections);
        }
      }
    }
    Array<Vertex> intersections=getIntersections(mArrRotatedVertices,lines,scanXmin);
    if (intersections.size() == 2) {
      Vertex v1=intersections.get(0);
      Vertex v2=intersections.get(1);
      if (v1.mPosY < v2.mPosY) {
        mArrOutputVertices.add(v2);
        mArrOutputVertices.add(v1);
      }
 else {
        mArrOutputVertices.addAll(intersections);
      }
    }
 else     if (intersections.size() != 0) {
      mArrTempVertices.addAll(intersections);
    }
    while (mArrOutputVertices.size() > 0) {
      Vertex v=mArrOutputVertices.remove(0);
      mArrTempVertices.add(v);
      boolean textureFront;
      if (i == 0) {
        textureFront=true;
        mVerticesCountFront++;
      }
 else       if (i == mArrScanLines.size() - 1 || curlLength == 0) {
        v.mPosX=-(curlLength + v.mPosX);
        v.mPosZ=2 * radius;
        v.mPenumbraX=-v.mPenumbraX;
        textureFront=false;
        mVerticesCountBack++;
      }
 else {
        double rotY=Math.PI * (v.mPosX / curlLength);
        v.mPosX=radius * Math.sin(rotY);
        v.mPosZ=radius - (radius * Math.cos(rotY));
        v.mPenumbraX*=Math.cos(rotY);
        v.mColorFactor=(float)(.1f + .9f * Math.sqrt(Math.sin(rotY) + 1));
        if (v.mPosZ >= radius) {
          textureFront=false;
          mVerticesCountBack++;
        }
 else {
          textureFront=true;
          mVerticesCountFront++;
        }
      }
      if (textureFront != mFlipTexture) {
        v.mTexX*=mTextureRectFront.right;
        v.mTexY*=mTextureRectFront.bottom;
        v.mColor=mTexturePage.getColor(CurlPage.SIDE_FRONT);
      }
 else {
        v.mTexX*=mTextureRectBack.right;
        v.mTexY*=mTextureRectBack.bottom;
        v.mColor=mTexturePage.getColor(CurlPage.SIDE_BACK);
      }
      v.rotateZ(curlAngle);
      v.translate(curlPos.x,curlPos.y);
      addVertex(v);
      if (DRAW_SHADOW && v.mPosZ > 0 && v.mPosZ <= radius) {
        ShadowVertex sv=mArrTempShadowVertices.remove(0);
        sv.mPosX=v.mPosX;
        sv.mPosY=v.mPosY;
        sv.mPosZ=v.mPosZ;
        sv.mPenumbraX=(v.mPosZ / 2) * -curlDir.x;
        sv.mPenumbraY=(v.mPosZ / 2) * -curlDir.y;
        sv.mPenumbraColor=v.mPosZ / radius;
        int idx=(mArrDropShadowVertices.size() + 1) / 2;
        mArrDropShadowVertices.add(idx,sv);
      }
      if (DRAW_SHADOW && v.mPosZ > radius) {
        ShadowVertex sv=mArrTempShadowVertices.remove(0);
        sv.mPosX=v.mPosX;
        sv.mPosY=v.mPosY;
        sv.mPosZ=v.mPosZ;
        sv.mPenumbraX=((v.mPosZ - radius) / 3) * v.mPenumbraX;
        sv.mPenumbraY=((v.mPosZ - radius) / 3) * v.mPenumbraY;
        sv.mPenumbraColor=(v.mPosZ - radius) / (2 * radius);
        int idx=(mArrSelfShadowVertices.size() + 1) / 2;
        mArrSelfShadowVertices.add(idx,sv);
      }
    }
    scanXmax=scanXmin;
  }
  mBufVertices.position(0);
  mBufColors.position(0);
  if (DRAW_TEXTURE) {
    mBufTexCoords.position(0);
  }
  if (DRAW_SHADOW) {
    mBufShadowColors.position(0);
    mBufShadowVertices.position(0);
    mDropShadowCount=0;
    for (int i=0; i < mArrDropShadowVertices.size(); ++i) {
      ShadowVertex sv=mArrDropShadowVertices.get(i);
      mBufShadowVertices.put((float)sv.mPosX);
      mBufShadowVertices.put((float)sv.mPosY);
      mBufShadowVertices.put((float)sv.mPosZ);
      mBufShadowVertices.put((float)(sv.mPosX + sv.mPenumbraX));
      mBufShadowVertices.put((float)(sv.mPosY + sv.mPenumbraY));
      mBufShadowVertices.put((float)sv.mPosZ);
      for (int j=0; j < 4; ++j) {
        double color=SHADOW_OUTER_COLOR[j] + (SHADOW_INNER_COLOR[j] - SHADOW_OUTER_COLOR[j]) * sv.mPenumbraColor;
        mBufShadowColors.put((float)color);
      }
      mBufShadowColors.put(SHADOW_OUTER_COLOR);
      mDropShadowCount+=2;
    }
    mSelfShadowCount=0;
    for (int i=0; i < mArrSelfShadowVertices.size(); ++i) {
      ShadowVertex sv=mArrSelfShadowVertices.get(i);
      mBufShadowVertices.put((float)sv.mPosX);
      mBufShadowVertices.put((float)sv.mPosY);
      mBufShadowVertices.put((float)sv.mPosZ);
      mBufShadowVertices.put((float)(sv.mPosX + sv.mPenumbraX));
      mBufShadowVertices.put((float)(sv.mPosY + sv.mPenumbraY));
      mBufShadowVertices.put((float)sv.mPosZ);
      for (int j=0; j < 4; ++j) {
        double color=SHADOW_OUTER_COLOR[j] + (SHADOW_INNER_COLOR[j] - SHADOW_OUTER_COLOR[j]) * sv.mPenumbraColor;
        mBufShadowColors.put((float)color);
      }
      mBufShadowColors.put(SHADOW_OUTER_COLOR);
      mSelfShadowCount+=2;
    }
    mBufShadowColors.position(0);
    mBufShadowVertices.position(0);
  }
}

public synchronized void curl ( PointF curlPos , PointF curlDir , double radius ) { if ( DRAW_CURL_POSITION ) { mBufCurlPositionLines . position ( 0 ) ; mBufCurlPositionLines . put ( curlPos . x ) ; mBufCurlPositionLines . put ( curlPos . y - 1.0f ) ; mBufCurlPositionLines . put ( curlPos . x ) ; mBufCurlPositionLines . put ( curlPos . y + 1.0f ) ; mBufCurlPositionLines . put ( curlPos . x - 1.0f ) ; mBufCurlPositionLines . put ( curlPos . y ) ; mBufCurlPositionLines . put ( curlPos . x + 1.0f ) ; mBufCurlPositionLines . put ( curlPos . y ) ; mBufCurlPositionLines . put ( curlPos . x ) ; mBufCurlPositionLines . put ( curlPos . y ) ; mBufCurlPositionLines . put ( curlPos . x + curlDir . x * 2 ) ; mBufCurlPositionLines . put ( curlPos . y + curlDir . y * 2 ) ; mBufCurlPositionLines . position ( 0 ) ; } mBufVertices . position ( 0 ) ; mBufColors . position ( 0 ) ; if ( DRAW_TEXTURE ) { mBufTexCoords . position ( 0 ) ; } double curlAngle = Math . acos ( curlDir . x ) ; curlAngle = curlDir . y > 0 ? - curlAngle : curlAngle ; mArrTempVertices . addAll ( mArrRotatedVertices ) ; mArrRotatedVertices . clear ( ) ; for ( int i = 0 ; i < 4 ; ++ i ) { Vertex v = mArrTempVertices . remove ( 0 ) ; v . set ( mRectangle [ i ] ) ; v . translate ( - curlPos . x , - curlPos . y ) ; v . rotateZ ( - curlAngle ) ; int j = 0 ; for ( ; j < mArrRotatedVertices . size ( ) ; ++ j ) { Vertex v2 = mArrRotatedVertices . get ( j ) ; if ( v . mPosX > v2 . mPosX ) { break ; } if ( v . mPosX == v2 . mPosX && v . mPosY > v2 . mPosY ) { break ; } } mArrRotatedVertices . add ( j , v ) ; } int lines [ ] [ ] = { { 0 , 1 } , { 0 , 2 } , { 1 , 3 } , { 2 , 3 } } ; { Vertex v0 = mArrRotatedVertices . get ( 0 ) ; Vertex v2 = mArrRotatedVertices . get ( 2 ) ; Vertex v3 = mArrRotatedVertices . get ( 3 ) ; double dist2 = Math . sqrt ( ( v0 . mPosX - v2 . mPosX ) * ( v0 . mPosX - v2 . mPosX ) + ( v0 . mPosY - v2 . mPosY ) * ( v0 . mPosY - v2 . mPosY ) ) ; double dist3 = Math . sqrt ( ( v0 . mPosX - v3 . mPosX ) * ( v0 . mPosX - v3 . mPosX ) + ( v0 . mPosY - v3 . mPosY ) * ( v0 . mPosY - v3 . mPosY ) ) ; if ( dist2 > dist3 ) { lines [ 1 ] [ 1 ] = 3 ; lines [ 2 ] [ 1 ] = 2 ; } } mVerticesCountFront = mVerticesCountBack = 0 ; if ( DRAW_SHADOW ) { mArrTempShadowVertices . addAll ( mArrDropShadowVertices ) ; mArrTempShadowVertices . addAll ( mArrSelfShadowVertices ) ; mArrDropShadowVertices . clear ( ) ; mArrSelfShadowVertices . clear ( ) ; } double curlLength = Math . PI * radius ; mArrScanLines . clear ( ) ; if ( mMaxCurlSplits > 0 ) { mArrScanLines . add ( ( double ) 0 ) ; } for ( int i = 1 ; i < mMaxCurlSplits ; ++ i ) { mArrScanLines . add ( ( - curlLength * i ) / ( mMaxCurlSplits - 1 ) ) ; } mArrScanLines . add ( mArrRotatedVertices . get ( 3 ) . mPosX - 1 ) ; double scanXmax = mArrRotatedVertices . get ( 0 ) . mPosX + 1 ; for ( int i = 0 ; i < mArrScanLines . size ( ) ; ++ i ) { double scanXmin = mArrScanLines . get ( i ) ; for ( int j = 0 ; j < mArrRotatedVertices . size ( ) ; ++ j ) { Vertex v = mArrRotatedVertices . get ( j ) ; if ( v . mPosX >= scanXmin && v . mPosX <= scanXmax ) { Vertex n = mArrTempVertices . remove ( 0 ) ; n . set ( v ) ; Array < Vertex > intersections = getIntersections ( mArrRotatedVertices , lines , n . mPosX ) ; if ( intersections . size ( ) == 1 && intersections . get ( 0 ) . mPosY > v . mPosY ) { mArrOutputVertices . addAll ( intersections ) ; mArrOutputVertices . add ( n ) ; } else if ( intersections . size ( ) <= 1 ) { mArrOutputVertices . add ( n ) ; mArrOutputVertices . addAll ( intersections ) ; } else { mArrTempVertices . add ( n ) ; mArrTempVertices . addAll ( intersections ) ; } } } Array < Vertex > intersections = getIntersections ( mArrRotatedVertices , lines , scanXmin ) ; if ( intersections . size ( ) == 2 ) { Vertex v1 = intersections . get ( 0 ) ; Vertex v2 = intersections . get ( 1 ) ; if ( v1 . mPosY < v2 . mPosY ) { mArrOutputVertices . add ( v2 ) ; mArrOutputVertices . add ( v1 ) ; } else { mArrOutputVertices . addAll ( intersections ) ; } } else if ( intersections . size ( ) != 0 ) { mArrTempVertices . addAll ( intersections ) ; } while ( mArrOutputVertices . size ( ) > 0 ) { Vertex v = mArrOutputVertices . remove ( 0 ) ; mArrTempVertices . add ( v ) ; boolean textureFront ; if ( i == 0 ) { textureFront = true ; mVerticesCountFront ++ ; } else if ( i == mArrScanLines . size ( ) - 1 || curlLength == 0 ) { v . mPosX = - ( curlLength + v . mPosX ) ; v . mPosZ = 2 * radius ; v . mPenumbraX = - v . mPenumbraX ; textureFront = false ; mVerticesCountBack ++ ; } else { double rotY = Math . PI * ( v . mPosX / curlLength ) ; v . mPosX = radius * Math . sin ( rotY ) ; v . mPosZ = radius - ( radius * Math . cos ( rotY ) ) ; v . mPenumbraX *= Math . cos ( rotY ) ; v . mColorFactor = ( float ) ( .1f + .9f * Math . sqrt ( Math . sin ( rotY ) + 1 ) ) ; if ( v . mPosZ >= radius ) { textureFront = false ; mVerticesCountBack ++ ; } else { textureFront = true ; mVerticesCountFront ++ ; } } if ( textureFront != mFlipTexture ) { v . mTexX *= mTextureRectFront . right ; v . mTexY *= mTextureRectFront . bottom ; v . mColor = mTexturePage . getColor ( CurlPage . SIDE_FRONT ) ; } else { v . mTexX *= mTextureRectBack . right ; v . mTexY *= mTextureRectBack . bottom ; v . mColor = mTexturePage . getColor ( CurlPage . SIDE_BACK ) ; } v . rotateZ ( curlAngle ) ; v . translate ( curlPos . x , curlPos . y ) ; addVertex ( v ) ; if ( DRAW_SHADOW && v . mPosZ > 0 && v . mPosZ <= radius ) { ShadowVertex sv = mArrTempShadowVertices . remove ( 0 ) ; sv . mPosX = v . mPosX ; sv . mPosY = v . mPosY ; sv . mPosZ = v . mPosZ ; sv . mPenumbraX = ( v . mPosZ / 2 ) * - curlDir . x ; sv . mPenumbraY = ( v . mPosZ / 2 ) * - curlDir . y ; sv . mPenumbraColor = v . mPosZ / radius ; int idx = ( mArrDropShadowVertices . size ( ) + 1 ) / 2 ; mArrDropShadowVertices . add ( idx , sv ) ; } if ( DRAW_SHADOW && v . mPosZ > radius ) { ShadowVertex sv = mArrTempShadowVertices . remove ( 0 ) ; sv . mPosX = v . mPosX ; sv . mPosY = v . mPosY ; sv . mPosZ = v . mPosZ ; sv . mPenumbraX = ( ( v . mPosZ - radius ) / 3 ) * v . mPenumbraX ; sv . mPenumbraY = ( ( v . mPosZ - radius ) / 3 ) * v . mPenumbraY ; sv . mPenumbraColor = ( v . mPosZ - radius ) / ( 2 * radius ) ; int idx = ( mArrSelfShadowVertices . size ( ) + 1 ) / 2 ; mArrSelfShadowVertices . add ( idx , sv ) ; } } scanXmax = scanXmin ; } mBufVertices . position ( 0 ) ; mBufColors . position ( 0 ) ; if ( DRAW_TEXTURE ) { mBufTexCoords . position ( 0 ) ; } if ( DRAW_SHADOW ) { mBufShadowColors . position ( 0 ) ; mBufShadowVertices . position ( 0 ) ; mDropShadowCount = 0 ; for ( int i = 0 ; i < mArrDropShadowVertices . size ( ) ; ++ i ) { ShadowVertex sv = mArrDropShadowVertices . get ( i ) ; mBufShadowVertices . put ( ( float ) sv . mPosX ) ; mBufShadowVertices . put ( ( float ) sv . mPosY ) ; mBufShadowVertices . put ( ( float ) sv . mPosZ ) ; mBufShadowVertices . put ( ( float ) ( sv . mPosX + sv . mPenumbraX ) ) ; mBufShadowVertices . put ( ( float ) ( sv . mPosY + sv . mPenumbraY ) ) ; mBufShadowVertices . put ( ( float ) sv . mPosZ ) ; for ( int j = 0 ; j < 4 ; ++ j ) { double color = SHADOW_OUTER_COLOR [ j ] + ( SHADOW_INNER_COLOR [ j ] - SHADOW_OUTER_COLOR [ j ] ) * sv . mPenumbraColor ; mBufShadowColors . put ( ( float ) color ) ; } mBufShadowColors . put ( SHADOW_OUTER_COLOR ) ; mDropShadowCount += 2 ; } mSelfShadowCount = 0 ; for ( int i = 0 ; i < mArrSelfShadowVertices . size ( ) ; ++ i ) { ShadowVertex sv = mArrSelfShadowVertices . get ( i ) ; mBufShadowVertices . put ( ( float ) sv . mPosX ) ; mBufShadowVertices . put ( ( float ) sv . mPosY ) ; mBufShadowVertices . put ( ( float ) sv . mPosZ ) ; mBufShadowVertices . put ( ( float ) ( sv . mPosX + sv . mPenumbraX ) ) ; mBufShadowVertices . put ( ( float ) ( sv . mPosY + sv . mPenumbraY ) ) ; mBufShadowVertices . put ( ( float ) sv . mPosZ ) ; for ( int j = 0 ; j < 4 ; ++ j ) { double color = SHADOW_OUTER_COLOR [ j ] + ( SHADOW_INNER_COLOR [ j ] - SHADOW_OUTER_COLOR [ j ] ) * sv . mPenumbraColor ; mBufShadowColors . put ( ( float ) color ) ; } mBufShadowColors . put ( SHADOW_OUTER_COLOR ) ; mSelfShadowCount += 2 ; } mBufShadowColors . position ( 0 ) ; mBufShadowVertices . position ( 0 ) ; } }
sets curl for this mesh .
