void CubeMapRenderer::render(const CubeMapTextureObject& cubeMapTexture, const ICamera<float>& camera, const TriangleBuffer& buffer) { const auto& positions = buffer.getPositions().get();// buffers[0].get(); const auto& normals = buffer.getNormals().get();//buffers[1].get(); if (positions.empty()) { return; } cubeMapTexture.bind(); glEnable(GL_DEPTH_TEST); glUseProgram(shader.getId()); //cubeMapTexture.bind(); // glUniform1f(shader.getUniformLocation("reflectFactor"), 0.8f); // glUniform1f(shader.getUniformLocation("refractFactor"), 1.2f); assert(GL_NO_ERROR == glGetError()); glUniform1i(shader.getUniformLocation("cubeMapTex"), cubeMapTexture.getId());// volumeTexture.getId()); glUniform3fv(shader.getUniformLocation("eyePosition"), 1, camera.getPosition().toArray().data()); assert(GL_NO_ERROR == glGetError()); glUniformMatrix4fv(shader.getUniformLocation("modelviewMatrix"), 1, false, camera.getModelviewMatrix().toArray().data()); glUniformMatrix4fv(shader.getUniformLocation("projectionMatrix"), 1, false, camera.getProjectionMatrix().toArray().data()); assert(GL_NO_ERROR == glGetError()); glVertexAttribPointer(shader.getAttribLocation("position"), 3, GL_FLOAT, GL_FALSE, 0, positions.data()); glVertexAttribPointer(shader.getAttribLocation("normal"), 3, GL_FLOAT, GL_FALSE, 0, normals.data()); assert(GL_NO_ERROR == glGetError()); assert(GL_NO_ERROR == glGetError()); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); for (const auto& b : buffer.getBlocks()) { const auto& indices = b.getIndices(); glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, indices.data()); } glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glBindFragDataLocation(shader.getId(), 0, "fragColor"); cubeMapTexture.unbind(); glDisable(GL_DEPTH_TEST); glUseProgram(0); }
void TorusGenerator::AddToTriangleBuffer(TriangleBuffer& Buffer) const { Buffer.RebaseOffset(); Buffer.EstimateVertexCount( ( this->NumPoloidalSeg + 1 ) * ( this->NumToroidalSeg + 1 ) ); Buffer.EstimateIndexCount( ( this->NumPoloidalSeg ) * ( this->NumToroidalSeg + 1 ) * 6 ); Real deltaSection = ( MathTools::GetTwoPi() / this->NumToroidalSeg ); Real deltaCircle = ( MathTools::GetTwoPi() / this->NumPoloidalSeg ); Integer Offset = 0; for( Whole i = 0 ; i <= this->NumPoloidalSeg ; i++ ) { for( Whole j = 0 ; j<= this->NumToroidalSeg ; j++ ) { Vector3 c0( this->TorusPoloidalRadius, 0.0, 0.0 ); Vector3 v0( this->TorusPoloidalRadius + this->TorusToroidalRadius * cosf( j * deltaSection ), this->TorusToroidalRadius * sinf( j * deltaSection ), 0.0 ); Quaternion q( i * deltaCircle, Vector3::Unit_Y() ); Vector3 v = q * v0; Vector3 c = q * c0; this->AddPoint( Buffer, v, ( v - c ).GetNormal(), Vector2( i / (Real)this->NumPoloidalSeg, j / (Real)this->NumToroidalSeg ) ); if( i != this->NumPoloidalSeg ) { Buffer.AddIndex( Offset + this->NumToroidalSeg + 1 ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + this->NumToroidalSeg ); Buffer.AddIndex( Offset + this->NumToroidalSeg + 1 ); Buffer.AddIndex( Offset + 1 ); Buffer.AddIndex( Offset ); } Offset++; } } }
void LegacyRenderer::render(const ICamera<float>& camera, const PointLight<float>& light, const TriangleBuffer& buffer) { const auto& positions = buffer.getPositions().get();// buffers[0].get(); const auto& normals = buffer.getNormals().get();//buffers[1].get(); if (positions.empty()) { return; } glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); const auto& projectionMatrix = camera.getProjectionMatrix(); const auto& modelviewMatrix = camera.getModelviewMatrix();; std::vector<float> lightPos = { light.getPos().getX(), light.getPos().getY(), light.getPos().getZ(), 1.0 }; glLightfv(GL_LIGHT0, GL_POSITION, lightPos.data()); glLightfv(GL_LIGHT0, GL_DIFFUSE, light.getDiffuse().toArray4().data()); // glLightfv(GL_LIGHT0, GL_SPECULAR, light.getSpecular().toArray4().data()); glLightfv(GL_LIGHT0, GL_AMBIENT, white); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glLoadMatrixf(projectionMatrix.toArray().data()); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(modelviewMatrix.toArray().data()); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, yellow); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, positions.data()); glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, normals.data()); //glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(positions.size()) / 3); for (const auto& b : buffer.getBlocks()) { const auto& indices = b.getIndices(); glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, indices.data()); } glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); glDisable(GL_DEPTH_TEST); }
void TorusKnotGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(mNumSegSection>0 && mNumSegCircle>0 && "Num seg and circle must be positive"); assert(mRadius>0. && mSectionRadius>0. && "Radius and section radius must be positive"); assert(mP>0 && mQ>0 && "p and q must be positive"); buffer.rebaseOffset(); buffer.estimateVertexCount((mNumSegCircle*mP+1)*(mNumSegSection+1)); buffer.estimateIndexCount((mNumSegCircle*mP)*(mNumSegSection+1)*6); int offset = 0; for (int i = 0; i <= mNumSegCircle * mP;i++) { Real phi = Math::TWO_PI * i/(Real)mNumSegCircle; Real x0 = mRadius*(2 + cos(mQ*phi/(Real)mP)) * cos(phi) / 3.f; Real y0 = mRadius*sin(mQ*phi/(Real)mP) / 3.f; Real z0 = mRadius*(2 + cos(mQ*phi/(Real)mP)) * sin(phi) / 3.f; Real phi1 = Math::TWO_PI * (i+1)/(Real)mNumSegCircle; Real x1 = mRadius*(2 + cos(mQ*phi1/(Real)mP)) * cos(phi1) / 3.f; Real y1 = mRadius*sin(mQ*phi1/mP) / 3.f; Real z1 = mRadius*(2 + cos(mQ*phi1/(Real)mP)) * sin(phi1) / 3.f; Vector3 v0(x0,y0,z0); Vector3 v1(x1,y1,z1); Vector3 direction((v1-v0).normalisedCopy()); Quaternion q = Utils::_computeQuaternion(direction); for (int j =0;j<=mNumSegSection;j++) { Real alpha = Math::TWO_PI *j/mNumSegSection; Vector3 vp = mSectionRadius*(q * Vector3(cos(alpha), sin(alpha),0)); addPoint(buffer, v0+vp, vp.normalisedCopy(), Vector2(i/(Real)mNumSegCircle, j/(Real)mNumSegSection)); if (i != mNumSegCircle * mP) { buffer.index(offset + mNumSegSection + 1); buffer.index(offset + mNumSegSection); buffer.index(offset); buffer.index(offset + mNumSegSection + 1); buffer.index(offset); buffer.index(offset + 1); } offset ++; } } }
void SphereUVModifier::Modify(TriangleBuffer& Buffer) { for( VertexIterator VertIt = Buffer.GetVertices().begin() ; VertIt != Buffer.GetVertices().end() ; ++VertIt ) { Vector3 NormalizedPos = VertIt->Position.GetNormal(); Vector2 VecXZ(NormalizedPos.X,NormalizedPos.Z); VertIt->UV.X = Vector2::Unit_X().AngleTo(VecXZ) / MathTools::GetTwoPi(); VertIt->UV.Y = ( MathTools::ATan(NormalizedPos.Y / VecXZ.Length()) + MathTools::GetHalfPi() ) / MathTools::GetPi(); } }
//----------------------------------------------------------------------- void Lathe::_latheBodyImpl(TriangleBuffer& buffer, const Shape* shapeToExtrude) const { int numSegShape = shapeToExtrude->getSegCount(); assert(numSegShape>1 && "Shape must contain at least two points"); int offset =0; //int numSeg = mClosed?mNumSeg+1:mNumSeg; int numSeg = mNumSeg+1; buffer.rebaseOffset(); buffer.estimateIndexCount(numSeg*numSegShape*6); buffer.estimateVertexCount((numSegShape+1)*(numSeg+1)); Radian angleEnd(mAngleEnd); if (mAngleBegin>mAngleEnd) angleEnd+=(Radian)Math::TWO_PI; for (int i=0;i<numSeg;i++) { Radian angle; if (mClosed) angle = i/(Real)mNumSeg*Math::TWO_PI; else angle = mAngleBegin + i/(Real)mNumSeg*(angleEnd-mAngleBegin); Quaternion q; q.FromAngleAxis(angle,Vector3::UNIT_Y); for (int j=0;j<=numSegShape;j++) { const Vector2& v0 = shapeToExtrude->getPoint(j); Vector3 vp(v0.x,v0.y,0); const Vector2& vp2direction = shapeToExtrude->getAvgDirection(j); Vector2 vp2normal = vp2direction.perpendicular(); Vector3 normal(vp2normal.x, vp2normal.y, 0); normal.normalise(); if (shapeToExtrude->getOutSide() == SIDE_RIGHT) normal = -normal; addPoint(buffer, q*vp, q*normal, Vector2(i/(Real)mNumSeg, j/(Real)numSegShape)); if (j <numSegShape && i <numSeg-1) { if (shapeToExtrude->getOutSide() == SIDE_RIGHT) { buffer.triangle(offset + numSegShape + 2, offset, offset + numSegShape + 1); buffer.triangle(offset + numSegShape + 2, offset + 1, offset); } else { buffer.triangle(offset + numSegShape + 2, offset + numSegShape + 1, offset); buffer.triangle(offset + numSegShape + 2, offset, offset + 1); } } offset ++; } } }
void VertexNormalsModifier::Modify(TriangleBuffer& Buffer) { const IndexContainer& Indices = Buffer.GetIndices(); VertexContainer& Vertices = Buffer.GetVertices(); if( this->Compute == VertexNormalsModifier::CM_Triangle ) { for( Whole Index = 0 ; Index < Indices.size() ; Index += 3 ) { Vector3 v1 = Vertices[Indices[Index]].Position; Vector3 v2 = Vertices[Indices[Index+1]].Position; Vector3 v3 = Vertices[Indices[Index+2]].Position; Vector3 VertNormal = (v2-v1).CrossProduct(v3-v1).GetNormal(); Vertices[Indices[Index]].Normal = VertNormal; Vertices[Indices[Index+1]].Normal = VertNormal; Vertices[Indices[Index+2]].Normal = VertNormal; } }else if( this->Compute == VertexNormalsModifier::CM_Vertex ) { std::vector< std::vector<Vector3> > TempNormals; TempNormals.resize(Vertices.size()); for( Whole Index = 0 ; Index < Indices.size() ; Index += 3 ) { Vector3 v1 = Vertices[Indices[Index]].Position; Vector3 v2 = Vertices[Indices[Index+1]].Position; Vector3 v3 = Vertices[Indices[Index+2]].Position; Vector3 VertNormal = (v2-v1).CrossProduct(v3-v1); TempNormals[Indices[Index]].push_back(VertNormal); TempNormals[Indices[Index+1]].push_back(VertNormal); TempNormals[Indices[Index+2]].push_back(VertNormal); } for( Whole CurrVertex = 0 ; CurrVertex < Vertices.size() ; ++CurrVertex ) { Vector3 VertNormal(0.0,0.0,0.0); for( Whole CurrNormal = 0 ; CurrNormal < TempNormals[CurrVertex].size() ; ++CurrNormal ) { VertNormal += TempNormals[CurrVertex][CurrNormal]; } Vertices[CurrVertex].Normal = VertNormal.GetNormal(); } } }
void BoxUVModifier::Modify(TriangleBuffer& Buffer) { static const Vector3 Directions[6] = { Vector3::Unit_X(), Vector3::Unit_Y(), Vector3::Unit_Z(), Vector3::Neg_Unit_X(), Vector3::Neg_Unit_Y(), Vector3::Neg_Unit_Z() }; for( VertexIterator VertIt = Buffer.GetVertices().begin() ; VertIt != Buffer.GetVertices().end() ; ++VertIt ) { Vector3 VertPos = VertIt->Position - this->BoxPosition; if( !VertPos.IsZeroLength() ) { //VertPos.Normalize(); VertPos.X /= ( this->BoxHalfExtents.X * 2.0 ); VertPos.Y /= ( this->BoxHalfExtents.Y * 2.0 ); VertPos.Z /= ( this->BoxHalfExtents.Z * 2.0 ); Vector3 VertNorm = VertIt->Normal; Real MaxAxis = 0; Integer PrincipalAxis = 0; for( UInt8 AxisIndex = 0 ; AxisIndex < 6 ; ++AxisIndex ) { if( Directions[AxisIndex].DotProduct(VertNorm) > MaxAxis ) { MaxAxis = Directions[AxisIndex].DotProduct(VertNorm); PrincipalAxis = AxisIndex; } } Vector3 vX, vY; if( PrincipalAxis % 3 == 1 ) { vY = Vector3::Unit_X(); }else{ vY = Vector3::Unit_Y(); } vX = Directions[PrincipalAxis].CrossProduct(vY); Vector2 UVCoord( 0.5 - vX.DotProduct(VertPos), 0.5 - vY.DotProduct(VertPos) ); if( this->Mapping == BoxUVModifier::MT_Full ) { VertIt->UV = UVCoord; }else if( this->Mapping == BoxUVModifier::MT_Cross ) { // Too lazy to think of a more elegant solution switch( PrincipalAxis ) { case 1: VertIt->UV = Vector2( ( UVCoord.X + 2 ) / 4, ( UVCoord.Y + 1 ) / 3 ); break; // 3,2 case 2: VertIt->UV = Vector2( ( UVCoord.X + 1 ) / 4, UVCoord.Y / 3 ); break; // 2,1 case 3: VertIt->UV = Vector2( ( UVCoord.X + 3 ) / 4, ( UVCoord.Y + 1 ) / 3 ); break; // 4,2 case 4: VertIt->UV = Vector2( UVCoord.X / 4, ( UVCoord.Y + 1 ) / 3 ); break; // 1,2 case 5: VertIt->UV = Vector2( ( UVCoord.X + 1 ) / 4, ( UVCoord.Y + 2 ) / 3 ); break; // 2,3 case 6: VertIt->UV = Vector2( ( UVCoord.X + 1 ) / 4, ( UVCoord.Y + 1 ) / 3 ); break; // 2,2 } }else if( this->Mapping == BoxUVModifier::MT_Packed ) { VertIt->UV = Vector2( ( UVCoord.X + PrincipalAxis % 3 ) / 3, ( UVCoord.Y + PrincipalAxis / 3 ) / 2 ); } } } }
void Lathe::addToTriangleBuffer(TriangleBuffer& buffer) const { assert( mShapeToExtrude && "Shape must not be null!"); int numSegShape = mShapeToExtrude->getSegCount(); assert(numSegShape>1 && "Shape must contain at least two points"); int offset =0; buffer.rebaseOffset(); buffer.estimateIndexCount(mNumSeg*numSegShape*6); buffer.estimateVertexCount((numSegShape+1)*(mNumSeg+1)); for (int i=0;i<=mNumSeg;i++) { Real angle = i/(Real)mNumSeg*Math::TWO_PI; Quaternion q; q.FromAngleAxis((Radian)angle,Vector3::UNIT_Y); for (int j=0;j<=numSegShape;j++) { Vector2 v0 = mShapeToExtrude->getPoint(j); Vector3 vp(v0.x,v0.y,0); Vector2 vp2direction = mShapeToExtrude->getAvgDirection(j); Vector2 vp2normal = vp2direction.perpendicular(); Vector3 normal(vp2normal.x, vp2normal.y, 0); normal.normalise(); if (mShapeToExtrude->getOutSide() == SIDE_LEFT) { normal = -normal; } addPoint(buffer, q*vp, q*normal, Vector2(i/(Real)mNumSeg, j/(Real)numSegShape)); if (j <numSegShape && i <mNumSeg) { buffer.index(offset + numSegShape + 2); buffer.index(offset); buffer.index(offset + numSegShape + 1); buffer.index(offset + numSegShape + 2); buffer.index(offset + 1); buffer.index(offset); } offset ++; } } }
void SphereGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(mNumRings>0 && mNumSegments>0 && "Num seg must be positive"); assert(mRadius>0 && "Radius must be positive"); buffer.rebaseOffset(); buffer.estimateVertexCount((mNumRings+1)*(mNumSegments+1)); buffer.estimateIndexCount(mNumRings*(mNumSegments+1)*6); Real fDeltaRingAngle = (Math::PI / mNumRings); Real fDeltaSegAngle = (Math::TWO_PI / mNumSegments); int offset = 0; // Generate the group of rings for the sphere for(unsigned int ring = 0; ring <= mNumRings; ring++ ) { Real r0 = mRadius * sinf (ring * fDeltaRingAngle); Real y0 = mRadius * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(unsigned int seg = 0; seg <= mNumSegments; seg++) { Real x0 = r0 * sinf(seg * fDeltaSegAngle); Real z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere addPoint(buffer, Vector3(x0, y0, z0), Vector3(x0, y0, z0).normalisedCopy(), Vector2((Real) seg / (Real) mNumSegments, (Real) ring / (Real) mNumRings)); if (ring != mNumRings) { // each vertex (except the last) has six indices pointing to it buffer.index(offset + mNumSegments + 1); buffer.index(offset); buffer.index(offset + mNumSegments); buffer.index(offset + mNumSegments + 1); buffer.index(offset + 1); buffer.index(offset); offset ++; } }; // end for seg } // end for ring }
//----------------------------------------------------------------------- void Lathe::_latheCapImpl(TriangleBuffer& buffer) const { std::vector<int> indexBuffer; PointList pointList; buffer.rebaseOffset(); Triangulator t; Shape shapeCopy; MultiShape multishapeCopy; if (mShapeToExtrude) { shapeCopy = *mShapeToExtrude; shapeCopy.close(); t.setShapeToTriangulate(&shapeCopy); } else { multishapeCopy = *mMultiShapeToExtrude; multishapeCopy.close(); t.setMultiShapeToTriangulate(mMultiShapeToExtrude); } t.triangulate(indexBuffer, pointList); buffer.estimateIndexCount(2*indexBuffer.size()); buffer.estimateVertexCount(2*pointList.size()); //begin cap buffer.rebaseOffset(); Quaternion q; q.FromAngleAxis(mAngleBegin, Vector3::UNIT_Y); for (size_t j =0;j<pointList.size();j++) { Vector2 vp2 = pointList[j]; Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal = Vector3::UNIT_Z; addPoint(buffer, q*vp, q*normal, vp2); } for (size_t i=0;i<indexBuffer.size()/3;i++) { buffer.index(indexBuffer[i*3]); buffer.index(indexBuffer[i*3+1]); buffer.index(indexBuffer[i*3+2]); } //end cap buffer.rebaseOffset(); q.FromAngleAxis(mAngleEnd, Vector3::UNIT_Y); for (size_t j =0;j<pointList.size();j++) { Vector2 vp2 = pointList[j]; Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal = -Vector3::UNIT_Z; addPoint(buffer, q*vp, q*normal, vp2); } for (size_t i=0;i<indexBuffer.size()/3;i++) { buffer.index(indexBuffer[i*3]); buffer.index(indexBuffer[i*3+2]); buffer.index(indexBuffer[i*3+1]); } }
void CylinderGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(mHeight>0. && mRadius>0. && "height and radius must be positive"); assert(mNumSegBase>0 && mNumSegHeight>0 && "Num seg must be positive integers"); buffer.rebaseOffset(); if (mCapped) { buffer.estimateVertexCount((mNumSegHeight+1)*(mNumSegBase+1)+2*(mNumSegBase+1)+2); buffer.estimateIndexCount(mNumSegHeight*(mNumSegBase+1)*6+6*mNumSegBase); } else { buffer.estimateVertexCount((mNumSegHeight+1)*(mNumSegBase+1)); buffer.estimateIndexCount(mNumSegHeight*(mNumSegBase+1)*6); } Real deltaAngle = (Math::TWO_PI / mNumSegBase); Real deltaHeight = mHeight/(Real)mNumSegHeight; int offset = 0; for (int i = 0; i <=mNumSegHeight; i++) for (int j = 0; j<=mNumSegBase; j++) { Real x0 = mRadius * cosf(j*deltaAngle); Real z0 = mRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, i*deltaHeight, z0), Vector3(x0,0,z0).normalisedCopy(), Vector2(j/(Real)mNumSegBase, i/(Real)mNumSegHeight)); if (i != mNumSegHeight) { buffer.index(offset + mNumSegBase + 1); buffer.index(offset); buffer.index(offset + mNumSegBase); buffer.index(offset + mNumSegBase + 1); buffer.index(offset + 1); buffer.index(offset); } offset ++; } if (mCapped) { //low cap int centerIndex = offset; addPoint(buffer, Vector3::ZERO, Vector3::NEGATIVE_UNIT_Y, Vector2::UNIT_Y); offset++; for (int j=0;j<=mNumSegBase;j++) { Real x0 = mRadius * cosf(j*deltaAngle); Real z0 = mRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, 0.0f, z0), Vector3::NEGATIVE_UNIT_Y, Vector2(j/(Real)mNumSegBase,0.0)); if (j!=mNumSegBase) { buffer.index(centerIndex); buffer.index(offset); buffer.index(offset+1); } offset++; } // high cap centerIndex = offset; addPoint(buffer, Vector3(0,mHeight,0), Vector3::UNIT_Y, Vector2::ZERO); offset++; for (int j=0;j<=mNumSegBase;j++) { Real x0 = mRadius * cosf(j*deltaAngle); Real z0 = mRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, mHeight, z0), Vector3::UNIT_Y, Vector2(j/(Real)mNumSegBase,1.)); if (j!=mNumSegBase) { buffer.index(centerIndex); buffer.index(offset+1); buffer.index(offset); } offset++; } } }
void ConeGenerator::AddToTriangleBuffer(TriangleBuffer& Buffer) const { Buffer.RebaseOffset(); Buffer.EstimateVertexCount( ( this->NumSegHeight + 1 ) * ( this->NumSegCircle + 1 ) + this->NumSegCircle + 2 ); Buffer.EstimateIndexCount( this->NumSegHeight * this->NumSegCircle * 6 + 3 * this->NumSegCircle ); Real deltaAngle = ( MathTools::GetTwoPi() / this->NumSegCircle ); Real deltaHeight = this->ConeHeight / (Real)this->NumSegHeight; Integer Offset = 0; Vector3 refNormal = Vector3( this->ConeRadius, this->ConeHeight, 0.f ).GetNormal(); Quaternion q; for( Whole i = 0 ; i <= this->NumSegHeight ; i++ ) { Real r0 = this->ConeRadius * ( 1 - i / (Real)this->NumSegHeight ); for( Whole j = 0; j <= this->NumSegCircle ; j++ ) { Real x0 = r0 * cosf( j * deltaAngle ); Real z0 = r0 * sinf( j * deltaAngle ); q.SetFromAxisAngle( -deltaAngle * j, Vector3::Unit_Y() ); this->AddPoint(Buffer, Vector3( x0, i * deltaHeight, z0 ), q * refNormal, Vector2( j / (Real)this->NumSegCircle, i / (Real)this->NumSegHeight ) ); if( i != this->NumSegHeight && j != this->NumSegCircle ) { Buffer.AddIndex( Offset + this->NumSegCircle + 2 ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + this->NumSegCircle + 1 ); Buffer.AddIndex( Offset + this->NumSegCircle + 2 ); Buffer.AddIndex( Offset + 1 ); Buffer.AddIndex( Offset ); } Offset++; } } //low cap Integer CenterIndex = Offset; this->AddPoint(Buffer, Vector3(0.0,0.0,0.0), Vector3::Neg_Unit_Y(), Vector2(0.0,1.0) ); Offset++; for( Whole j = 0 ; j <= this->NumSegCircle ; j++ ) { Real x0 = this->ConeRadius * cosf( j * deltaAngle ); Real z0 = this->ConeRadius * sinf( j * deltaAngle ); this->AddPoint(Buffer, Vector3(x0, 0.0f, z0), Vector3::Neg_Unit_Y(), Vector2( j / (Real)this->NumSegCircle, 0.0 ) ); if( j != this->NumSegCircle ) { Buffer.AddIndex( CenterIndex ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + 1 ); } Offset++; } }
void DamBreakSample::demonstrate(const int width, const int height, const Crystal::Graphics::ICamera<float>& camera) { this->width = width; this->height = height; this->rotationMatrix = camera.getRotationMatrix(); glEnable(GL_DEPTH_TEST); interaction.simulate(1.0f / 60.0f); PointLight<float> light; light.setPos(Vector3d<float>(10.0f, 10.0f, -10.0f)); light.setDiffuse(ColorRGBA<float>(1.0f, 0.0f, 0.0f, 1.0f)); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (auto r : rigids) { const auto matrix = r->getTransformMatrix(); auto p = r->getShape()->clone(r->getShape()->getId()); p->transform(matrix); glViewport(0, 0, width, height); TriangleBuffer triangleBuffer; triangleBuffer.add(*p); //renderer.render(camera, lineBuffer); Material material; material.setAmbient(ColorRGBA<float>(0.2, 0.2, 0.2, 0.0)); smoothRenderer.render(camera, triangleBuffer, light, material); glViewport(0, 0, fb.getWidth(), fb.getHeight()); fb.bind(); idRenderer.render(camera, triangleBuffer); fb.unbind(); delete p; } glClearColor(0.7f, 0.7f, 0.7f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (auto r : rigids) { const auto matrix = r->getTransformMatrix(); auto p = r->getShape()->clone(r->getShape()->getId()); p->transform(matrix); glViewport(0, 0, width, height); TriangleBuffer triangleBuffer; triangleBuffer.add(*p); //renderer.render(camera, lineBuffer); Material material; smoothRenderer.render(camera, triangleBuffer, light, material); //glViewport(0, 0, fb.getWidth(), fb.getHeight()); delete p; } glViewport(0, 0, width, height); const auto& particles = fluid->getParticles(); float minPressure = +FLT_MAX; float maxPressure = -FLT_MAX; for (auto p : particles) { minPressure = std::min<float>(minPressure, p->getDensity()); maxPressure = std::max<float>(maxPressure, p->getDensity()); } colorMap.setMinMax(900.0f, 1400.0f); //colorMap.setMinMax(800.0f, 2000.0f); PointBuffer buffer; for (auto p : particles) { const auto pos = p->getPosition(); auto color = colorMap.getColor(p->getDensity()); color.setAlpha(0.5f); Crystal::Graphics::Point point(pos, color, 500.0f); buffer.add(point); } pointRenderer.render(camera, buffer); }
void CapsuleGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(mNumRings>0 && mNumSegments>0 && mNumSegHeight>0 && "Num seg must be positive integers"); assert(mHeight>0. && mRadius>0. && "mHeight and radius must be positive"); buffer.rebaseOffset(); buffer.estimateVertexCount((2*mNumRings+2)*(mNumSegments+1) + (mNumSegHeight-1)*(mNumSegments+1)); buffer.estimateIndexCount((2*mNumRings+1)*(mNumSegments+1)*6 + (mNumSegHeight-1)*(mNumSegments+1)*6); Real fDeltaRingAngle = (Math::HALF_PI / mNumRings); Real fDeltaSegAngle = (Math::TWO_PI / mNumSegments); Real sphereRatio = mRadius / (2 * mRadius + mHeight); Real cylinderRatio = mHeight / (2 * mRadius + mHeight); int offset = 0; // Top half sphere // Generate the group of rings for the sphere for(unsigned int ring = 0; ring <= mNumRings; ring++ ) { Real r0 = mRadius * sinf ( ring * fDeltaRingAngle); Real y0 = mRadius * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(unsigned int seg = 0; seg <= mNumSegments; seg++) { Real x0 = r0 * cosf(seg * fDeltaSegAngle); Real z0 = r0 * sinf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere addPoint(buffer, Vector3(x0, 0.5f*mHeight + y0, z0), Vector3(x0, y0, z0).normalisedCopy(), Vector2((Real) seg / (Real) mNumSegments, (Real) ring / (Real) mNumRings * sphereRatio)); // each vertex (except the last) has six indices pointing to it buffer.index(offset + mNumSegments + 1); buffer.index(offset + mNumSegments); buffer.index(offset); buffer.index(offset + mNumSegments + 1); buffer.index(offset); buffer.index(offset + 1); offset ++; } // end for seg } // end for ring // Cylinder part Real deltaAngle = (Math::TWO_PI / mNumSegments); Real deltamHeight = mHeight/(Real)mNumSegHeight; for (unsigned short i = 1; i < mNumSegHeight; i++) for (unsigned short j = 0; j<=mNumSegments; j++) { Real x0 = mRadius * cosf(j*deltaAngle); Real z0 = mRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, 0.5f*mHeight-i*deltamHeight, z0), Vector3(x0,0,z0).normalisedCopy(), Vector2(j/(Real)mNumSegments, i/(Real)mNumSegHeight * cylinderRatio + sphereRatio)); buffer.index(offset + mNumSegments + 1); buffer.index(offset + mNumSegments); buffer.index(offset); buffer.index(offset + mNumSegments + 1); buffer.index(offset); buffer.index(offset + 1); offset ++; } // Bottom half sphere // Generate the group of rings for the sphere for(unsigned int ring = 0; ring <= mNumRings; ring++) { Real r0 = mRadius * sinf (Math::HALF_PI + ring * fDeltaRingAngle); Real y0 = mRadius * cosf (Math::HALF_PI + ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(unsigned int seg = 0; seg <= mNumSegments; seg++) { Real x0 = r0 * cosf(seg * fDeltaSegAngle); Real z0 = r0 * sinf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere addPoint(buffer, Vector3(x0, -0.5f*mHeight + y0, z0), Vector3(x0, y0, z0).normalisedCopy(), Vector2((Real) seg / (Real) mNumSegments, (Real) ring / (Real) mNumRings*sphereRatio + cylinderRatio + sphereRatio)); if (ring != mNumRings) { // each vertex (except the last) has six indices pointing to it buffer.index(offset + mNumSegments + 1); buffer.index(offset + mNumSegments); buffer.index(offset); buffer.index(offset + mNumSegments + 1); buffer.index(offset); buffer.index(offset + 1); } offset ++; } // end for seg } // end for ring }
void IcoSphereGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(mRadius>0. && "Radius must me positive"); assert(mNumIterations>0 && "numIterations must be positive"); std::vector<Vector3> vertices; int offset = 0; /// Step 1 : Generate icosahedron Real phi = .5f*(1.f+sqrt(5.f)); Real invnorm = 1/sqrt(phi*phi+1); vertices.push_back(invnorm*Vector3(-1, phi, 0));//0 vertices.push_back(invnorm*Vector3( 1, phi, 0));//1 vertices.push_back(invnorm*Vector3(0, 1, -phi));//2 vertices.push_back(invnorm*Vector3(0, 1, phi));//3 vertices.push_back(invnorm*Vector3(-phi,0, -1));//4 vertices.push_back(invnorm*Vector3(-phi,0, 1));//5 vertices.push_back(invnorm*Vector3( phi,0, -1));//6 vertices.push_back(invnorm*Vector3( phi,0, 1));//7 vertices.push_back(invnorm*Vector3(0, -1, -phi));//8 vertices.push_back(invnorm*Vector3(0, -1, phi));//9 vertices.push_back(invnorm*Vector3(-1, -phi,0));//10 vertices.push_back(invnorm*Vector3( 1, -phi,0));//11 int firstFaces[] = {0,1,2, 0,3,1, 0,4,5, 1,7,6, 1,6,2, 1,3,7, 0,2,4, 0,5,3, 2,6,8, 2,8,4, 3,5,9, 3,9,7, 11,6,7, 10,5,4, 10,4,8, 10,9,5, 11,8,6, 11,7,9, 10,8,11, 10,11,9 }; std::vector<int> faces(firstFaces, firstFaces + sizeof(firstFaces)/sizeof(*firstFaces)); int size = 60; /// Step 2 : tessellate for (unsigned short iteration = 0; iteration<mNumIterations; iteration++) { size*=4; std::vector<int> newFaces; newFaces.clear(); //newFaces.resize(size); for (int i=0; i<size/12; i++) { int i1 = faces[i*3]; int i2 = faces[i*3+1]; int i3 = faces[i*3+2]; int i12 = vertices.size(); int i23 = i12+1; int i13 = i12+2; Vector3 v1 = vertices[i1]; Vector3 v2 = vertices[i2]; Vector3 v3 = vertices[i3]; //make 1 vertice at the center of each edge and project it onto the sphere vertices.push_back((v1+v2).normalisedCopy()); vertices.push_back((v2+v3).normalisedCopy()); vertices.push_back((v1+v3).normalisedCopy()); //now recreate indices newFaces.push_back(i1); newFaces.push_back(i12); newFaces.push_back(i13); newFaces.push_back(i2); newFaces.push_back(i23); newFaces.push_back(i12); newFaces.push_back(i3); newFaces.push_back(i13); newFaces.push_back(i23); newFaces.push_back(i12); newFaces.push_back(i23); newFaces.push_back(i13); } faces.swap(newFaces); } /// Step 3 : generate texcoords std::vector<Vector2> texCoords; for (unsigned short i=0;i<vertices.size();i++) { const Vector3& vec = vertices[i]; Real u, v; Real r0 = sqrtf(vec.x*vec.x+vec.z*vec.z); Real alpha; alpha = atan2f(vec.z,vec.x); u = alpha/Math::TWO_PI+.5f; v = atan2f(vec.y, r0)/Math::PI + .5f; texCoords.push_back(Vector2(u,v)); } /// Step 4 : fix texcoords // find vertices to split std::vector<int> indexToSplit; for (unsigned int i=0;i<faces.size()/3;i++) { Vector2& t0 = texCoords[faces[i*3+0]]; Vector2& t1 = texCoords[faces[i*3+1]]; Vector2& t2 = texCoords[faces[i*3+2]]; if (Math::Abs(t2.x-t0.x)>0.5) { if (t0.x<0.5) indexToSplit.push_back(faces[i*3]); else indexToSplit.push_back(faces[i*3+2]); } if (Math::Abs(t1.x-t0.x)>0.5) { if (t0.x<0.5) indexToSplit.push_back(faces[i*3]); else indexToSplit.push_back(faces[i*3+1]); } if (Math::Abs(t2.x-t1.x)>0.5) { if (t1.x<0.5) indexToSplit.push_back(faces[i*3+1]); else indexToSplit.push_back(faces[i*3+2]); } } //split vertices for (unsigned short i=0;i<indexToSplit.size();i++) { int index = indexToSplit[i]; //duplicate vertex Vector3 v = vertices[index]; Vector2 t = texCoords[index] + Vector2::UNIT_X; vertices.push_back(v); texCoords.push_back(t); int newIndex = vertices.size()-1; //reassign indices for (unsigned short j=0;j<faces.size();j++) { if (faces[j]==index) { int index1 = faces[(j+1)%3+(j/3)*3]; int index2 = faces[(j+2)%3+(j/3)*3]; if ((texCoords[index1].x>0.5) || (texCoords[index2].x>0.5)) { faces[j] = newIndex; } } } } /// Step 5 : realize buffer.rebaseOffset(); buffer.estimateVertexCount(vertices.size()); buffer.estimateIndexCount(size); for (unsigned short i=0; i<vertices.size(); i++) { addPoint(buffer, mRadius*vertices[i], vertices[i],//note : vertices are already normalised Vector2(texCoords[i].x,texCoords[i].y)); } for (unsigned short i=0; i<size; i++) { buffer.index(offset+faces[i]); } offset+=vertices.size(); }
void PlaneGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(mNumSegX>0 && mNumSegY>0 && "Num seg must be positive"); assert(!mNormal.isZeroLength() && "Normal must not be null"); assert(mSizeX>0. && mSizeY>0. && "Size must be positive"); buffer.rebaseOffset(); buffer.estimateVertexCount((mNumSegX+1)*(mNumSegY+1)); buffer.estimateIndexCount(mNumSegX*mNumSegY*6); int offset = 0; Vector3 vX = mNormal.perpendicular(); Vector3 vY = mNormal.crossProduct(vX); Vector3 delta1 = mSizeX / (Real)mNumSegX * vX; Vector3 delta2 = mSizeY / (Real)mNumSegY * vY; // build one corner of the square Vector3 orig = -0.5f*mSizeX*vX - 0.5f*mSizeY*vY; for (unsigned short i1 = 0; i1<=mNumSegX; i1++) for (unsigned short i2 = 0; i2<=mNumSegY; i2++) { addPoint(buffer, orig+i1*delta1+i2*delta2, mNormal, Vector2(i1/(Real)mNumSegX, i2/(Real)mNumSegY)); } bool reverse = false; if (delta1.crossProduct(delta2).dotProduct(mNormal)>0) reverse= true; for (unsigned short n1 = 0; n1<mNumSegX; n1++) { for (unsigned short n2 = 0; n2<mNumSegY; n2++) { if (reverse) { buffer.index(offset+0); buffer.index(offset+(mNumSegY+1)); buffer.index(offset+1); buffer.index(offset+1); buffer.index(offset+(mNumSegY+1)); buffer.index(offset+(mNumSegY+1)+1); } else { buffer.index(offset+0); buffer.index(offset+1); buffer.index(offset+(mNumSegY+1)); buffer.index(offset+1); buffer.index(offset+(mNumSegY+1)+1); buffer.index(offset+(mNumSegY+1)); } offset++; } offset++; } }
void CapsuleGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(numRings>0 && numSegments>0 && numSegHeight>0 && "Num seg must be positive integers"); assert(height>0. && radius>0. && "Height and radius must be positive"); buffer.rebaseOffset(); buffer.estimateVertexCount((2*numRings+2)*(numSegments+1) + (numSegHeight-1)*(numSegments+1)); buffer.estimateIndexCount((2*numRings+1)*(numSegments+1)*6 + (numSegHeight-1)*(numSegments+1)*6); Ogre::Real fDeltaRingAngle = (Ogre::Math::HALF_PI / numRings); Ogre::Real fDeltaSegAngle = (Ogre::Math::TWO_PI / numSegments); Ogre::Real sphereRatio = radius / (2 * radius + height); Ogre::Real cylinderRatio = height / (2 * radius + height); int offset = 0; // Top half sphere // Generate the group of rings for the sphere for(unsigned int ring = 0; ring <= numRings; ring++ ) { Ogre::Real r0 = radius * sinf ( ring * fDeltaRingAngle); Ogre::Real y0 = radius * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(unsigned int seg = 0; seg <= numSegments; seg++) { Ogre::Real x0 = r0 * cosf(seg * fDeltaSegAngle); Ogre::Real z0 = r0 * sinf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere buffer.position( x0, 0.5*height + y0, z0); if (enableNormals) buffer.normal(Ogre::Vector3(x0, y0, z0).normalisedCopy()); for (unsigned int tc=0;tc<numTexCoordSet;tc++) buffer.textureCoord((Ogre::Real) seg / (Ogre::Real) numSegments * uTile, (Ogre::Real) ring / (Ogre::Real) numRings * vTile * sphereRatio); // each vertex (except the last) has six indices pointing to it buffer.index(offset + numSegments + 1); buffer.index(offset + numSegments); buffer.index(offset); buffer.index(offset + numSegments + 1); buffer.index(offset); buffer.index(offset + 1); offset ++; } // end for seg } // end for ring // Cylinder part Ogre::Real deltaAngle = (Ogre::Math::TWO_PI / numSegments); Ogre::Real deltaHeight = height/(Ogre::Real)numSegHeight; for (int i = 1; i < numSegHeight; i++) for (int j = 0; j<=numSegments; j++) { Ogre::Real x0 = radius * cosf(j*deltaAngle); Ogre::Real z0 = radius * sinf(j*deltaAngle); buffer.position(x0, 0.5*height-i*deltaHeight, z0); buffer.normal(Ogre::Vector3(x0,0,z0).normalisedCopy()); buffer.textureCoord(j/(Ogre::Real)numSegments*uTile, i/(Ogre::Real)numSegHeight*vTile * cylinderRatio + sphereRatio); buffer.index(offset + numSegments + 1); buffer.index(offset + numSegments); buffer.index(offset); buffer.index(offset + numSegments + 1); buffer.index(offset); buffer.index(offset + 1); offset ++; } // Bottom half sphere // Generate the group of rings for the sphere for(unsigned int ring = 0; ring <= numRings; ring++) { Ogre::Real r0 = radius * sinf (Ogre::Math::HALF_PI + ring * fDeltaRingAngle); Ogre::Real y0 = radius * cosf (Ogre::Math::HALF_PI + ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(unsigned int seg = 0; seg <= numSegments; seg++) { Ogre::Real x0 = r0 * cosf(seg * fDeltaSegAngle); Ogre::Real z0 = r0 * sinf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere buffer.position( x0, -0.5*height + y0, z0); if (enableNormals) buffer.normal(Ogre::Vector3(x0, y0, z0).normalisedCopy()); for (unsigned int tc=0;tc<numTexCoordSet;tc++) buffer.textureCoord((Ogre::Real) seg / (Ogre::Real) numSegments * uTile, (Ogre::Real) ring / (Ogre::Real) numRings * vTile*sphereRatio + cylinderRatio + sphereRatio); if (ring != numRings) { // each vertex (except the last) has six indices pointing to it buffer.index(offset + numSegments + 1); buffer.index(offset + numSegments); buffer.index(offset); buffer.index(offset + numSegments + 1); buffer.index(offset); buffer.index(offset + 1); } offset ++; } // end for seg } // end for ring }
//----------------------------------------------------------------------- void Extruder::_extrudeBodyImpl(TriangleBuffer& buffer, const Shape* shapeToExtrude) const { assert(mExtrusionPath && shapeToExtrude && "Shape and Path must not be null!"); unsigned int numSegPath = mExtrusionPath->getSegCount(); unsigned int numSegShape = shapeToExtrude->getSegCount(); assert(numSegPath>0 && numSegShape>0 && "Shape and path must contain at least two points"); Real totalPathLength = mExtrusionPath->getTotalLength(); Real totalShapeLength = shapeToExtrude->getTotalLength(); // Merge shape and path with tracks Ogre::Real lineicPos=0.; Path path = *mExtrusionPath; if (mRotationTrack) path = path.mergeKeysWithTrack(*mRotationTrack); if (mScaleTrack) path = path.mergeKeysWithTrack(*mScaleTrack); if (mPathTextureTrack) path = path.mergeKeysWithTrack(*mPathTextureTrack); numSegPath = path.getSegCount(); Shape shape = *shapeToExtrude; if (mShapeTextureTrack) shape = shape.mergeKeysWithTrack(*mShapeTextureTrack); numSegShape = shape.getSegCount(); // Estimate vertex and index count buffer.rebaseOffset(); buffer.estimateIndexCount(numSegShape*numSegPath*6); buffer.estimateVertexCount((numSegShape+1)*(numSegPath+1)); Vector3 oldup; for (unsigned int i = 0; i <= numSegPath; ++i) { Vector3 v0 = path.getPoint(i); Vector3 direction = path.getAvgDirection(i); Quaternion q = Utils::_computeQuaternion(direction); Radian angle = (q*Vector3::UNIT_Y).angleBetween(oldup); if (i>0 && angle>(Radian)Math::HALF_PI/2.) { q = Utils::_computeQuaternion(direction, oldup); } oldup = q * Vector3::UNIT_Y; Real scale=1.; if (i>0) lineicPos += (v0-path.getPoint(i-1)).length(); // Get the values of angle and scale if (mRotationTrack) { Real angle; angle = mRotationTrack->getValue(lineicPos, lineicPos / totalPathLength, i); q = q*Quaternion((Radian)angle, Vector3::UNIT_Z); } if (mScaleTrack) { scale = mScaleTrack->getValue(lineicPos, lineicPos / totalPathLength, i); } Real uTexCoord; if (mPathTextureTrack) uTexCoord = mPathTextureTrack->getValue(lineicPos, lineicPos / totalPathLength, i); else uTexCoord = lineicPos / totalPathLength; Real lineicShapePos = 0.; // Insert new points for (unsigned int j =0; j <= numSegShape; ++j) { Vector2 vp2 = shapeToExtrude->getPoint(j); //Vector2 vp2direction = shapeToExtrude->getAvgDirection(j); Vector2 vp2normal = shapeToExtrude->getAvgNormal(j); Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal(vp2normal.x, vp2normal.y, 0); buffer.rebaseOffset(); Vector3 newPoint = v0+q*(scale*vp); if (j>0) lineicShapePos += (vp2 - shape.getPoint(j-1)).length(); Real vTexCoord; if (mShapeTextureTrack) vTexCoord = mShapeTextureTrack->getValue(lineicShapePos, lineicShapePos / totalShapeLength, j); else vTexCoord = lineicShapePos / totalShapeLength; addPoint(buffer, newPoint, q*normal, Vector2(uTexCoord, vTexCoord)); if (j <numSegShape && i <numSegPath) { if (shapeToExtrude->getOutSide() == SIDE_LEFT) { buffer.triangle(numSegShape + 1, numSegShape + 2, 0); buffer.triangle(0, numSegShape + 2, 1); } else { buffer.triangle(numSegShape + 2, numSegShape + 1, 0); buffer.triangle(numSegShape + 2, 0, 1); } } } } }
//----------------------------------------------------------------------- void Extruder::_extrudeCapImpl(TriangleBuffer& buffer) const { std::vector<int> indexBuffer; PointList pointList; buffer.rebaseOffset(); Triangulator t; if (mShapeToExtrude) t.setShapeToTriangulate(mShapeToExtrude); else t.setMultiShapeToTriangulate(mMultiShapeToExtrude); t.triangulate(indexBuffer, pointList); buffer.estimateIndexCount(2*indexBuffer.size()); buffer.estimateVertexCount(2*pointList.size()); //begin cap buffer.rebaseOffset(); Quaternion qBegin = Utils::_computeQuaternion(mExtrusionPath->getDirectionAfter(0)); if (mRotationTrack) { Real angle = mRotationTrack->getFirstValue(); qBegin = qBegin*Quaternion((Radian)angle, Vector3::UNIT_Z); } Real scaleBegin=1.; if (mScaleTrack) scaleBegin = mScaleTrack->getFirstValue(); for (size_t j =0;j<pointList.size();j++) { Vector2 vp2 = pointList[j]; Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal = -Vector3::UNIT_Z; Vector3 newPoint = mExtrusionPath->getPoint(0)+qBegin*(scaleBegin*vp); addPoint(buffer, newPoint, qBegin*normal, vp2); } for (size_t i=0;i<indexBuffer.size()/3;i++) { buffer.index(indexBuffer[i*3]); buffer.index(indexBuffer[i*3+2]); buffer.index(indexBuffer[i*3+1]); } // end cap buffer.rebaseOffset(); Quaternion qEnd = Utils::_computeQuaternion(mExtrusionPath->getDirectionBefore(mExtrusionPath->getSegCount())); if (mRotationTrack) { Real angle = mRotationTrack->getLastValue(); qEnd = qEnd*Quaternion((Radian)angle, Vector3::UNIT_Z); } Real scaleEnd=1.; if (mScaleTrack) scaleEnd = mScaleTrack->getLastValue(); for (size_t j =0;j<pointList.size();j++) { Vector2 vp2 = pointList[j]; Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal = Vector3::UNIT_Z; Vector3 newPoint = mExtrusionPath->getPoint(mExtrusionPath->getSegCount())+qEnd*(scaleEnd*vp); addPoint(buffer, newPoint, qEnd*normal, vp2); } for (size_t i=0;i<indexBuffer.size()/3;i++) { buffer.index(indexBuffer[i*3]); buffer.index(indexBuffer[i*3+1]); buffer.index(indexBuffer[i*3+2]); } }
void TubeGenerator::AddToTriangleBuffer(TriangleBuffer& Buffer) const { Buffer.RebaseOffset(); Buffer.EstimateVertexCount( ( this->NumSegHeight + 1 ) * ( this->NumSegCircle + 1 ) * 2 + ( this->NumSegCircle + 1 ) * 4 ); Buffer.EstimateIndexCount( 6 * ( this->NumSegCircle + 1 ) * this->NumSegHeight * 2 + 6 * this->NumSegCircle * 2 ); Real deltaAngle = ( MathTools::GetTwoPi() / this->NumSegCircle ); Real deltaHeight = this->TubeHeight / (Real)this->NumSegHeight; int Offset = 0; for( Whole i = 0 ; i <= this->NumSegHeight ; ++i ) { for( Whole j = 0 ; j <= this->NumSegCircle ; ++j ) { Real x0 = this->TubeOuterRadius * cosf( j * deltaAngle ); Real z0 = this->TubeOuterRadius * sinf( j * deltaAngle ); this->AddPoint(Buffer, Vector3( x0, i * deltaHeight, z0 ), Vector3( x0, 0, z0 ).GetNormal(), Vector2( j / (Real)this->NumSegCircle, i / (Real)this->NumSegHeight ) ); if( i != this->NumSegHeight ) { Buffer.AddIndex( Offset + this->NumSegCircle + 1 ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + this->NumSegCircle ); Buffer.AddIndex( Offset + this->NumSegCircle + 1 ); Buffer.AddIndex( Offset + 1 ); Buffer.AddIndex( Offset ); } Offset++; } } for( Whole i = 0 ; i <= this->NumSegHeight ; ++i ) { for( Whole j = 0 ; j<= this->NumSegCircle ; ++j ) { Real x0 = this->TubeInnerRadius * cosf( j * deltaAngle ); Real z0 = this->TubeInnerRadius * sinf( j * deltaAngle ); this->AddPoint(Buffer, Vector3( x0, i * deltaHeight, z0 ), -Vector3( x0, 0, z0 ).GetNormal(), Vector2( j / (Real)this->NumSegCircle, i / (Real)this->NumSegHeight ) ); if( i != this->NumSegHeight ) { Buffer.AddIndex( Offset + this->NumSegCircle + 1 ); Buffer.AddIndex( Offset + this->NumSegCircle ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + this->NumSegCircle + 1 ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + 1); } Offset++; } } //low cap for( Whole j = 0 ; j <= this->NumSegCircle ; ++j ) { Real x0 = this->TubeInnerRadius * cosf( j * deltaAngle ); Real z0 = this->TubeInnerRadius * sinf( j * deltaAngle ); this->AddPoint(Buffer, Vector3( x0, 0.0f, z0 ), Vector3::Neg_Unit_Y(), Vector2( j / (Real)this->NumSegCircle, 1. ) ); x0 = this->TubeOuterRadius * cosf( j * deltaAngle ); z0 = this->TubeOuterRadius * sinf( j * deltaAngle ); this->AddPoint(Buffer, Vector3( x0, 0.0f, z0 ), Vector3::Neg_Unit_Y(), Vector2( j / (Real)this->NumSegCircle, 0. ) ); if( j != this->NumSegCircle ) { Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + 1 ); Buffer.AddIndex( Offset + 3 ); Buffer.AddIndex( Offset + 2 ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + 3 ); } Offset += 2; } //high cap for( Whole j = 0 ; j <= this->NumSegCircle ; ++j ) { Real x0 = this->TubeInnerRadius * cosf( j * deltaAngle ); Real z0 = this->TubeInnerRadius * sinf( j * deltaAngle ); this->AddPoint(Buffer, Vector3( x0, this->TubeHeight, z0 ), Vector3::Unit_Y(), Vector2( j / (Real)this->NumSegCircle, 0. ) ); x0 = this->TubeOuterRadius * cosf( j * deltaAngle ); z0 = this->TubeOuterRadius * sinf( j * deltaAngle ); this->AddPoint(Buffer, Vector3( x0, this->TubeHeight, z0 ), Vector3::Unit_Y(), Vector2( j / (Real)this->NumSegCircle, 1. ) ); if( j != this->NumSegCircle ) { Buffer.AddIndex( Offset + 1 ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + 3 ); Buffer.AddIndex( Offset ); Buffer.AddIndex( Offset + 2 ); Buffer.AddIndex( Offset + 3 ); } Offset += 2; } }
void PlaneGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(numSegX>0 && numSegY>0 && "Num seg must be positive"); assert(!normal.isZeroLength() && "Normal must not be null"); assert(sizeX>0. && sizeY>0. && "Size must be positive"); buffer.rebaseOffset(); buffer.estimateVertexCount((numSegX+1)*(numSegY+1)); buffer.estimateIndexCount(numSegX*numSegY*6); int offset = 0; Ogre::Vector3 vX = normal.perpendicular(); Ogre::Vector3 vY = normal.crossProduct(vX); Ogre::Vector3 delta1 = sizeX / numSegX * vX; Ogre::Vector3 delta2 = sizeY / numSegY * vY; // build one corner of the square Ogre::Vector3 orig = -0.5*sizeX*vX - 0.5*sizeY*vY; for (int i1 = 0; i1<=numSegX; i1++) for (int i2 = 0; i2<=numSegY; i2++) { buffer.position(orig+i1*delta1+i2*delta2+position); buffer.textureCoord(i1/(Ogre::Real)numSegX*uTile, i2/(Ogre::Real)numSegY*vTile); buffer.normal(normal); } bool reverse = false; if (delta1.crossProduct(delta2).dotProduct(normal)>0) reverse= true; for (int n1 = 0; n1<numSegX; n1++) { for (int n2 = 0; n2<numSegY; n2++) { if (reverse) { buffer.index(offset+0); buffer.index(offset+(numSegY+1)); buffer.index(offset+1); buffer.index(offset+1); buffer.index(offset+(numSegY+1)); buffer.index(offset+(numSegY+1)+1); } else { buffer.index(offset+0); buffer.index(offset+1); buffer.index(offset+(numSegY+1)); buffer.index(offset+1); buffer.index(offset+(numSegY+1)+1); buffer.index(offset+(numSegY+1)); } offset++; } offset++; } }
void TubeGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { buffer.rebaseOffset(); buffer.estimateVertexCount((mNumSegHeight+1)*(mNumSegBase+1)*2+(mNumSegBase+1)*4); buffer.estimateIndexCount(6*(mNumSegBase+1)*mNumSegHeight*2+6*mNumSegBase*2); Real deltaAngle = (Math::TWO_PI / mNumSegBase); Real deltaHeight = mHeight/(Real)mNumSegHeight; int offset = 0; for (unsigned int i = 0; i <=mNumSegHeight; i++) for (unsigned int j = 0; j<=mNumSegBase; j++) { Real x0 = mOuterRadius * cosf(j*deltaAngle); Real z0 = mOuterRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, i*deltaHeight, z0), Vector3(x0,0,z0).normalisedCopy(), Vector2(j/(Real)mNumSegBase, i/(Real)mNumSegHeight)); if (i != mNumSegHeight) { buffer.index(offset + mNumSegBase + 1); buffer.index(offset); buffer.index(offset + mNumSegBase); buffer.index(offset + mNumSegBase + 1); buffer.index(offset + 1); buffer.index(offset); } offset ++; } for (unsigned int i = 0; i <=mNumSegHeight; i++) for (unsigned int j = 0; j<=mNumSegBase; j++) { Real x0 = mInnerRadius * cosf(j*deltaAngle); Real z0 = mInnerRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, i*deltaHeight, z0), -Vector3(x0,0,z0).normalisedCopy(), Vector2(j/(Real)mNumSegBase, i/(Real)mNumSegHeight)); if (i != mNumSegHeight) { buffer.index(offset + mNumSegBase + 1); buffer.index(offset + mNumSegBase); buffer.index(offset); buffer.index(offset + mNumSegBase + 1); buffer.index(offset); buffer.index(offset + 1); } offset ++; } //low cap for (unsigned int j=0; j<=mNumSegBase; j++) { Real x0 = mInnerRadius * cosf(j*deltaAngle); Real z0 = mInnerRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, 0.0f, z0), Vector3::NEGATIVE_UNIT_Y, Vector2(j/(Real)mNumSegBase,1.)); x0 = mOuterRadius * cosf(j*deltaAngle); z0 = mOuterRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, 0.0f, z0), Vector3::NEGATIVE_UNIT_Y, Vector2(j/(Real)mNumSegBase,0.)); if (j!=mNumSegBase) { buffer.index(offset); buffer.index(offset+1); buffer.index(offset+3); buffer.index(offset+2); buffer.index(offset); buffer.index(offset+3); } offset+=2; } //high cap for (unsigned int j=0; j<=mNumSegBase; j++) { Real x0 = mInnerRadius * cosf(j*deltaAngle); Real z0 = mInnerRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, mHeight, z0), Vector3::UNIT_Y, Vector2(j/(Real)mNumSegBase,0.)); x0 = mOuterRadius * cosf(j*deltaAngle); z0 = mOuterRadius * sinf(j*deltaAngle); addPoint(buffer, Vector3(x0, mHeight, z0), Vector3::UNIT_Y, Vector2(j/(Real)mNumSegBase,1.)); if (j!=mNumSegBase) { buffer.index(offset+1); buffer.index(offset); buffer.index(offset+3); buffer.index(offset); buffer.index(offset+2); buffer.index(offset+3); } offset+=2; } }
void TubeGenerator::addToTriangleBuffer(TriangleBuffer& buffer) const { assert(height>0. && outerRadius>0. && innerRadius>0. && "Height and radius must be positive"); assert(innerRadius<outerRadius && "Outer radius must be bigger than inner radius"); assert(numSegBase>0 && numSegHeight>0 && "Num seg must be positive integers"); buffer.rebaseOffset(); buffer.estimateVertexCount((numSegHeight+1)*(numSegBase+1)*2+(numSegBase+1)*4); buffer.estimateIndexCount(6*(numSegBase+1)*numSegHeight*2+6*numSegBase*2); Ogre::Real deltaAngle = (Ogre::Math::TWO_PI / numSegBase); Ogre::Real deltaHeight = height/(Ogre::Real)numSegHeight; int offset = 0; for (int i = 0; i <=numSegHeight; i++) for (int j = 0; j<=numSegBase; j++) { Ogre::Real x0 = outerRadius * cosf(j*deltaAngle); Ogre::Real z0 = outerRadius * sinf(j*deltaAngle); buffer.position(x0, i*deltaHeight, z0); buffer.normal(Ogre::Vector3(x0,0,z0).normalisedCopy()); buffer.textureCoord(j/(Ogre::Real)numSegBase*uTile, i/(Ogre::Real)numSegHeight*vTile); if (i != numSegHeight) { buffer.index(offset + numSegBase + 1); buffer.index(offset); buffer.index(offset + numSegBase); buffer.index(offset + numSegBase + 1); buffer.index(offset + 1); buffer.index(offset); } offset ++; } for (int i = 0; i <=numSegHeight; i++) for (int j = 0; j<=numSegBase; j++) { Ogre::Real x0 = innerRadius * cosf(j*deltaAngle); Ogre::Real z0 = innerRadius * sinf(j*deltaAngle); buffer.position(x0, i*deltaHeight, z0); buffer.normal(-Ogre::Vector3(x0,0,z0).normalisedCopy()); buffer.textureCoord(j/(Ogre::Real)numSegBase*uTile, i/(Ogre::Real)numSegHeight*vTile); if (i != numSegHeight) { buffer.index(offset + numSegBase + 1); buffer.index(offset + numSegBase); buffer.index(offset); buffer.index(offset + numSegBase + 1); buffer.index(offset); buffer.index(offset + 1); } offset ++; } //low cap for (int j=0;j<=numSegBase;j++) { Ogre::Real x0 = innerRadius * cosf(j*deltaAngle); Ogre::Real z0 = innerRadius * sinf(j*deltaAngle); buffer.position(x0, 0.0f, z0); buffer.normal(Ogre::Vector3::NEGATIVE_UNIT_Y); buffer.textureCoord(j/(Ogre::Real)numSegBase*uTile,vTile); x0 = outerRadius * cosf(j*deltaAngle); z0 = outerRadius * sinf(j*deltaAngle); buffer.position(x0, 0.0f, z0); buffer.normal(Ogre::Vector3::NEGATIVE_UNIT_Y); buffer.textureCoord(j/(Ogre::Real)numSegBase*uTile,0.0); if (j!=numSegBase) { buffer.index(offset); buffer.index(offset+1); buffer.index(offset+3); buffer.index(offset+2); buffer.index(offset); buffer.index(offset+3); } offset+=2; } //high cap for (int j=0;j<=numSegBase;j++) { Ogre::Real x0 = innerRadius * cosf(j*deltaAngle); Ogre::Real z0 = innerRadius * sinf(j*deltaAngle); buffer.position(x0, height, z0); buffer.normal(Ogre::Vector3::UNIT_Y); buffer.textureCoord(j/(Ogre::Real)numSegBase*uTile,0.0); x0 = outerRadius * cosf(j*deltaAngle); z0 = outerRadius * sinf(j*deltaAngle); buffer.position(x0, height, z0); buffer.normal(Ogre::Vector3::UNIT_Y); buffer.textureCoord(j/(Ogre::Real)numSegBase*uTile,vTile); if (j!=numSegBase) { buffer.index(offset+1); buffer.index(offset); buffer.index(offset+3); buffer.index(offset); buffer.index(offset+2); buffer.index(offset+3); } offset+=2; } }