//----------------------------------------------------------------------------
void CollisionsBoundTree::Response (CRecord& record0, int t0,
    CRecord& record1, int t1, Intersector<float,Vector3f>*)
{
    CollisionsBoundTree* app = (CollisionsBoundTree*)TheApplication;

    // Mesh0 triangles that are intersecting change from blue to cyan.
    TriMesh* mesh = record0.GetMesh();
    VertexBufferAccessor vba(mesh);
    const int* indices = (int*)mesh->GetIndexBuffer()->GetData();
    int i0 = indices[3*t0];
    int i1 = indices[3*t0 + 1];
    int i2 = indices[3*t0 + 2];
    vba.TCoord<Float2>(0, i0) = app->mCyanUV;
    vba.TCoord<Float2>(0, i1) = app->mCyanUV;
    vba.TCoord<Float2>(0, i2) = app->mCyanUV;
    app->mRenderer->Update(mesh->GetVertexBuffer());

    // Mesh1 triangles that are intersecting change from red to yellow.
    mesh = record1.GetMesh();
    vba.ApplyTo(mesh);
    indices = (int*)mesh->GetIndexBuffer()->GetData();
    i0 = indices[3*t1];
    i1 = indices[3*t1 + 1];
    i2 = indices[3*t1 + 2];
    vba.TCoord<Float2>(0 ,i0) = app->mYellowUV;
    vba.TCoord<Float2>(0, i1) = app->mYellowUV;
    vba.TCoord<Float2>(0, i2) = app->mYellowUV;
    app->mRenderer->Update(mesh->GetVertexBuffer());

    // NOTE: See the comments in Wm5CollisionGroup.h about information that
    // is available from the Intersector<float,Vector3f> object.
}
//----------------------------------------------------------------------------
TriMesh* PolyhedronDistance::CreatePlane ()
{
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);

    float size = 16.0f;
    vba.Position<Float3>(0) = Float3(-size, -size, -0.1f);
    vba.Position<Float3>(1) = Float3(+size, -size, -0.1f);
    vba.Position<Float3>(2) = Float3(+size, +size, -0.1f);
    vba.Position<Float3>(3) = Float3(-size, +size, -0.1f);
    vba.Color<Float3>(0, 0) = Float3(0.0f, 0.50f, 0.00f);
    vba.Color<Float3>(0, 1) = Float3(0.0f, 0.25f, 0.00f);
    vba.Color<Float3>(0, 2) = Float3(0.0f, 0.75f, 0.00f);
    vba.Color<Float3>(0, 3) = Float3(0.0f, 1.00f, 0.00f);

    IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[0] = 0; indices[1] = 1; indices[2] = 2;
    indices[3] = 0; indices[4] = 2; indices[5] = 3;

    TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer);
    mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());

    return mesh;
}
//----------------------------------------------------------------------------
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());
}
Beispiel #4
0
//----------------------------------------------------------------------------
void Polysegments::CreateScene ()
{
    mScene = new0 Node();

    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(128, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);
    for (int i = 0; i < vba.GetNumVertices(); ++i)
    {
        vba.Position<Float3>(i) = Float3(Mathf::SymmetricRandom(),
            Mathf::SymmetricRandom(), Mathf::SymmetricRandom());
        vba.Color<Float3>(0, i) = Float3(Mathf::UnitRandom(),
            Mathf::UnitRandom(), Mathf::UnitRandom());
    }

    mPolysegment = new0 Polysegment(vformat, vbuffer, true);
    mPolysegment->SetEffectInstance(
        VertexColor3Effect::CreateUniqueInstance());

    mScene->AttachChild(mPolysegment);
}
Beispiel #5
0
//----------------------------------------------------------------------------
Polysegment* BSplineFitContinuous::ReducedPolysegment (int numCtrlPoints,
    Vector3d* ctrlPoints, double fraction)
{
    int numLSCtrlPoints;
    Vector3d* lsCtrlPoints;
    BSplineReduction3d(numCtrlPoints, ctrlPoints, mDegree, fraction,
        numLSCtrlPoints, lsCtrlPoints);

    BSplineCurve3d spline(numLSCtrlPoints, lsCtrlPoints, mDegree, false,
        true);
    delete1(lsCtrlPoints);

    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(numCtrlPoints, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);
    Float3 blue(0.0f, 0.0f, 1.0f);
    for (int i = 0; i < numCtrlPoints; ++i)
    {
        double t = i/(double)numCtrlPoints;
        Vector3d pos = spline.GetPosition(t);
        vba.Position<Float3>(i) = Float3((float)pos[0], (float)pos[1],
            (float)pos[2]);
        vba.Color<Float3>(0, i) = blue;
    }

    Polysegment* segment = new0 Polysegment(vformat, vbuffer, true);
    segment->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());
    return segment;
}
Beispiel #6
0
//----------------------------------------------------------------------------
void BouncingBall::CreateFloor ()
{
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);

    const float xExtent = 8.0f;
    const float yExtent = 16.0f;
    const float zValue = 0.0f;
    vba.Position<Float3>(0) = Float3(-xExtent, -yExtent, zValue);
    vba.Position<Float3>(1) = Float3(+xExtent, -yExtent, zValue);
    vba.Position<Float3>(2) = Float3(+xExtent, +yExtent, zValue);
    vba.Position<Float3>(3) = Float3(-xExtent, +yExtent, zValue);
    vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
    vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
    vba.TCoord<Float2>(0, 2) = Float2(1.0f, 1.0f);
    vba.TCoord<Float2>(0, 3) = Float2(0.0f, 1.0f);

    IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
    indices[3] = 0;  indices[4] = 2;  indices[5] = 3;

    mFloor = new0 TriMesh(vformat, vbuffer, ibuffer);

    std::string path = Environment::GetPathR("Floor.wmtf");
    Texture2D* texture = Texture2D::LoadWMTF(path);
    mFloor->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture,
        Shader::SF_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT));
}
//----------------------------------------------------------------------------
Polypoint* FoucaultPendulum::CreatePath ()
{
    // Points used to display path of pendulum.
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    const int numPoints = 8192;
    VertexBuffer* vbuffer = new0 VertexBuffer(numPoints, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);

    Float3 zero(0.0f, 0.0f, 0.0f);
    Float3 white(1.0f, 1.0f, 1.0f);
    for (int i = 0; i < numPoints; ++i)
    {
        vba.Position<Float3>(i) = zero;
        vba.Color<Float3>(0, i) = white;
    }

    mPath = new0 Polypoint(vformat, vbuffer);
    mPath->SetNumPoints(1);
    mNextPoint = 0;
    mColorDiff = 1.0f/(float)numPoints;

    mPath->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());

    return mPath;
}
//----------------------------------------------------------------------------
void BouncingSpheres::CreateBackWall ()
{
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    Float3 backWallColor(209.0f/255.0f, 204.0f/255.0f, 180.0f/255.0f);

    VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);
    vba.Position<Float3>(0) = Float3(1.0f,  1.0f,  1.0f);
    vba.Position<Float3>(1) = Float3(1.0f, 20.0f,  1.0f);
    vba.Position<Float3>(2) = Float3(1.0f, 20.0f, 17.0f);
    vba.Position<Float3>(3) = Float3(1.0f,  1.0f, 17.0f);
    vba.Color<Float3>(0, 0) = backWallColor;
    vba.Color<Float3>(0, 1) = backWallColor;
    vba.Color<Float3>(0, 2) = backWallColor;
    vba.Color<Float3>(0, 3) = backWallColor;

    IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
    indices[3] = 0;  indices[4] = 2;  indices[5] = 3;

    mBackWall = new0 TriMesh(vformat, vbuffer, ibuffer);
    mBackWall->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());
}
Beispiel #9
0
//----------------------------------------------------------------------------
void VolumeFog::CreateScene ()
{
    // Create a screen-space camera for the background image.
    mScreenCamera = ScreenTarget::CreateCamera();

    // Create a screen polygon for the background image.
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);

    mScreenPolygon = ScreenTarget::CreateRectangle(vformat, GetWidth(),
        GetHeight(), 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);

    std::string skyName = Environment::GetPathR("BlueSky.wmtf");
    Texture2D* skyTexture = Texture2D::LoadWMTF(skyName);
    Texture2DEffect* skyEffect = new0 Texture2DEffect();
    mScreenPolygon->SetEffectInstance(skyEffect->CreateInstance(skyTexture));

    // Create the scene graph for the terrain.
    mScene = new0 Node();

    // Begin with a flat height field.
    vformat = VertexFormat::Create(3,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0,
        VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);

    mMesh = StandardMesh(vformat).Rectangle(64, 64, 8.0f, 8.0f);
    mScene->AttachChild(mMesh);

    // Set the heights based on a precomputed height field.  Also create a
    // texture image to go with the height field.
    std::string heightFieldName = Environment::GetPathR("HeightField.wmtf");
    Texture2D* heightTexture = Texture2D::LoadWMTF(heightFieldName);
    unsigned char* data = (unsigned char*)heightTexture->GetData(0);
    Float4 white(1.0f, 1.0f, 1.0f, 0.0f);
    VertexBufferAccessor vba(mMesh);
    for (int i = 0; i < vba.GetNumVertices(); ++i)
    {
        unsigned char value = *data;
        float height = 3.0f*value/255.0f + 0.05f*Mathf::SymmetricRandom();

        *data++ = (unsigned char)Mathf::IntervalRandom(32.0f, 64.0f);
        *data++ = 3*(128 - value/2)/4;
        *data++ = 0;
        *data++ = 255;

        vba.Position<Float3>(i)[2] = height;

        // The fog color is white.  The alpha channel is filled in by the
        // function UpdateFog().
        vba.Color<Float4>(0, i) = white;
    }

    UpdateFog();

    std::string effectFile = Environment::GetPathR("VolumeFog.wmfx");
    VolumeFogEffect* effect = new0 VolumeFogEffect(effectFile);
    mMesh->SetEffectInstance(effect->CreateInstance(heightTexture));
}
Beispiel #10
0
//----------------------------------------------------------------------------
void BlendedAnimations::Update ()
{
	// Animate the biped.
	mManager.Update(mUpArrowPressed, mShiftPressed);
	mScene->Update(mAnimTime);
	mAnimTime += mAnimTimeDelta;

	// Give the impression the floor is moving by translating the texture
	// coordinates.  For this demo, the texture coordinates are modified in
	// the vertex buffer.  Generally, you could write a vertex shader with
	// time and velocity as inputs, and then compute the new texture
	// coordinates in the shader.
#ifdef _DEBUG
	float adjust = mManager.GetSpeed()/16.0f;
#else
	float adjust = mManager.GetSpeed()/160.0f;
#endif
	VertexBufferAccessor vba(mFloor);
	for (int i = 0; i < vba.GetNumVertices(); ++i)
	{
		Float2& tcoord = vba.TCoord<Float2>(0, i);
		tcoord[1] -= adjust;
	}
	mRenderer->Update(mFloor->GetVertexBuffer());
}
Beispiel #11
0
//----------------------------------------------------------------------------
void BlendedAnimations::CreateScene ()
{
	mWireState = new0 WireState();
	mRenderer->SetOverrideWireState(mWireState);

	mScene = new0 Node();
	mScene->AttachChild(mManager.GetRoot());

	// Create a floor to walk on.
	VertexFormat* vformat = VertexFormat::Create(3,
	                        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
	                        VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0,
	                        VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);

	mFloor = StandardMesh(vformat).Rectangle(2, 2, 1024.0f, 2048.0f);
	VertexBufferAccessor vba(mFloor);
	for (int i = 0; i < vba.GetNumVertices(); ++i)
	{
		Float2& tcoord = vba.TCoord<Float2>(0, i);
		tcoord[0] *= 64.0f;
		tcoord[1] *= 256.0f;
	}

	std::string textureName = Environment::GetPathR("Grating.wmtf");
	Texture2D* texture = Texture2D::LoadWMTF(textureName);
	texture->GenerateMipmaps();
	mFloor->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture,
	                          Shader::SF_LINEAR_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT));

	mScene->AttachChild(mFloor);

	ComputeVisibleSet(mScene);
}
Beispiel #12
0
//----------------------------------------------------------------------------
void IntersectTriangleCylinder::TestIntersection ()
{
    Triangle3f triangle;
    triangle.V[0] =
        (const Vector3f&)(mTMesh->WorldTransform*mTriangleMVertex0);
    triangle.V[1] =
        (const Vector3f&)(mTMesh->WorldTransform*mTriangleMVertex1);
    triangle.V[2] =
        (const Vector3f&)(mTMesh->WorldTransform*mTriangleMVertex2);

    Cylinder3f cylinder;
    cylinder.Axis.Origin =
        (const Vector3f&)(mCMesh->WorldTransform*APoint::ORIGIN);
    cylinder.Axis.Direction =
        (const Vector3f&)(mCMesh->WorldTransform*AVector::UNIT_Z);
    cylinder.Radius = mCylinderRadius;
    cylinder.Height = mCylinderHeight;

    VertexBufferAccessor vba(mTMesh);
    if (IntrTriangle3Cylinder3f(triangle, cylinder).Test())
    {
        vba.Color<Float3>(0, 0) = Float3(0.0f, 1.0f, 0.0f);
        vba.Color<Float3>(0, 1) = Float3(0.0f, 1.0f, 0.0f);
        vba.Color<Float3>(0, 2) = Float3(0.0f, 1.0f, 0.0f);
    }
    else
    {
        vba.Color<Float3>(0, 0) = Float3(0.0f, 0.0f, 1.0f);
        vba.Color<Float3>(0, 1) = Float3(0.0f, 0.0f, 1.0f);
        vba.Color<Float3>(0, 2) = Float3(0.0f, 0.0f, 1.0f);
    }
    mRenderer->Update(mTMesh->GetVertexBuffer());
}
Beispiel #13
0
//----------------------------------------------------------------------------
void Fluids3D::UpdateVertexBuffer ()
{
    VertexBufferAccessor vba(mCube);
    const int bound0 = mSmoke->GetIMax() + 1;
    const int bound1 = mSmoke->GetJMax() + 1;
    const int bound2 = mSmoke->GetKMax() + 1;
    float*** density = mSmoke->GetDensity();

    for (int i2 = 0, index = 0; i2 < bound2; ++i2)
    {
        for (int i1 = 0; i1 < bound1; ++i1)
        {
            for (int i0 = 0; i0 < bound0; ++i0)
            {
                const float scaleDown = 0.5f;
                float value = density[i2][i1][i0];
                if (value > 1.0f)
                {
                    value = 1.0f;
                }

                Float4 color;
                if (mUseColor)
                {
                    Vector3f key = mColor[(int)(255.0f*value)];
                    color[0] = key[0];
                    color[1] = key[1];
                    color[2] = key[2];
                    color[3] = scaleDown*value;
                }
                else
                {
                    color[0] = scaleDown*value;
                    color[1] = color[0];
                    color[2] = color[0];
                    color[3] = color[0];
                }

                const float alphaThreshold = 0.01f;
                if (color[3] < alphaThreshold)
                {
                    color[3] = 0.0f;
                }

#ifdef USE_PARTICLES
                vba.Color<Float4>(0, index++) = color;
                vba.Color<Float4>(0, index++) = color;
                vba.Color<Float4>(0, index++) = color;
                vba.Color<Float4>(0, index++) = color;
#else
                vba.Color<Float4>(0, index++) = color;
#endif
            }
        }
    }

    mRenderer->Update(mCube->GetVertexBuffer());
}
Beispiel #14
0
//----------------------------------------------------------------------------
void Fluids3D::UpdateIndexBuffer ()
{
    VertexBufferAccessor vba(mCube);
    APoint camPos = mCamera->GetPosition();
    const int numTriangles = mNumIndices/3;
    int* currentIndex = mIndices;

    mTriangles.clear();
    for (int t = 0; t < numTriangles; ++t)
    {
        Triangle tri;
        tri.mIndex0 = *currentIndex++;
        tri.mIndex1 = *currentIndex++;
        tri.mIndex2 = *currentIndex++;

#ifdef USE_PARTICLES
        float alpha = vba.Color<Float4>(0, tri.mIndex0)[3];
        if (alpha == 0.0f)
        {
            continue;
        }
#else
        float alpha0 = vba.Color<Float4>(0, tri.mIndex0)[3];
        float alpha1 = vba.Color<Float4>(0, tri.mIndex1)[3];
        float alpha2 = vba.Color<Float4>(0, tri.mIndex2)[3];
        if (alpha0 == 0.0f && alpha1 == 0.0f && alpha2 == 0.0f)
        {
            continue;
        }
#endif

        Vector3f scaledCenter =
            vba.Position<Vector3f>(tri.mIndex0) +
            vba.Position<Vector3f>(tri.mIndex1) +
            vba.Position<Vector3f>(tri.mIndex2);

        APoint output = mCube->WorldTransform*APoint(scaledCenter);
        AVector diff = output - camPos;
        tri.mNegSqrDistance = -diff.SquaredLength();

        mTriangles.insert(tri);
    }

    IndexBuffer* ibuffer = mCube->GetIndexBuffer();
    int* indices = (int*)ibuffer->GetData();
    ibuffer->SetNumElements(3*(int)mTriangles.size());

    std::multiset<Triangle>::iterator iter = mTriangles.begin();
    std::multiset<Triangle>::iterator end = mTriangles.end();
    for (/**/; iter != end; ++iter)
    {
        *indices++ = iter->mIndex0;
        *indices++ = iter->mIndex1;
        *indices++ = iter->mIndex2;
    }

    mRenderer->Update(ibuffer);
}
//----------------------------------------------------------------------------
void PointInPolyhedron::CreateScene ()
{
    mScene = new0 Node();
    mWireState = new0 WireState();
    mRenderer->SetOverrideWireState(mWireState);

    // Create a semitransparent sphere mesh.
    VertexFormat* vformatMesh = VertexFormat::Create(1,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0);
    TriMesh* mesh = StandardMesh(vformatMesh).Sphere(16, 16, 1.0f);
    Material* material = new0 Material();
    material->Diffuse = Float4(1.0f, 0.0f, 0.0f, 0.25f);
    VisualEffectInstance* instance = MaterialEffect::CreateUniqueInstance(
        material);
    instance->GetEffect()->GetAlphaState(0, 0)->BlendEnabled = true;
    mesh->SetEffectInstance(instance);

    // Create the data structures for the polyhedron that represents the
    // sphere mesh.
    CreateQuery(mesh);

    // Create a set of random points.  Points inside the polyhedron are
    // colored white.  Points outside the polyhedron are colored blue.
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(1024, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);
    Float3 white(1.0f, 1.0f, 1.0f);
    Float3 blue(0.0f, 0.0f, 1.0f);
    for (int i = 0; i < vba.GetNumVertices(); ++i)
    {
        Vector3f random(Mathf::SymmetricRandom(),
            Mathf::SymmetricRandom(), Mathf::SymmetricRandom());

        vba.Position<Vector3f>(i) = random;

        if (mQuery->Contains(random))
        {
            vba.Color<Float3>(0, i) = white;
        }
        else
        {
            vba.Color<Float3>(0, i) = blue;
        }
    }

    DeleteQuery();

    mPoints = new0 Polypoint(vformat, vbuffer);
    mPoints->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());

    mScene->AttachChild(mPoints);
    mScene->AttachChild(mesh);
}
//----------------------------------------------------------------------------
void ClipMesh::Update ()
{
    // Transform the model-space vertices to world space.
    int numVertices = (int)mTorusVerticesMS.size();
    int i;
    for (i = 0; i < numVertices; ++i)
    {
        mTorusVerticesWS[i] = mTorus->LocalTransform*mTorusVerticesMS[i];
    }

    // Partition the torus mesh.
    std::vector<APoint> clipVertices;
    std::vector<int> negIndices, posIndices;
    PartitionMesh(mTorusVerticesWS, mTorusIndices, mPlane, clipVertices,
        negIndices, posIndices);

    // Replace the torus vertex buffer.
    numVertices = (int)clipVertices.size();
    int stride = mTorus->GetVertexFormat()->GetStride();
    VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, stride,
        Buffer::BU_STATIC);
    mTorus->SetVertexBuffer(vbuffer);
    VertexBufferAccessor vba(mTorus);
    Float3 black(0.0f, 0.0f, 0.0f);
    for (i = 0; i < numVertices; ++i)
    {
        // Transform the world-space vertex to model space.
        vba.Position<Float3>(i) =
            mTorus->LocalTransform.Inverse()*clipVertices[i];

        vba.Color<Float3>(0, i) = black;
    }

    // Modify the vertex color based on which mesh the vertices lie.
    int negQuantity = (int)negIndices.size();
    for (i = 0; i < negQuantity; ++i)
    {
        vba.Color<Float3>(0, negIndices[i])[2] = 1.0f;
    }
    int posQuantity = (int)posIndices.size();
    for (i = 0; i < posQuantity; ++i)
    {
        vba.Color<Float3>(0, posIndices[i])[0] = 1.0f;
    }

    // To display the triangles generated by the split.
    int numIndices = negQuantity + posQuantity;
    IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int));
    mTorus->SetIndexBuffer(ibuffer);
    int* indices = (int*)ibuffer->GetData();
    memcpy(indices, &negIndices[0], negQuantity*sizeof(int));
    memcpy(indices + negQuantity, &posIndices[0], posQuantity*sizeof(int));
}
//----------------------------------------------------------------------------
void FreeFormDeformation::UpdateMesh ()
{
    VertexBufferAccessor vba(mMesh);
    int numVertices = vba.GetNumVertices();
    for (int i = 0; i < numVertices; ++i)
    {
        const Vector3f& param = mParameters[i];
        Vector3f& position = vba.Position<Vector3f>(i);
        position = mVolume->GetPosition(param[0], param[1], param[2]);
    }
    mRenderer->Update(mMesh->GetVertexBuffer());
}
//----------------------------------------------------------------------------
void ClipMesh::CreateScene ()
{
    mScene = new0 Node();

    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);

    // The plane is fixed at z = 0.
    mPlane.SetNormal(AVector::UNIT_Z);
    mPlane.SetConstant(0.0f);
    mMeshPlane = StandardMesh(vformat).Rectangle(32, 32, 16.0f, 16.0f);
    VisualEffectInstance* instance =
        VertexColor3Effect::CreateUniqueInstance();
    instance->GetEffect()->GetWireState(0,0)->Enabled = true;
    mMeshPlane->SetEffectInstance(instance);
    mScene->AttachChild(mMeshPlane);

    VertexBufferAccessor vba(mMeshPlane);
    Float3 green(0.0f, 1.0f, 0.0f);
    int i;
    for (i = 0; i < vba.GetNumVertices(); ++i)
    {
        vba.Color<Float3>(0, i) = green;
    }

    // Get the positions and indices for a torus.
    mTorus = StandardMesh(vformat).Torus(64, 64, 4.0f, 1.0f);
    instance = VertexColor3Effect::CreateUniqueInstance();
    mTorusWireState = instance->GetEffect()->GetWireState(0, 0);
    mTorus->SetEffectInstance(instance);
    mScene->AttachChild(mTorus);

    vba.ApplyTo(mTorus);
    mTorusVerticesMS.resize(vba.GetNumVertices());
    mTorusVerticesWS.resize(vba.GetNumVertices());
    Float3 black(0.0f, 0.0f, 0.0f);
    for (i = 0; i < vba.GetNumVertices(); ++i)
    {
        mTorusVerticesMS[i] = vba.Position<Float3>(i);
        mTorusVerticesWS[i] = mTorusVerticesMS[i];
        vba.Color<Float3>(0, i) = black;
    }

    IndexBuffer* ibuffer = mTorus->GetIndexBuffer();
    int numIndices = ibuffer->GetNumElements();
    int* indices = (int*)ibuffer->GetData();
    mTorusIndices.resize(numIndices);
    memcpy(&mTorusIndices[0], indices, numIndices*sizeof(int));

    Update();
}
Beispiel #19
0
//----------------------------------------------------------------------------
Node* ExtremalQuery::CreateVisualConvexPolyhedron ()
{
    const Vector3f* vertices = mConvexPolyhedron->GetVertices();
    int numTriangles = mConvexPolyhedron->GetNumTriangles();
    int numIndices = 3*numTriangles;
    const int* polyIndices = mConvexPolyhedron->GetIndices();

    // Visualize the convex polyhedron as a collection of face-colored
    // triangles.
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(numIndices, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);

    IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int));
    int* indices = (int*)ibuffer->GetData();

    int i;
    for (i = 0; i < numIndices; ++i)
    {
        vba.Position<Vector3f>(i) = vertices[polyIndices[i]];
        indices[i] = i;
    }

    TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer);

    // Use randomly generated vertex colors.
    for (i = 0; i < numTriangles; ++i)
    {
        Float3 color;
        for (int j = 0; j < 3; ++j)
        {
            color[j] = Mathf::UnitRandom();
        }

        vba.Color<Float3>(0, 3*i  ) = color;
        vba.Color<Float3>(0, 3*i+1) = color;
        vba.Color<Float3>(0, 3*i+2) = color;
    }

    mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());

    Node* root = new0 Node();
    root->AttachChild(mesh);
    return root;
}
Beispiel #20
0
//----------------------------------------------------------------------------
void Delaunay3D::ChangeTetraStatus (int index, const Float4& color,
    bool enableWire)
{
    Visual* tetra = DynamicCast<Visual>(mScene->GetChild(1 + index));
    assertion(tetra != 0, "Expecting a Visual object.\n");
    VertexBufferAccessor vba(tetra);
    for (int i = 0; i < 4; ++i)
    {
        vba.Color<Float4>(0, i) = color;
    }
    mRenderer->Update(tetra->GetVertexBuffer());

    VisualEffectInstance* instance = tetra->GetEffectInstance();
    instance->GetEffect()->GetWireState(0, 0)->Enabled = enableWire;
}
//----------------------------------------------------------------------------
void FoucaultPendulum::PhysicsTick ()
{
    mModule.Update();

    // Update the pendulum mechanism.  The pendulum rod is attached at
    // (x,y,z) = (0,0,16).  The update here has the 16 hard-coded.
    mPendulum->LocalTransform.SetRotate(mModule.GetOrientation());
    mPendulum->Update();

    // Draw only the active quantity of pendulum points for the initial
    // portion of the simulation.  Once all points are activated, then all
    // are drawn.
    mPath->SetNumPoints(mPath->GetNumPoints() + 1);

    // Add the new pendulum point to the point system.  The initial color is
    // white.  All previously known points have their colors decremented to
    // cause them to become dim over time.
    APoint proj = mPendulum->WorldTransform*APoint(0.0f, 0.0f, -16.0f);
    proj[2] = 0.0f;

    VertexBufferAccessor vba(mPath);
    vba.Position<Float3>(mNextPoint) = proj;
    vba.Color<Float3>(0, mNextPoint) = Float3(1.0f, 1.0f, 1.0f);
    int i;
    for (i = 0; i < mNextPoint; ++i)
    {
        Float3& color = vba.Color<Float3>(0, i);
        color[0] -= mColorDiff;
        color[1] -= mColorDiff;
        color[2] -= mColorDiff;
    }
    for (i = mNextPoint+1; i < vba.GetNumVertices(); ++i)
    {
        Float3& color = vba.Color<Float3>(0, i);
        color[0] -= mColorDiff;
        color[1] -= mColorDiff;
        color[2] -= mColorDiff;
    }

    // Prepare for the next pendulum point.
    if (++mNextPoint == vba.GetNumVertices())
    {
        mNextPoint = 0;
    }

    mRenderer->Update(mPath->GetVertexBuffer());
}
//----------------------------------------------------------------------------
void CollisionsBoundTree::ResetColors ()
{
    VertexBufferAccessor vba(mCylinder0);
    int i;
    for (i = 0; i < vba.GetNumVertices(); ++i)
    {
        vba.TCoord<Float2>(0, i) = mBlueUV;
    }
    mRenderer->Update(mCylinder0->GetVertexBuffer());

    vba.ApplyTo(mCylinder1);
    for (i = 0; i < vba.GetNumVertices(); ++i)
    {
        vba.TCoord<Float2>(0, i) = mRedUV;
    }
    mRenderer->Update(mCylinder1->GetVertexBuffer());
}
Beispiel #23
0
//----------------------------------------------------------------------------
void IntersectTriangleCylinder::CreateScene ()
{
    mScene = new0 Node();
    mCullState = new0 CullState();
    mCullState->Enabled = false;
    mRenderer->SetOverrideCullState(mCullState);
    mWireState = new0 WireState();
    mRenderer->SetOverrideWireState(mWireState);

    VertexFormat* vformat = VertexFormat::Create(2,
                            VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
                            VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(3, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);
    vba.Position<Vector3f>(0) = (const Vector3f&)mTriangleMVertex0;
    vba.Color<Float3>(0, 0) = Float3(0.0f, 0.0f, 1.0f);
    vba.Position<Vector3f>(1) = (const Vector3f&)mTriangleMVertex1;
    vba.Color<Float3>(0, 1) = Float3(0.0f, 0.0f, 1.0f);
    vba.Position<Vector3f>(2) = (const Vector3f&)mTriangleMVertex2;
    vba.Color<Float3>(0, 2) = Float3(0.0f, 0.0f, 1.0f);

    IndexBuffer* ibuffer = new0 IndexBuffer(3, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[0] = 0;
    indices[1] = 1;
    indices[2] = 2;
    mTMesh = new0 TriMesh(vformat, vbuffer, ibuffer);
    mTMesh->SetEffectInstance(
        VertexColor3Effect::CreateUniqueInstance());
    mTMesh->LocalTransform.SetTranslate(APoint(0.0f, 1.125f, 0.0f));

    mCMesh = StandardMesh(vformat).Cylinder(8, 16, mCylinderRadius,
                                            mCylinderHeight, false);
    vba.ApplyTo(mCMesh);
    for (int i = 0; i < vba.GetNumVertices(); ++i)
    {
        vba.Color<Float3>(0, i) = Float3(1.0f, 0.0f, 0.0f);
    }
    mCMesh->SetEffectInstance(
        VertexColor3Effect::CreateUniqueInstance());

    mScene->AttachChild(mTMesh);
    mScene->AttachChild(mCMesh);
}
//----------------------------------------------------------------------------
TriMesh* PolyhedronDistance::CreateTetra (float size, bool isBlack)
{
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);

    vba.Position<Vector3f>(0) = -(size/3.0f)*Vector3f(1.0f, 1.0f, 1.0f);
    vba.Position<Vector3f>(1) = Vector3f(size, 0.0f, 0.0f);
    vba.Position<Vector3f>(2) = Vector3f(0.0f, size, 0.0f);
    vba.Position<Vector3f>(3) = Vector3f(0.0f, 0.0f, size);

    if (isBlack)
    {
        // Black tetrahedra for the small ones used as points.
        Float3 black(0.0f, 0.0f, 0.0f);
        vba.Color<Float3>(0, 0) = black;
        vba.Color<Float3>(0, 1) = black;
        vba.Color<Float3>(0, 2) = black;
        vba.Color<Float3>(0, 3) = black;
    }
    else
    {
        // Colorful colors for the tetrahedra under study.
        vba.Color<Float3>(0, 0) = Float3(0.0f, 0.0f, 1.0f);
        vba.Color<Float3>(0, 1) = Float3(0.0f, 1.0f, 0.0f);
        vba.Color<Float3>(0, 2) = Float3(1.0f, 0.0f, 0.0f);
        vba.Color<Float3>(0, 3) = Float3(1.0f, 1.0f, 1.0f);
    }

    IndexBuffer* ibuffer = new0 IndexBuffer(12, sizeof(int));
    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] = 3;
    indices[ 9] = 1; indices[10] = 2; indices[11] = 3;

    TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer);
    mesh->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());

    return mesh;
}
//----------------------------------------------------------------------------
TriMesh* RoughPlaneSolidBox::CreateRamp ()
{
    float x = 8.0f;
    float y = 8.0f;
    float z = y*Mathf::Tan((float)mModule.Angle);

    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(6, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);

    vba.Position<Float3>(0) = Float3(-x, 0.0f, 0.0f);
    vba.Position<Float3>(1) = Float3(+x, 0.0f, 0.0f);
    vba.Position<Float3>(2) = Float3(-x, y, 0.0f);
    vba.Position<Float3>(3) = Float3(+x, y, 0.0f);
    vba.Position<Float3>(4) = Float3(-x, y, z);
    vba.Position<Float3>(5) = Float3(+x, y, z);
    vba.TCoord<Float2>(0, 0) = Float2(0.25f, 0.0f);
    vba.TCoord<Float2>(0, 1) = Float2(0.75f, 0.0f);
    vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
    vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
    vba.TCoord<Float2>(0, 4) = Float2(0.25f, 1.0f);
    vba.TCoord<Float2>(0, 5) = Float2(0.75f, 1.0f);

    IndexBuffer* ibuffer = new0 IndexBuffer(18, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[ 0] = 0;  indices[ 1] = 1;  indices[ 2] = 4;
    indices[ 3] = 1;  indices[ 4] = 5;  indices[ 5] = 4;
    indices[ 6] = 0;  indices[ 7] = 4;  indices[ 8] = 2;
    indices[ 9] = 1;  indices[10] = 3;  indices[11] = 5;
    indices[12] = 3;  indices[13] = 2;  indices[14] = 4;
    indices[15] = 3;  indices[16] = 4;  indices[17] = 5;

    TriMesh* ramp = new0 TriMesh(vformat, vbuffer, ibuffer);

    std::string path = Environment::GetPathR("Metal.wmtf");
    Texture2D* texture = Texture2D::LoadWMTF(path);
    ramp->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture,
        Shader::SF_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT));

    return ramp;
}
Beispiel #26
0
//----------------------------------------------------------------------------
TriMesh* ConvexHull3D::CreateSphere ()
{
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);

    Float3 white(1.0f, 1.0f, 1.0f);
    float radius = 0.01f;
    TriMesh* sphere = StandardMesh(vformat).Sphere(8, 8, radius);
    VertexBufferAccessor vba(sphere);
    for (int i = 0; i < vba.GetNumVertices(); ++i)
    {
        vba.Color<Float3>(0, i) = white;
    }

    sphere->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());
    return sphere;
}
//----------------------------------------------------------------------------
Polysegment* PolyhedronDistance::CreateSegment ()
{
    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(2, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);

    vba.Position<Vector3f>(0) = Vector3f::ZERO;
    vba.Position<Vector3f>(1) = Vector3f::UNIT_X;
    vba.Color<Float3>(0, 0) = Float3(1.0f, 1.0f, 1.0f);
    vba.Color<Float3>(0, 1) = Float3(1.0f, 1.0f, 1.0f);

    Polysegment* segment = new0 Polysegment(vformat, vbuffer, true);
    segment->SetEffectInstance(VertexColor3Effect::CreateUniqueInstance());

    return segment;
}
Beispiel #28
0
//----------------------------------------------------------------------------
void RigidTetra::GetVertices (Vector3f* vertices) const
{
    // Do not move the boundaries.  The hard-coded numbers here depend on
    // those of the floor/walls in the application.
    Vector3f offset;
    if (0.0f < mPosition.X() && mPosition.X() < 20.0f)
    {
        offset = mPosition;
    }
    else
    {
        offset = Vector3f::ZERO;
    }

    // Move the tetra vertices.
    VertexBufferAccessor vba(mMesh);
    for (int i = 0; i < 4; ++i)
    {
        vertices[i] = mRotOrient*vba.Position<Vector3f>(i) + offset;
    }
}
Beispiel #29
0
//----------------------------------------------------------------------------
BspNode* BspNodes::CreateNode (const Vector2f& v0, const Vector2f& v1,
                               VertexColor3Effect* effect, const Float3& color)
{
	// Create the model-space separating plane.
	Vector2f dir = v1 - v0;
	AVector normal(dir[1], -dir[0], 0.0f);
	normal.Normalize();
	float constant = normal[0]*v0[0] + normal[1]*v0[1];
	HPlane modelPlane(normal, constant);

	// Create the BSP node.
	BspNode* bsp = new0 BspNode(modelPlane);

	VertexFormat* vformat = VertexFormat::Create(2,
	                        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
	                        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0);

	// Create the rectangle representation of the model plane and set the
	// vertex colors to the specified color.
	float xExtent = 0.5f*dir.Length();
	float yExtent = 0.125f;
	TriMesh* rect = StandardMesh(vformat).Rectangle(2, 2, xExtent, yExtent);
	VertexBufferAccessor vba(rect);
	for (int i = 0; i < 4; ++i)
	{
		vba.Color<Float3>(0, i) = color;
	}
	rect->SetEffectInstance(effect->CreateInstance());

	// Set the position and orientation for the world-space plane.
	APoint trn(0.5f*(v0[0] + v1[0]), 0.5f*(v0[1] + v1[1]), yExtent + 0.001f);
	HMatrix zRotate(AVector::UNIT_Z, Mathf::ATan2(dir.Y(),dir.X()));
	HMatrix xRotate(AVector::UNIT_X, Mathf::HALF_PI);
	HMatrix rotate = zRotate*xRotate;
	rect->LocalTransform.SetTranslate(trn);
	rect->LocalTransform.SetRotate(rotate);

	bsp->AttachCoplanarChild(rect);
	return bsp;
}
Beispiel #30
0
//----------------------------------------------------------------------------
TriMesh* Delaunay3D::CreateTetra (int index) const
{
    const Vector3f* dvertices = mDelaunay->GetVertices();
    const int* dindices = mDelaunay->GetIndices();

    VertexFormat* vformat = VertexFormat::Create(2,
        VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
        VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0);
    int vstride = vformat->GetStride();

    VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride);
    VertexBufferAccessor vba(vformat, vbuffer);
    vba.Position<Vector3f>(0) = dvertices[dindices[4*index    ]];
    vba.Position<Vector3f>(1) = dvertices[dindices[4*index + 1]];
    vba.Position<Vector3f>(2) = dvertices[dindices[4*index + 2]];
    vba.Position<Vector3f>(3) = dvertices[dindices[4*index + 3]];
    Float4 lightGray(0.75f, 0.75f, 0.75f, 1.0f);
    vba.Color<Float4>(0, 0) = lightGray;
    vba.Color<Float4>(0, 1) = lightGray;
    vba.Color<Float4>(0, 2) = lightGray;
    vba.Color<Float4>(0, 3) = lightGray;

    IndexBuffer* ibuffer = new0 IndexBuffer(12, sizeof(int));
    int* indices = (int*)ibuffer->GetData();
    indices[ 0] = 0;  indices[ 1] = 1;  indices[ 2] = 2;
    indices[ 3] = 0;  indices[ 4] = 3;  indices[ 5] = 1;
    indices[ 6] = 0;  indices[ 7] = 2;  indices[ 8] = 3;
    indices[ 9] = 3;  indices[10] = 2;  indices[11] = 1;

    TriMesh* tetra = new0 TriMesh(vformat, vbuffer, ibuffer);
    VisualEffectInstance* instance =
        VertexColor4Effect::CreateUniqueInstance();
    instance->GetEffect()->GetAlphaState(0, 0)->BlendEnabled = true;
    instance->GetEffect()->GetWireState(0, 0)->Enabled = true;
    tetra->SetEffectInstance(instance);

    return tetra;
}