//----------------------------------------------------------------------------
void IntersectingBoxes::ModifyMesh (int i)
{
    Vector3f center(
        0.5f*(mBoxes[i].Min[0] + mBoxes[i].Max[0]),
        0.5f*(mBoxes[i].Min[1] + mBoxes[i].Max[1]),
        0.5f*(mBoxes[i].Min[2] + mBoxes[i].Max[2]));

    float xExtent = 0.5f*(mBoxes[i].Max[0] - mBoxes[i].Min[0]);
    float yExtent = 0.5f*(mBoxes[i].Max[1] - mBoxes[i].Min[1]);
    float zExtent = 0.5f*(mBoxes[i].Max[2] - mBoxes[i].Min[2]);

    Vector3f xTerm = xExtent*Vector3f::UNIT_X;
    Vector3f yTerm = yExtent*Vector3f::UNIT_Y;
    Vector3f zTerm = zExtent*Vector3f::UNIT_Z;

    TriMesh* mesh = StaticCast<TriMesh>(mScene->GetChild(i));
    VertexBufferAccessor vba(mesh);

    vba.Position<Vector3f>(0) = center - xTerm - yTerm - zTerm;
    vba.Position<Vector3f>(1) = center + xTerm - yTerm - zTerm;
    vba.Position<Vector3f>(2) = center + xTerm + yTerm - zTerm;
    vba.Position<Vector3f>(3) = center - xTerm + yTerm - zTerm;
    vba.Position<Vector3f>(4) = center - xTerm - yTerm + zTerm;
    vba.Position<Vector3f>(5) = center + xTerm - yTerm + zTerm;
    vba.Position<Vector3f>(6) = center + xTerm + yTerm + zTerm;
    vba.Position<Vector3f>(7) = center - xTerm + yTerm + zTerm;

    mesh->UpdateModelSpace(Visual::GU_NORMALS);
    mRenderer->Update(mesh->GetVertexBuffer());
}
Example #2
0
//----------------------------------------------------------------------------
TriMesh* StandardMesh::Cylinder (int axisSamples, int radialSamples,
    float radius, float height, bool open)
{
    TriMesh* mesh;
    int unit;
    Float2 tcoord;

    if (open)
    {
        int numVertices = axisSamples*(radialSamples+1);
        int numTriangles = 2*(axisSamples-1)*radialSamples;
        int numIndices = 3*numTriangles;
        int stride = mVFormat->GetStride();

        // Create a vertex buffer.
        VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, stride,
            mUsage);

        VertexBufferAccessor vba(mVFormat, vbuffer);

        // Generate geometry.
        float invRS = 1.0f/(float)radialSamples;
        float invASm1 = 1.0f/(float)(axisSamples-1);
        float halfHeight = 0.5f*height;
        int r, a, aStart, i;

        // Generate points on the unit circle to be used in computing the
        // mesh points on a cylinder slice.
        float* cs = new1<float>(radialSamples + 1);
        float* sn = new1<float>(radialSamples + 1);
        for (r = 0; r < radialSamples; ++r)
        {
            float angle = Mathf::TWO_PI*invRS*r;
            cs[r] = Mathf::Cos(angle);
            sn[r] = Mathf::Sin(angle);
        }
        cs[radialSamples] = cs[0];
        sn[radialSamples] = sn[0];

        // Generate the cylinder itself.
        for (a = 0, i = 0; a < axisSamples; ++a)
        {
            float axisFraction = a*invASm1;  // in [0,1]
            float z = -halfHeight + height*axisFraction;

            // Compute center of slice.
            APoint sliceCenter(0.0f, 0.0f, z);

            // Compute slice vertices with duplication at endpoint.
            int save = i;
            for (r = 0; r < radialSamples; ++r)
            {
                float radialFraction = r*invRS;  // in [0,1)
                AVector normal(cs[r], sn[r], 0.0f);

                vba.Position<Float3>(i) = sliceCenter + radius*normal;

                if (mHasNormals)
                {
                    if (mInside)
                    {
                        vba.Normal<Float3>(i) = -normal;
                    }
                    else
                    {
                        vba.Normal<Float3>(i) = normal;
                    }
                }

                tcoord = Float2(radialFraction, axisFraction);
                for (unit = 0; unit < MAX_UNITS; ++unit)
                {
                    if (mHasTCoords[unit])
                    {
                        vba.TCoord<Float2>(unit, i) = tcoord;
                    }
                }

                ++i;
            }

            vba.Position<Float3>(i) = vba.Position<Float3>(save);

            if (mHasNormals)
            {
                vba.Normal<Float3>(i) = vba.Normal<Float3>(save);
            }

            tcoord = Float2(1.0f, axisFraction);
            for (unit = 0; unit < MAX_UNITS; ++unit)
            {
                if (mHasTCoords[unit])
                {
                    vba.TCoord<Float2>(0, i) = tcoord;
                }
            }

            ++i;
        }
        TransformData(vba);

        // Generate indices.
        IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, 4, mUsage);
        int* indices = (int*)ibuffer->GetData();
        for (a = 0, aStart = 0; a < axisSamples-1; ++a)
        {
            int i0 = aStart;
            int i1 = i0 + 1;
            aStart += radialSamples + 1;
            int i2 = aStart;
            int i3 = i2 + 1;
            for (i = 0; i < radialSamples; ++i, indices += 6)
            {
                if (mInside)
                {
                    indices[0] = i0++;
                    indices[1] = i2;
                    indices[2] = i1;
                    indices[3] = i1++;
                    indices[4] = i2++;
                    indices[5] = i3++;
                }
                else // outside view
                {
                    indices[0] = i0++;
                    indices[1] = i1;
                    indices[2] = i2;
                    indices[3] = i1++;
                    indices[4] = i3++;
                    indices[5] = i2++;
                }
            }
        }

        delete1(cs);
        delete1(sn);

        mesh = new0 TriMesh(mVFormat, vbuffer, ibuffer);
    }
    else
    {
        mesh = Sphere(axisSamples, radialSamples, radius);
        VertexBuffer* vbuffer = mesh->GetVertexBuffer();
        int numVertices = vbuffer->GetNumElements();

        VertexBufferAccessor vba(mVFormat, vbuffer);

        // Flatten sphere at poles.
        float hDiv2 = 0.5f*height;
        vba.Position<Float3>(numVertices-2)[2] = -hDiv2;  // south pole
        vba.Position<Float3>(numVertices-1)[2] = +hDiv2;  // north pole

        // Remap z-values to [-h/2,h/2].
        float zFactor = 2.0f/(axisSamples-1);
        float tmp0 = radius*(-1.0f + zFactor);
        float tmp1 = 1.0f/(radius*(+1.0f - zFactor));
        for (int i = 0; i < numVertices-2; ++i)
        {
            Float3& pos = vba.Position<Float3>(i);
            pos[2] = hDiv2*(-1.0f + tmp1*(pos[2] - tmp0));
            float adjust = radius*Mathf::InvSqrt(pos[0]*pos[0] +
                pos[1]*pos[1]);
            pos[0] *= adjust;
            pos[1] *= adjust;
        }
        TransformData(vba);

        if (mHasNormals)
        {
            mesh->UpdateModelSpace(Visual::GU_NORMALS);
        }
    }

    // The duplication of vertices at the seam causes the automatically
    // generated bounding volume to be slightly off center.  Reset the bound
    // to use the true information.
    float maxDist = Mathf::Sqrt(radius*radius + height*height);
    mesh->GetModelBound().SetCenter(APoint::ORIGIN);
    mesh->GetModelBound().SetRadius(maxDist);
    return mesh;
}
Example #3
0
//----------------------------------------------------------------------------
TriMesh* StandardMesh::Box (float xExtent, float yExtent, float zExtent)
{
    int numVertices = 8;
    int numTriangles = 12;
    int numIndices = 3*numTriangles;
    int stride = mVFormat->GetStride();

    // Create a vertex buffer.
    VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, stride, mUsage);
    VertexBufferAccessor vba(mVFormat, vbuffer);

    // Generate geometry.
    vba.Position<Float3>(0) = Float3(-xExtent, -yExtent, -zExtent);
    vba.Position<Float3>(1) = Float3(+xExtent, -yExtent, -zExtent);
    vba.Position<Float3>(2) = Float3(+xExtent, +yExtent, -zExtent);
    vba.Position<Float3>(3) = Float3(-xExtent, +yExtent, -zExtent);
    vba.Position<Float3>(4) = Float3(-xExtent, -yExtent, +zExtent);
    vba.Position<Float3>(5) = Float3(+xExtent, -yExtent, +zExtent);
    vba.Position<Float3>(6) = Float3(+xExtent, +yExtent, +zExtent);
    vba.Position<Float3>(7) = Float3(-xExtent, +yExtent, +zExtent);
    for (int unit = 0; unit < MAX_UNITS; ++unit)
    {
        if (mHasTCoords[unit])
        {
            vba.TCoord<Float2>(unit, 0) = Float2(0.25f, 0.75f);
            vba.TCoord<Float2>(unit, 1) = Float2(0.75f, 0.75f);
            vba.TCoord<Float2>(unit, 2) = Float2(0.75f, 0.25f);
            vba.TCoord<Float2>(unit, 3) = Float2(0.25f, 0.25f);
            vba.TCoord<Float2>(unit, 4) = Float2(0.0f, 1.0f);
            vba.TCoord<Float2>(unit, 5) = Float2(1.0f, 1.0f);
            vba.TCoord<Float2>(unit, 6) = Float2(1.0f, 0.0f);
            vba.TCoord<Float2>(unit, 7) = Float2(0.0f, 0.0f);
        }
    }
    TransformData(vba);

    // Generate indices (outside view).
    IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, 4, mUsage);
    int* indices = (int*)ibuffer->GetData();
    indices[ 0] = 0;  indices[ 1] = 2;  indices[ 2] = 1;
    indices[ 3] = 0;  indices[ 4] = 3;  indices[ 5] = 2;
    indices[ 6] = 0;  indices[ 7] = 1;  indices[ 8] = 5;
    indices[ 9] = 0;  indices[10] = 5;  indices[11] = 4;
    indices[12] = 0;  indices[13] = 4;  indices[14] = 7;
    indices[15] = 0;  indices[16] = 7;  indices[17] = 3;
    indices[18] = 6;  indices[19] = 4;  indices[20] = 5;
    indices[21] = 6;  indices[22] = 7;  indices[23] = 4;
    indices[24] = 6;  indices[25] = 5;  indices[26] = 1;
    indices[27] = 6;  indices[28] = 1;  indices[29] = 2;
    indices[30] = 6;  indices[31] = 2;  indices[32] = 3;
    indices[33] = 6;  indices[34] = 3;  indices[35] = 7;

    if (mInside)
    {
        ReverseTriangleOrder(numTriangles, indices);
    }

    TriMesh* mesh = new0 TriMesh(mVFormat, vbuffer, ibuffer);
    if (mHasNormals)
    {
        mesh->UpdateModelSpace(Visual::GU_NORMALS);
    }
    return mesh;
}
//----------------------------------------------------------------------------
void BoxSurface::UpdateSurface ()
{
	int permute[3];
	TriMesh* mesh;
	VertexFormat* vformat;
	VertexBuffer* vbuffer;

	// u faces
	permute[0] = 1;
	permute[1] = 2;
	permute[2] = 0;

	// u = 0
	mesh = StaticCast<TriMesh>(GetChild(0));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumWSamples, mNumVSamples, vformat, vbuffer, false, 0.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// u = 1
	mesh = StaticCast<TriMesh>(GetChild(1));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumWSamples, mNumVSamples, vformat, vbuffer, true, 1.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// v faces
	permute[0] = 0;
	permute[1] = 2;
	permute[2] = 1;

	// v = 0
	mesh = StaticCast<TriMesh>(GetChild(2));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumWSamples, mNumUSamples, vformat, vbuffer, true, 0.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// v = 1
	mesh = StaticCast<TriMesh>(GetChild(3));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumWSamples, mNumUSamples, vformat, vbuffer, false, 1.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// w faces
	permute[0] = 0;
	permute[1] = 1;
	permute[2] = 2;

	// w = 0
	mesh = StaticCast<TriMesh>(GetChild(4));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumVSamples, mNumUSamples, vformat, vbuffer, false, 0.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);

	// w = 1
	mesh = StaticCast<TriMesh>(GetChild(5));
	vformat = mesh->GetVertexFormat();
	vbuffer = mesh->GetVertexBuffer();
	UpdateFace(mNumVSamples, mNumUSamples, vformat, vbuffer, true, 1.0f,
		permute);
	mesh->UpdateModelSpace(Renderable::GU_NORMALS);
	Renderer::UpdateAll(vbuffer);
}
//----------------------------------------------------------------------------
Node* SimplePendulumFriction::CreatePendulum ()
{
	VertexFormat* vformat = VertexFormat::Create(2,
	                        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
	                        VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0);

	StandardMesh sm(vformat);

	// Pendulum rod.
	TriMesh* rod = sm.Cylinder(2, 8, 0.05f, 12.0f, true);
	rod->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 10.0f));

	// The pendulum bulb.  Start with a sphere (to get the connectivity) and
	// then adjust the vertices to form a pair of joined cones.
	TriMesh* bulb = sm.Sphere(16, 32, 2.0f);
	VertexBufferAccessor vba(bulb);
	int numVertices = vba.GetNumVertices();
	int i;
	for (i = 0; i < numVertices; ++i)
	{
		Float3& pos = vba.Position<Float3>(i);
		float r = Mathf::Sqrt(pos[0]*pos[0] + pos[1]*pos[1]);
		float z = pos[2] + 2.0f;
		if (z >= 2.0f)
		{
			z = 4.0f - r;
		}
		else
		{
			z = r;
		}
		pos[2] = z;
	}

	// Translate the pendulum joint to the origin for the purpose of
	// rotation.
	for (i = 0; i < numVertices; ++i)
	{
		vba.Position<Float3>(i)[2] -= 16.0f;
	}
	bulb->UpdateModelSpace(Visual::GU_NORMALS);

	vba.ApplyTo(rod);
	numVertices = vba.GetNumVertices();
	for (i = 0; i < numVertices; ++i)
	{
		vba.Position<Float3>(i)[2] -= 16.0f;
	}
	rod->UpdateModelSpace(Visual::GU_NORMALS);

	// Group the objects into a single subtree.
	mPendulum = new0 Node();
	mPendulum->AttachChild(rod);
	mPendulum->AttachChild(bulb);

	// Translate back to original model position.
	mPendulum->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 16.0f));

	// Add a material for coloring.
	Float4 black(0.0f, 0.0f, 0.0f, 1.0f);
	Float4 white(1.0f, 1.0f, 1.0f, 1.0f);
	Material* material = new0 Material();
	material->Emissive = black;
	material->Ambient = Float4(0.1f, 0.1f, 0.1f, 1.0f);
	material->Diffuse = Float4(0.99607f, 0.83920f, 0.67059f, 1.0f);
	material->Specular = black;

	// Use two lights to illuminate the pendulum.
	Light* light[2];
	light[0] = new0 Light(Light::LT_DIRECTIONAL);
	light[0]->Ambient = white;
	light[0]->Diffuse = white;
	light[0]->Specular = black;
	light[0]->SetDirection(AVector(-1.0f, -1.0f, 0.0f));

	light[1] = new0 Light(Light::LT_DIRECTIONAL);
	light[1]->Ambient = white;
	light[1]->Diffuse = white;
	light[1]->Specular = black;
	light[1]->SetDirection(AVector(+1.0f, -1.0f, 0.0f));

	// TODO:  The following code is used to piece together an effect with
	// two passes.  It is better to write an effect whose vertex shader
	// has constants corresponding to the two lights (for a single-pass
	// effect).
	LightDirPerVerEffect* effect = new0 LightDirPerVerEffect();
	VisualTechnique* technique = effect->GetTechnique(0);
	VisualPass* pass0 = technique->GetPass(0);
	VisualPass* pass1 = new0 VisualPass();
	pass1->SetVertexShader(pass0->GetVertexShader());
	pass1->SetPixelShader(pass0->GetPixelShader());
	AlphaState* astate = new0 AlphaState();
	astate->BlendEnabled = true;
	astate->SrcBlend = AlphaState::SBM_ONE;
	astate->DstBlend = AlphaState::DBM_ONE;
	pass1->SetAlphaState(astate);
	pass1->SetCullState(pass0->GetCullState());
	pass1->SetDepthState(pass0->GetDepthState());
	pass1->SetStencilState(pass0->GetStencilState());
	pass1->SetOffsetState(pass0->GetOffsetState());
	pass1->SetWireState(pass0->GetWireState());
	technique->InsertPass(pass1);

	VisualEffectInstance* instance = new0 VisualEffectInstance(effect, 0);
	for (int pass = 0; pass < 2; ++pass)
	{
		instance->SetVertexConstant(pass, 0,
		                            new0 PVWMatrixConstant());
		instance->SetVertexConstant(pass, 1,
		                            new0 CameraModelPositionConstant());
		instance->SetVertexConstant(pass, 2,
		                            new0 MaterialEmissiveConstant(material));
		instance->SetVertexConstant(pass, 3,
		                            new0 MaterialAmbientConstant(material));
		instance->SetVertexConstant(pass, 4,
		                            new0 MaterialDiffuseConstant(material));
		instance->SetVertexConstant(pass, 5,
		                            new0 MaterialSpecularConstant(material));
		instance->SetVertexConstant(pass, 6,
		                            new0 LightModelDVectorConstant(light[pass]));
		instance->SetVertexConstant(pass, 7,
		                            new0 LightAmbientConstant(light[pass]));
		instance->SetVertexConstant(pass, 8,
		                            new0 LightDiffuseConstant(light[pass]));
		instance->SetVertexConstant(pass, 9,
		                            new0 LightSpecularConstant(light[pass]));
		instance->SetVertexConstant(pass, 10,
		                            new0 LightAttenuationConstant(light[pass]));
	}

	rod->SetEffectInstance(instance);
	bulb->SetEffectInstance(instance);

	return mPendulum;
}
//----------------------------------------------------------------------------
TriMesh *UniMaterialMesh::ToTriMesh()
{
	if (mVertexMapQuantity == 0)
		return 0;

	// VertexBuffer
	VertexFormat *vFormat = new0 VertexFormat();
	vFormat->Add(VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0);
	if (mNormalMap)
	{
		vFormat->Add(VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0);
	}
	if (mExportTargentBinormal)
	{
		vFormat->Add(VertexFormat::AU_TANGENT, VertexFormat::AT_FLOAT3, 0);
		vFormat->Add(VertexFormat::AU_BINORMAL, VertexFormat::AT_FLOAT3, 0);
	}
	if (mExportColor)
	{
		vFormat->Add(VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0);
	}
	if (mTextureCoordMap)
	{
		if (1 == mNumTexcoordToExport)
		{
			vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
		}
		else if (2 == mNumTexcoordToExport)
		{
			vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
			vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 1);
		}
	}
	if (mExportSkin)
	{
		vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT4, 1);
		vFormat->Add(VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT4, 2);
	}

	vFormat->Create();

	PX2::VertexBuffer *vBuffer = new0 PX2::VertexBuffer(mVertexMapQuantity, 
		vFormat->GetStride());

	VertexBufferAccessor vBA(vFormat, vBuffer);

	for (int i=0; i<mVertexMapQuantity; i++)
	{
		vBA.Position<Float3>(i) = mVertexMap[i];

		if (mNormalMap)
		{
			vBA.Normal<Float3>(i) = mNormalMap[i];
		}

		if (mColorMap)
		{
			vBA.Color<Float4>(0, i) = Float4(mColorMap[i][0], mColorMap[i][1],
				mColorMap[i][2], mColorMap[i][3]);
		}
		else
		{
			if (mExportColor)
				vBA.Color<Float4>(0, i) = Float4::WHITE;
		}

		if (mAlphaMap)
		{
			vBA.Color<Float4>(0, i) = Float4(mColorMap[i][0], mColorMap[i][1],
				mColorMap[i][2], mAlphaMap[i]);
		}

		if (mTextureCoordMap)
		{
			if (mNumTexcoordToExport == 1)
			{
				vBA.TCoord<Float2>(0, i) = Float2(mTextureCoordMap[i][0], 1.0f-mTextureCoordMap[i][1]);
			}
			else if (mNumTexcoordToExport == 2)
			{
				Float2 texCoord0 = Float2(mTextureCoordMap[i][0], 1.0f-mTextureCoordMap[i][1]);

				vBA.TCoord<Float2>(0, i) = texCoord0;

				if (mTextureCoordMap1)
				{
					vBA.TCoord<Float2>(1, i) = Float2(mTextureCoordMap1[i][0], 1.0f-mTextureCoordMap1[i][1]);
				}
				else
				{
					vBA.TCoord<Float2>(1, i) = texCoord0;
				}
			}
		}
	}
	
	// IndexBuffer
	IndexBuffer *iBuffer = new0 IndexBuffer(3*mFQuantity, 2);
	unsigned short *iData = (unsigned short*)iBuffer->GetData();
	for (int i=0; i<(int)3*mFQuantity; i++)
	{
		iData[i] = (unsigned short)mVFace[i];
	}

	// 创建Mesh
	TriMesh *triMesh = new0 TriMesh(vFormat, vBuffer, iBuffer);
	triMesh->UpdateModelSpace(Renderable::GU_MODEL_BOUND_ONLY);
	if (mExportTargentBinormal)
	{
		triMesh->UpdateModelSpace(Renderable::GU_USE_GEOMETRY);
	}

	MaterialInstance *mi = 0;
	mi = mMaterialInstance;

	triMesh->SetMaterialInstance(mi);
	triMesh->SetShine(mShine);

	return triMesh;
}