void GeometryGenerator::CreateCylinder(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT stackCount, MeshData& meshData)
{
	meshData.Vertices.clear();
	meshData.Indices.clear();

	//
	// Build Stacks.
	// 

	float stackHeight = height / stackCount;

	// Amount to increment radius as we move up each stack level from bottom to top.
	float radiusStep = (topRadius - bottomRadius) / stackCount;

	UINT ringCount = stackCount+1;

	// Compute vertices for each stack ring starting at the bottom and moving up.
	for(UINT i = 0; i < ringCount; ++i)
	{
		float y = -0.5f*height + i*stackHeight;
		float r = bottomRadius + i*radiusStep;

		// vertices of ring
		float dTheta = 2.0f*XM_PI/sliceCount;
		for(UINT j = 0; j <= sliceCount; ++j)
		{
			Vertex vertex;

			float c = cosf(j*dTheta);
			float s = sinf(j*dTheta);

			vertex.Position = XMFLOAT3(r*c, y, r*s);

			vertex.TexC.x = (float)j/sliceCount;
			vertex.TexC.y = 1.0f - (float)i/stackCount;

			// Cylinder can be parameterized as follows, where we introduce v
			// parameter that goes in the same direction as the v tex-coord
			// so that the bitangent goes in the same direction as the v tex-coord.
			//   Let r0 be the bottom radius and let r1 be the top radius.
			//   y(v) = h - hv for v in [0,1].
			//   r(v) = r1 + (r0-r1)v
			//
			//   x(t, v) = r(v)*cos(t)
			//   y(t, v) = h - hv
			//   z(t, v) = r(v)*sin(t)
			// 
			//  dx/dt = -r(v)*sin(t)
			//  dy/dt = 0
			//  dz/dt = +r(v)*cos(t)
			//
			//  dx/dv = (r0-r1)*cos(t)
			//  dy/dv = -h
			//  dz/dv = (r0-r1)*sin(t)

			// This is unit length.
			vertex.TangentU = XMFLOAT3(-s, 0.0f, c);

			float dr = bottomRadius-topRadius;
			XMFLOAT3 bitangent(dr*c, -height, dr*s);

			XMVECTOR T = XMLoadFloat3(&vertex.TangentU);
			XMVECTOR B = XMLoadFloat3(&bitangent);
			XMVECTOR N = XMVector3Normalize(XMVector3Cross(T, B));
			XMStoreFloat3(&vertex.Normal, N);

			meshData.Vertices.push_back(vertex);
		}
	}

	// Add one because we duplicate the first and last vertex per ring
	// since the texture coordinates are different.
	UINT ringVertexCount = sliceCount+1;

	// Compute indices for each stack.
	for(UINT i = 0; i < stackCount; ++i)
	{
		for(UINT j = 0; j < sliceCount; ++j)
		{
			meshData.Indices.push_back(i*ringVertexCount + j);
			meshData.Indices.push_back((i+1)*ringVertexCount + j);
			meshData.Indices.push_back((i+1)*ringVertexCount + j+1);

			meshData.Indices.push_back(i*ringVertexCount + j);
			meshData.Indices.push_back((i+1)*ringVertexCount + j+1);
			meshData.Indices.push_back(i*ringVertexCount + j+1);
		}
	}

	BuildCylinderTopCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData);
	BuildCylinderBottomCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData);
}
Пример #2
0
void TextureProjection::emitTextureCoordinates (std::size_t width, std::size_t height, Winding& w,
		const Vector3& normal, const Matrix4& localToWorld)
{
	if (w.size() < 3) {
		return;
	}

	Matrix4 local2tex = m_texdef.getTransform((float) width, (float) height);

	{
		Matrix4 xyz2st;
		// we don't care if it's not normalised...
		basisForNormal(matrix4_transformed_direction(localToWorld, normal), xyz2st);
		matrix4_multiply_by_matrix4(local2tex, xyz2st);
	}

	Vector3 tangent(local2tex.getTransposed().x().getVector3().getNormalised());
	Vector3 bitangent(local2tex.getTransposed().y().getVector3().getNormalised());

	matrix4_multiply_by_matrix4(local2tex, localToWorld);

	for (Winding::iterator i = w.begin(); i != w.end(); ++i) {
		Vector3 texcoord = matrix4_transformed_point(local2tex, (*i).vertex);
		(*i).texcoord[0] = texcoord[0];
		(*i).texcoord[1] = texcoord[1];

		(*i).tangent = tangent;
		(*i).bitangent = bitangent;
	}
}
Пример #3
0
    bool Mesh::CreateCylinder(float bottomRadius, float topRadius, float height, u32 sliceCount, u32 stackCount, Mesh& mesh)
    {
        mesh.m_vertices.clear();
        mesh.m_indices.clear();

        float stackHeight = height / stackCount;
        float radiusStep = (topRadius - bottomRadius) / stackCount;

        u32 ringCount = stackCount + 1;

        // Compute vertices
        for (u32 i = 0; i < ringCount; ++i)
        {
            float y = -0.5f * height + i * stackHeight;
            float r = bottomRadius + i * radiusStep;

            // Vertics of ring
            float dTheta = 2.0f * FARLOR_PI / sliceCount;
            for (u32 j = 0; j < sliceCount; ++j)
            {
                VertexPositionUVNormal vertex;
                float c = cosf(j * dTheta);
                float s = sinf(j * dTheta);

                vertex.m_position = Vector3(r * c, y, r * s);

                vertex.m_uv.x = (float)j / sliceCount;
                vertex.m_uv.y = 1.0f - (float)i / stackCount;

                Vector3 tangent(-1.0f * s, 0.0f, c);
                float dr = bottomRadius - topRadius;
                Vector3 bitangent(dr * c, -1.0f * height, dr * s);

                vertex.m_normal = tangent.Cross(bitangent).Normalized();
            }
        }

        u32 ringVertexCount = sliceCount + 1;

        for (u32 i = 0; i < stackCount; ++i)
        {
            for (u32 j = 0; j < stackCount; ++j)
            {
                mesh.m_indices.push_back(i*ringVertexCount + j);
                mesh.m_indices.push_back((i+1)*ringVertexCount + j);
                mesh.m_indices.push_back((i+1)*ringVertexCount + j+1);
                mesh.m_indices.push_back(i*ringVertexCount + j);
                mesh.m_indices.push_back((i+1)*ringVertexCount + j+1);
                mesh.m_indices.push_back(i*ringVertexCount + j+1);
            }
        }

        //  No end cap geometry yet, need to do!!

        return true;
    }
