Esempio n. 1
0
void SoRing::generatePrimitives(SoAction* action)
{
  SoPrimitiveVertex pv;

  int nbSlices = (int)((float)NbTrianglesPerRing*sweepAngle.getValue()/360.F);
  if ( nbSlices < 3 ) nbSlices = 3;
  float angleInc = (sweepAngle.getValue())*M_PI/180.F/float(nbSlices);

  float R1 = innerRadius.getValue();
  float R2 = outerRadius.getValue();
  float radiiRatio = R1/R2;
  float Xc, Yc;
  center.getValue().getValue(Xc,Yc);

  beginShape(action, SoShape::TRIANGLE_STRIP);

  float angle = sweepAngle.getValue()*M_PI/180.F;

  // point at outer radius
  pv.setPoint(SbVec3f(R2*cos(angle)+Xc,R2*sin(angle)+Yc,0));
  pv.setNormal(normal);
  pv.setTextureCoords(SbVec4f(0.5f*(1+cos(angle)),
                              0.5f*(1+sin(angle)), 0, 1));
  shapeVertex(&pv);

  // point at inner radius
  pv.setPoint(SbVec3f(R1*cos(angle)+Xc,R1*sin(angle)+Yc,0));
  pv.setNormal(normal);
  pv.setTextureCoords(SbVec4f(0.5f*(1+radiiRatio*cos(angle)),
                              0.5f*(1+radiiRatio*sin(angle)), 0, 1));
  shapeVertex(&pv);


  for ( int i = 0; i < nbSlices; i++ )
  {
    angle -= angleInc;

    // outer radius
    pv.setPoint(SbVec3f((float)(R2*cos(angle))+Xc,(float)(R2*sin(angle))+Yc,0));
    pv.setNormal(normal);
    pv.setTextureCoords(SbVec4f(0.5f*(1+cos(angle)),
                                0.5f*(1+sin(angle)), 0, 1));
    shapeVertex(&pv);

    // inner radius
    pv.setPoint(SbVec3f((float)(R1*cos(angle))+Xc,(float)(R1*sin(angle)+Yc),0));
    pv.setNormal(normal);
    pv.setTextureCoords(SbVec4f(0.5f*(1+radiiRatio*cos(angle)),
                                0.5f*(1+radiiRatio*sin(angle)), 0, 1));
    shapeVertex(&pv);
  }
  endShape();
}
Esempio n. 2
0
void
SoCylinder::generatePrimitives(SoAction *action)
//
////////////////////////////////////////////////////////////////////////
{
    SbBool		materialPerPart;
    int			curParts, numSides, numSections, side, section;
    float		yTop, yBot, dy;
    float		s, ds, tTop, tBot, dt;
    float		outerRadius, innerRadius, dRadius;
    SbVec2f		*ringCoords;
    SbVec3f		pt, norm;
    float		radius, halfHeight;
    SbVec4f		tex;
    SbBool		genTexCoords;
    SoPrimitiveVertex	pv;
    SoCylinderDetail	detail;
    const SoTextureCoordinateElement	*tce;

    SoMaterialBindingElement::Binding mbe =
	SoMaterialBindingElement::get(action->getState());
    materialPerPart =
	(mbe == SoMaterialBindingElement::PER_PART_INDEXED ||
	 mbe == SoMaterialBindingElement::PER_PART);

    curParts = (parts.isIgnored() ? ALL : parts.getValue());

    // Compute number of sides and sections to use to represent
    // cylinder, then compute ring of x,z coordinates around cylinder
    // and store in ringCoords.
    computeRing(action, numSides, numSections, ringCoords);

    pv.setDetail(&detail);

    // Determine whether we should generate our own texture coordinates
    switch (SoTextureCoordinateElement::getType(action->getState())) {
      case SoTextureCoordinateElement::EXPLICIT:
	genTexCoords = TRUE;
	break;
      case SoTextureCoordinateElement::FUNCTION:
	genTexCoords = FALSE;
	break;
    }

    // If we're not generating our own coordinates, we'll need the
    // texture coordinate element to get coords based on points/normals.
    if (! genTexCoords)
	tce = SoTextureCoordinateElement::getInstance(action->getState());
    else {
	tex[2] = 0.0;
	tex[3] = 1.0;
    }

    getSize(radius, halfHeight);

    if (HAS_PART(curParts, SIDES)) {

	// Draw each section of sides as a triangle mesh, from top to bottom
	yTop = 1.0;
	dy   = -2.0 / numSections;
	tTop = 1.0;
	dt   = -1.0 / numSections;
	ds   = -1.0 / numSides;

	for (section = 0; section < numSections; section++) {

	    yBot = yTop + dy;

	    tBot = tTop + dt;
	    s    = 1.0;

	    detail.setPart(SIDES);

	    beginShape(action, TRIANGLE_STRIP);

	    for (side = 0; side < numSides; side++) {
		pt[0] = ringCoords[side][0];
		pt[2] = ringCoords[side][1];

		// Deal with normal
		norm.setValue(pt[0], 0.0, pt[2]);
		pv.setNormal(norm);

		// Point at bottom of section
		pt[1] = yBot;
		pt[0] *= radius;
		pt[1] *= halfHeight;
		pt[2] *= radius;

		if (genTexCoords) {
		    tex[0] = s;
		    tex[1] = tBot;
		}
		else
		    tex = tce->get(pt, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);

		// Point at top of section
		pt[1] = yTop;
		pt[1] *= halfHeight;
		if (genTexCoords) {
		    tex[0] = s;
		    tex[1] = tTop;
		}
		else
		    tex = tce->get(pt, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);
		s += ds;
	    }

	    // Join end of strip back to beginning
	    side = 0;
	    s = 0.0;
	    pt[0] = ringCoords[side][0];
	    pt[2] = ringCoords[side][1];

	    // Deal with normal
	    norm.setValue(pt[0], 0.0, pt[2]);
	    pv.setNormal(norm);

	    // Point at bottom of section
	    pt[1] = yBot;
	    pt[0] *= radius;
	    pt[1] *= halfHeight;
	    pt[2] *= radius;

	    if (genTexCoords) {
		tex[0] = s;
		tex[1] = tBot;
	    }
	    else
		tex = tce->get(pt, norm);
	    pv.setPoint(pt);
	    pv.setTextureCoords(tex);
	    shapeVertex(&pv);

	    // Point at top of section
	    pt[1] = yTop;
	    pt[1] *= halfHeight;
	    if (genTexCoords) {
		tex[0] = s;
		tex[1] = tTop;
	    }
	    else
		tex = tce->get(pt, norm);
	    pv.setPoint(pt);
	    pv.setTextureCoords(tex);
	    shapeVertex(&pv);
	    s += ds;

	    endShape();

	    // Prepare for next section down
	    yTop = yBot;
	    tTop = tBot;
	}
    }

    // Draw top face as a series of concentric rings. The number of
    // rings is the same as the number of sections of the sides of the
    // cylinder.
    if (HAS_PART(curParts, TOP)) {
	norm.setValue(0.0, 1.0, 0.0);
	pt[1] = halfHeight;

	if (materialPerPart)
	    pv.setMaterialIndex(1);
	pv.setNormal(norm);
	detail.setPart(TOP);

	// Start at the outside and work in
	outerRadius = 1.0;
	dRadius     = -1.0 / numSections;
	for (section = numSections - 1; section >= 0; --section) {

	    innerRadius = outerRadius + dRadius;

	    // Innermost ring is treated as a triangle fan. This not
	    // only gets better shading (because the center vertex is
	    // sent), but also avoids the problem of having a polygon
	    // with too many vertices.
	    if (section == 0) {
		beginShape(action, TRIANGLE_FAN);

		// Center point comes first
		pt[0] = pt[2] = 0.0;
		if (genTexCoords)
		    tex[0] = tex[1] = 0.5;
		else
		    tex = tce->get(norm, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);

		// Send all vertices around ring. Go in reverse order
		// so that vertex ordering is correct
		for (side = numSides - 1; side >= 0; side--) {
		    pt[0] = outerRadius * ringCoords[side][0];
		    pt[2] = outerRadius * ringCoords[side][1];
		    pt[0] *= radius;
		    pt[2] *= radius;
		    if (genTexCoords) {
			tex[0] = TOP_TEX_S(pt[0]);
			tex[1] = TOP_TEX_T(pt[2]);
		    }
		    else
			tex = tce->get(pt, norm);
		    pv.setPoint(pt);
		    pv.setTextureCoords(tex);
		    shapeVertex(&pv);
		}
		// Send first vertex again
		pt[0] = outerRadius * ringCoords[numSides - 1][0];
		pt[2] = outerRadius * ringCoords[numSides - 1][1];
		pt[0] *= radius;
		pt[2] *= radius;
		if (genTexCoords) {
		    tex[0] = TOP_TEX_S(pt[0]);
		    tex[1] = TOP_TEX_T(pt[2]);
		}
		else
		    tex = tce->get(pt, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);

		endShape();
	    }

	    // Other rings are triangle strips
	    else {
		beginShape(action, TRIANGLE_STRIP);

		for (side = 0; side < numSides; side++) {
		    // Send points on outer and inner rings
		    pt[0] = outerRadius * ringCoords[side][0];
		    pt[2] = outerRadius * ringCoords[side][1];
		    pt[0] *= radius;
		    pt[2] *= radius;
		    if (genTexCoords) {
			tex[0] = TOP_TEX_S(pt[0]);
			tex[1] = TOP_TEX_T(pt[2]);
		    }
		    else
			tex = tce->get(pt, norm);
		    pv.setPoint(pt);
		    pv.setTextureCoords(tex);
		    shapeVertex(&pv);
		    pt[0] = innerRadius * ringCoords[side][0];
		    pt[2] = innerRadius * ringCoords[side][1];
		    pt[0] *= radius;
		    pt[2] *= radius;
		    if (genTexCoords) {
			tex[0] = TOP_TEX_S(pt[0]);
			tex[1] = TOP_TEX_T(pt[2]);
		    }
		    else
			tex = tce->get(pt, norm);
		    pv.setPoint(pt);
		    pv.setTextureCoords(tex);
		    shapeVertex(&pv);
		}

		// Join end of strip back to beginning
		pt[0] = outerRadius * ringCoords[0][0];
		pt[2] = outerRadius * ringCoords[0][1];
		pt[0] *= radius;
		pt[2] *= radius;
		if (genTexCoords) {
		    tex[0] = TOP_TEX_S(pt[0]);
		    tex[1] = TOP_TEX_T(pt[2]);
		}
		else
		    tex = tce->get(pt, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);
		pt[0] = innerRadius * ringCoords[0][0];
		pt[2] = innerRadius * ringCoords[0][1];
		pt[0] *= radius;
		pt[2] *= radius;
		if (genTexCoords) {
		    tex[0] = TOP_TEX_S(pt[0]);
		    tex[1] = TOP_TEX_T(pt[2]);
		}
		else
		    tex = tce->get(pt, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);

		endShape();

		// Prepare for next ring
		outerRadius = innerRadius;
	    }
	}
    }

    // Draw bottom face the same way as the top
    if (HAS_PART(curParts, BOTTOM)) {
	norm.setValue(0.0, -1.0, 0.0);
	pt[1] = -halfHeight;

	if (materialPerPart)
	    pv.setMaterialIndex(2);
	pv.setNormal(norm);
	detail.setPart(BOTTOM);

	// Start at the outside and work in
	outerRadius = 1.0;
	dRadius     = -1.0 / numSections;
	for (section = numSections - 1; section >= 0; --section) {

	    innerRadius = outerRadius + dRadius;

	    // Innermost ring is drawn as a triangle fan. This not
	    // only gets better shading (because the center vertex is
	    // sent), but also avoids the problem of having a polygon
	    // with too many vertices.
	    if (section == 0) {
		beginShape(action, TRIANGLE_FAN);

		// Center point comes first
		pt[0] = pt[2] = 0.0;
		if (genTexCoords)
		    tex[0] = tex[1] = 0.5;
		else
		    tex = tce->get(norm, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);

		// Send all vertices around ring
		for (side = 0; side < numSides; side++) {
		    pt[0] = outerRadius * ringCoords[side][0];
		    pt[2] = outerRadius * ringCoords[side][1];
		    pt[0] *= radius;
		    pt[2] *= radius;
		    if (genTexCoords) {
			tex[0] = BOT_TEX_S(pt[0]);
			tex[1] = BOT_TEX_T(pt[2]);
		    }
		    else
			tex = tce->get(pt, norm);
		    pv.setPoint(pt);
		    pv.setTextureCoords(tex);
		    shapeVertex(&pv);
		}
		// Send first vertex again
		pt[0] = outerRadius * ringCoords[0][0];
		pt[2] = outerRadius * ringCoords[0][1];
		pt[0] *= radius;
		pt[2] *= radius;
		if (genTexCoords) {
		    tex[0] = BOT_TEX_S(pt[0]);
		    tex[1] = BOT_TEX_T(pt[2]);
		}
		else
		    tex = tce->get(pt, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);

		endShape();
	    }

	    // Other rings are triangle strips
	    else {
		beginShape(action, TRIANGLE_STRIP);

		// Go in reverse order so that vertex ordering is correct
		for (side = numSides - 1; side >= 0; side--) {
		    // Send points on outer and inner rings
		    pt[0] = outerRadius * ringCoords[side][0];
		    pt[2] = outerRadius * ringCoords[side][1];
		    pt[0] *= radius;
		    pt[2] *= radius;
		    if (genTexCoords) {
			tex[0] = BOT_TEX_S(pt[0]);
			tex[1] = BOT_TEX_T(pt[2]);
		    }
		    else
			tex = tce->get(pt, norm);
		    pv.setPoint(pt);
		    pv.setTextureCoords(tex);
		    shapeVertex(&pv);
		    pt[0] = innerRadius * ringCoords[side][0];
		    pt[2] = innerRadius * ringCoords[side][1];
		    pt[0] *= radius;
		    pt[2] *= radius;
		    if (genTexCoords) {
			tex[0] = BOT_TEX_S(pt[0]);
			tex[1] = BOT_TEX_T(pt[2]);
		    }
		    else
			tex = tce->get(pt, norm);
		    pv.setPoint(pt);
		    pv.setTextureCoords(tex);
		    shapeVertex(&pv);
		}

		// Join end of strip back to beginning
		side = numSides - 1;
		pt[0] = outerRadius * ringCoords[side][0];
		pt[2] = outerRadius * ringCoords[side][1];
		pt[0] *= radius;
		pt[2] *= radius;
		if (genTexCoords) {
		    tex[0] = BOT_TEX_S(pt[0]);
		    tex[1] = BOT_TEX_T(pt[2]);
		}
		else
		    tex = tce->get(pt, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);
		pt[0] = innerRadius * ringCoords[side][0];
		pt[2] = innerRadius * ringCoords[side][1];
		pt[0] *= radius;
		pt[2] *= radius;
		if (genTexCoords) {
		    tex[0] = BOT_TEX_S(pt[0]);
		    tex[1] = BOT_TEX_T(pt[2]);
		}
		else
		    tex = tce->get(pt, norm);
		pv.setPoint(pt);
		pv.setTextureCoords(tex);
		shapeVertex(&pv);

		endShape();

		// Prepare for next ring
		outerRadius = innerRadius;
	    }
	}
    }
}
void ShapeParabolicRectangle::generatePrimitives(SoAction *action)
{
    SoPrimitiveVertex   pv;
    SoState  *state = action->getState();

    SbBool useTexFunc = ( SoTextureCoordinateElement::getType(state) ==
                          SoTextureCoordinateElement::FUNCTION );

    const SoTextureCoordinateElement* tce = 0;
    if ( useTexFunc ) tce = SoTextureCoordinateElement::getInstance(state);


    SbVec3f  point;
 	const int rows = 12; // Number of points per row
    const int columns = 12; // Number of points per column
    const int totalPoints = (rows)*(columns); // Total points in the grid

    float vertex[totalPoints][6];

    int h = 0;
    double ui = 0;
	double vj = 0;

    for (int i = 0; i < rows; ++i )
    {
    	ui =( 1.0 /(double)(rows-1) ) * i;

    	for ( int j = 0 ; j < columns ; ++j )
    	{
    		vj = ( 1.0 /(double)(columns-1) ) * j;

    		Point3D point = GetPoint3D(ui, vj);
    		NormalVector normal;
    		if( activeSide.getValue() == 0 )	normal = -GetNormal(ui, vj);
    		else	normal = GetNormal(ui, vj);

    		vertex[h][0] = point.x;
    		vertex[h][1] = point.y;
    		vertex[h][2] = point.z;
    		vertex[h][3] = normal.x;
    		vertex[h][4] = normal.y;
    		vertex[h][5] = normal.z;

    		pv.setPoint( vertex[h][0], vertex[h][1], vertex[h][2] );
    		h++; //Increase h to the next point.

    	}
    }

    float u = 1;
    float v = 1;
    beginShape(action, QUADS );
	for( int irow = 0; irow < (rows-1); ++irow )
	{
		for( int icolumn = 0; icolumn < (columns-1); ++icolumn )
		{
			int index0 = irow*columns + icolumn;
			SbVec3f  point0( vertex[index0][0], vertex[index0][1],  vertex[index0][2] );
			SbVec3f normal0(vertex[index0][3], vertex[index0][4], vertex[index0][5] );
			SbVec4f texCoord0 = useTexFunc ? tce->get(point0, normal0): SbVec4f( u,v, 0.0, 1.0 );
			pv.setPoint(point0);
			pv.setNormal(normal0);
			pv.setTextureCoords(texCoord0);
			shapeVertex(&pv);

			int index1 = index0 + 1;
			SbVec3f  point1( vertex[index1][0], vertex[index1][1],  vertex[index1][2] );
			SbVec3f normal1(vertex[index1][3], vertex[index1][4], vertex[index1][5] );
			SbVec4f texCoord1 = useTexFunc ? tce->get(point1, normal1): SbVec4f( u,v, 0.0, 1.0 );
			pv.setPoint(point1);
			pv.setNormal(normal1);
			pv.setTextureCoords(texCoord1);
			shapeVertex(&pv);

			int index3 = index0 + columns;
			int index2 = index3 + 1;

			SbVec3f  point2( vertex[index2][0], vertex[index2][1],  vertex[index2][2] );
			SbVec3f normal2(vertex[index2][3], vertex[index2][4], vertex[index2][5] );
			SbVec4f texCoord2 = useTexFunc ? tce->get(point2, normal2): SbVec4f( u,v, 0.0, 1.0 );
			pv.setPoint(point2);
			pv.setNormal(normal2);
			pv.setTextureCoords(texCoord2);
			shapeVertex(&pv);

			SbVec3f  point3( vertex[index3][0], vertex[index3][1],  vertex[index3][2] );
			SbVec3f normal3(vertex[index3][3], vertex[index3][4], vertex[index3][5] );
			SbVec4f texCoord3 = useTexFunc ? tce->get(point3, normal3): SbVec4f( u,v, 0.0, 1.0 );
			pv.setPoint(point3);
			pv.setNormal(normal3);
			pv.setTextureCoords(texCoord3);
			shapeVertex(&pv);

		}
	}

	endShape();

}