Пример #4
0
	GLuint Bitangents(std::vector<T>& dest) const
	{
		unsigned k = 0, n = _vertex_count();
		dest.resize(n * 3);
		Vec3f bitangent(Normalized(_v));

		for(unsigned i=0; i!=n; ++i)
		{
			dest[k++] = T(bitangent.x());
			dest[k++] = T(bitangent.y());
			dest[k++] = T(bitangent.z());
		}
		//
		assert(k == dest.size());
		// 3 values per vertex
		return 3;
	}
Пример #5
0
void GeometryGenerator::CreateCylinder(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT stackCount, MeshData& meshData)
{
	meshData.Vertices.clear();
	meshData.Indices.clear();

	float stackHeight = height / stackCount;

	float radiusStep = (topRadius - bottomRadius) / stackCount;

	UINT ringCount = stackCount+1;

	for(UINT i = 0; i < ringCount; ++i)
	{
		float y = -0.5f*height + i*stackHeight;
		float r = bottomRadius + i*radiusStep;

		float dTheta = 2.0f*XM_PI/sliceCount;
		for(UINT j = 0; j <= sliceCount; ++j)
		{
			Vertex vertex;

			float c = cosf(j*dTheta);
			float s = sinf(j*dTheta);

			vertex.Position = glm::vec3(r*c, y, r*s);

			vertex.TexC.x = (float)j/sliceCount;
			vertex.TexC.y = 1.0f - (float)i/stackCount;

			vertex.TangentU = glm::vec3(-s, 0.0f, c);

			float dr = bottomRadius-topRadius;
			glm::vec3 bitangent(dr*c, -height, dr*s);

			glm::vec3 T = vertex.TangentU;
			glm::vec3 B = bitangent;
			glm::vec3 N = glm::normalize(glm::cross(T, B));
			vertex.Normal = N;

			meshData.Vertices.push_back(vertex);
		}
	}

	UINT ringVertexCount = sliceCount+1;

	for(UINT i = 0; i < stackCount; ++i)
	{
		for(UINT j = 0; j < sliceCount; ++j)
		{
			meshData.Indices.push_back(i*ringVertexCount + j);
			meshData.Indices.push_back((i+1)*ringVertexCount + j);
			meshData.Indices.push_back((i+1)*ringVertexCount + j+1);

			meshData.Indices.push_back(i*ringVertexCount + j);
			meshData.Indices.push_back((i+1)*ringVertexCount + j+1);
			meshData.Indices.push_back(i*ringVertexCount + j+1);
		}
	}

	BuildCylinderTopCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData);
	BuildCylinderBottomCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData);
}
double integrateD(const KernelD & F, const Element & e)
{
    double result = 0.0;

    // Get the quadrature rules for azimuthal and polar integrations
    namespace mpl = boost::mpl;
    typedef typename mpl::at<rules_map, mpl::int_<PhiPoints> >::type PhiPolicy;
    typedef typename mpl::at<rules_map, mpl::int_<ThetaPoints> >::type ThetaPolicy;
    QuadratureRule<PhiPolicy> phiRule;
    QuadratureRule<ThetaPolicy> thetaRule;
    int upper_phi = PhiPoints / 2; // Upper limit for loop on phi points
    int upper_theta = ThetaPoints / 2; // Upper limit for loop on theta points

    // Extract relevant data from Element
    int nVertices = e.nVertices();
    Eigen::Vector3d normal = e.normal();
    Sphere sph = e.sphere();
    Eigen::Matrix3Xd vertices = e.vertices();
    Eigen::Matrix3Xd arcs = e.arcs();

    // Calculation of the tangent and the bitangent (binormal) vectors
    // Tangent, Bitangent and Normal form a local reference frame:
    // T <-> x; B <-> y; N <-> z
    Eigen::Vector3d tangent, bitangent;
    tangent_and_bitangent(normal, tangent, bitangent);

    std::vector<double> theta(nVertices), phi(nVertices), phinumb(nVertices+1);
    std::vector<int> numb(nVertices+1);
    // Clean-up heap crap
    std::fill_n(theta.begin(),   nVertices,   0.0);
    std::fill_n(phi.begin(),     nVertices,   0.0);
    std::fill_n(numb.begin(),    nVertices+1, 0);
    std::fill_n(phinumb.begin(), nVertices+1, 0.0);
    // Populate arrays and redefine tangent and bitangent
    e.spherical_polygon(tangent, bitangent, theta, phi, phinumb, numb);

    // Actual integration occurs here
    for (int i = 0; i < nVertices; ++i) { // Loop on edges
        double phiLower = phinumb[i]; // Lower vertex of edge
        double phiUpper = phinumb[i+1]; // Upper vertex of edge
        double phiA = (phiUpper - phiLower) / 2.0;
        double phiB = (phiUpper + phiLower) / 2.0;
        double thetaLower = theta[numb[i]];
        double thetaUpper = theta[numb[i+1]];
        double thetaMax = 0.0;
        Eigen::Vector3d oc = (arcs.col(i) - sph.center) / sph.radius;
        double oc_norm = oc.norm();
        double oc_norm2 = std::pow(oc_norm, 2);
        for (int j = 0; j < upper_phi; ++j) { // Loop on Gaussian points: phi integration
            for (int k = 0; k <= 1; ++k) {
                double ph = (2*k - 1) * phiA * phiRule.abscissa(j) + phiB;
                double cos_phi = std::cos(ph);
                double sin_phi = std::sin(ph);
                if (oc_norm2 < 1.0e-07) { // This should check if oc_norm2 is zero
                    double cotg_thmax = (std::sin(ph-phiLower) / std::tan(thetaUpper) + std::sin(phiUpper-ph) / std::tan(
                                thetaLower)) / std::sin(phiUpper - phiLower);
                    thetaMax = std::atan(1.0 / cotg_thmax);
                } else {
                    Eigen::Vector3d scratch;
                    scratch << tangent.dot(oc), bitangent.dot(oc), normal.dot(oc);
                    double aa = std::pow(tangent.dot(oc)*cos_phi + bitangent.dot(oc)*sin_phi,
                            2) + std::pow(normal.dot(oc), 2);
                    double bb = -normal.dot(oc) * oc_norm2;
                    double cc = std::pow(oc_norm2,
                            2) - std::pow(tangent.dot(oc)*cos_phi + bitangent.dot(oc)*sin_phi, 2);
                    double ds = std::pow(bb, 2) - aa*cc;
                    if (ds < 0.0) ds = 0.0;
                    double cs = (-bb + std::sqrt(ds)) / aa;
                    if (cs > 1.0) cs = 1.0;
                    if (cs < -1.0) cs = 1.0;
                    thetaMax = std::acos(cs);
                }
                double thetaA = thetaMax / 2.0;
                double scratch = 0.0;
                if (!(thetaMax < 1.0e-08)) {
                    for (int l = 0; l < upper_theta; ++l) { // Loop on Gaussian points: theta integration
                        for (int m = 0; m <= 1; ++m) {
                            double th = (2*m - 1) * thetaA  * thetaRule.abscissa(l) + thetaA;
                            double cos_theta = std::cos(th);
                            double sin_theta = std::sin(th);
                            Eigen::Vector3d point;
                            point(0) = tangent(0) * sin_theta * cos_phi
                                + bitangent(0) * sin_theta * sin_phi
                                + normal(0) * (cos_theta - 1.0);
                            point(1) = tangent(1) * sin_theta * cos_phi
                                + bitangent(1) * sin_theta * sin_phi
                                + normal(1) * (cos_theta - 1.0);
                            point(2) = tangent(2) * sin_theta * cos_phi
                                + bitangent(2) * sin_theta * sin_phi
                                + normal(2) * (cos_theta - 1.0);
                            double value = F(e.normal(),
                                    Eigen::Vector3d::Zero(),
                                    point); // Evaluate integrand at Gaussian point
                            scratch += std::pow(sph.radius, 2) * value * sin_theta * thetaA * thetaRule.weight(l);
                        }
                    }
                    result += scratch * phiA * phiRule.weight(j);
                }
            }
        }
    }
    return result;
}
Пример #7
0
void mesh::calculateTangents() {
	std::vector<float> tans(3*vertCount, 0);
	std::vector<float> bitans(3*vertCount, 0);
	tangents.resize(4 * vertCount);

	//calculate tentative tangents and bitangents for each triangle
	for (int i = 0; i < triCount; i++) {
		//find the vertices of the current triangle, and their UV coords
		int vi1 = triangles[3*i];
		int vi2 = triangles[3*i + 1];
		int vi3 = triangles[3*i + 2];

		glm::vec3 vert0(vertices[3*vi1], vertices[3*vi1 + 1], vertices[3*vi1 + 2]);
		glm::vec3 vert1(vertices[3*vi2], vertices[3*vi2 + 1], vertices[3*vi2 + 2]);
		glm::vec3 vert2(vertices[3*vi3], vertices[3*vi3 + 1], vertices[3*vi3 + 2]);

		glm::vec2 uv0(texCoords[2*vi1], texCoords[2*vi1 + 1]);
		glm::vec2 uv1(texCoords[2*vi2], texCoords[2*vi2 + 1]);
		glm::vec2 uv2(texCoords[2*vi3], texCoords[2*vi3 + 1]);

		//differences in position and UV coords
		glm::vec3 dPos1 = vert1 - vert0;
		glm::vec3 dPos2 = vert2 - vert0;

		glm::vec2 dUV1 = uv1 - uv0;
		glm::vec2 dUV2 = uv2 - uv0;

		//calculate and store the tangent and bitangent
		float coeff = 1.0f / (dUV1.x * dUV2.y - dUV1.y * dUV2.x);

		glm::vec3 tan = dPos1 * dUV2.y - dPos2 * dUV1.y;
		glm::vec3 bitan = dPos2 * dUV1.x  - dPos1 * dUV2.x;
		tan *= coeff;
		bitan *= coeff;

		tans[3*vi1] += tan.x;
		tans[3*vi1 + 1] += tan.y;
		tans[3*vi1 + 2] += tan.z;

		tans[3*vi2] += tan.x;
		tans[3*vi2 + 1] += tan.y;
		tans[3*vi2 + 2] += tan.z;

		tans[3*vi3] += tan.x;
		tans[3*vi3 + 1] += tan.y;
		tans[3*vi3 + 2] += tan.z;

		bitans[3*vi1] += bitan.x;
		bitans[3*vi1 + 1] += bitan.y;
		bitans[3*vi1 + 2] += bitan.z;

		bitans[3*vi2] += bitan.x;
		bitans[3*vi2 + 1] += bitan.y;
		bitans[3*vi2 + 2] += bitan.z;

		bitans[3*vi3] += bitan.x;
		bitans[3*vi3 + 1] += bitan.y;
		bitans[3*vi3 + 2] += bitan.z;
	}

	//find the final tangent (and bitangent) for each vertex
	for (int j = 0; j < vertCount; j++) {
		glm::vec3 normal (normals[3*j], normals[3*j + 1], normals[3*j + 2]);
		glm::vec3 tangent (tans[3*j], tans[3*j + 1], tans[3*j + 2]);
		glm::vec3 bitangent (bitans[3*j], bitans[3*j + 1], bitans[3*j + 2]);

		glm::normalize(tangent);
		glm::normalize(bitangent);

		//orthagonalize
		glm::vec3 tangent_orth(normal);
		tangent_orth *= glm::dot(normal, tangent);
		tangent_orth = tangent - tangent_orth;
		glm::normalize(tangent_orth);

		//compute handedness
		float handedness = 1.0f;
		glm::vec3 nCrossT = glm::cross(normal, tangent_orth);
		
		if(glm::dot(nCrossT, bitangent) > 0) {
			handedness = 1.0f;
		} else {
			handedness = -1.0f;
		}

		//store the orthagonalized tangent and handedness
		tangents[4*j] = tangent_orth.x;
		tangents[4*j + 1] = tangent_orth.y;
		tangents[4*j + 2] = tangent_orth.z;
		tangents[4*j + 3] = handedness;
	}

}