예제 #1
0
void TexturingWindow::CreateScene()
{
    // Create a vertex buffer for a two-triangles square.  The PNG is stored
    // in left-handed coordinates.  The texture coordinates are chosen to
    // reflect the texture in the y-direction.
    struct Vertex
    {
        Vector3<float> position;
        Vector2<float> tcoord;
    };
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4));
    Vertex* vertex = vbuffer->Get<Vertex>();
    vertex[0].position = { 0.0f, 0.0f, 0.0f };
    vertex[0].tcoord = { 0.0f, 1.0f };
    vertex[1].position = { 1.0f, 0.0f, 0.0f };
    vertex[1].tcoord = { 1.0f, 1.0f };
    vertex[2].position = { 0.0f, 1.0f, 0.0f };
    vertex[2].tcoord = { 0.0f, 0.0f };
    vertex[3].position = { 1.0f, 1.0f, 0.0f };
    vertex[3].tcoord = { 1.0f, 0.0f };

    // Create an indexless buffer for a triangle mesh with two triangles.
    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2));

    // Create an effect for the vertex and pixel shaders.  The texture is
    // bilinearly filtered and the texture coordinates are clamped to [0,1]^2.
    std::shared_ptr<Texture2> myTexture(WICFileIO::Load(
        mEnvironment.GetPath("StoneWall.png"), false));
    std::shared_ptr<Texture2Effect> effect =
        std::make_shared<Texture2Effect>(mProgramFactory, myTexture,
        SamplerState::MIN_L_MAG_L_MIP_P, SamplerState::CLAMP,
        SamplerState::CLAMP);

    // Create the geometric object for drawing.  Translate it so that its
    // center of mass is at the origin.  This supports virtual trackball
    // motion about the object "center".
    mSquare = std::make_shared<Visual>(vbuffer, ibuffer, effect);
    mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f);

    // Enable automatic updates of pvw-matrices and w-matrices.
    mCameraRig.Subscribe(mSquare->worldTransform,
        effect->GetPVWMatrixConstant());

#if defined(SAVE_RENDERING_TO_DISK)
    mTarget = std::make_shared<DrawTarget>(1, DF_R8G8B8A8_UNORM, mXSize,
        mYSize);
    mTarget->GetRTTexture(0)->SetCopyType(Resource::COPY_STAGING_TO_CPU);
#endif

    mTrackball.Attach(mSquare);
    mTrackball.Update();
}
예제 #2
0
void BlendedAnimationsWindow::CreateScene()
{
    mWireState = std::make_shared<RasterizerState>();
    mWireState->fillMode = RasterizerState::FILL_WIREFRAME;

    mScene = std::make_shared<Node>();
    mScene->AttachChild(mManager->GetRoot());

    // Create a floor to walk on.
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_NORMAL, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);

    MeshFactory mf;
    mf.SetVertexFormat(vformat);
    mFloor = mf.CreateRectangle(2, 2, 1024.0f, 2048.0f);
    mFloor->name = "Floor";
    mScene->AttachChild(mFloor);
    std::shared_ptr<VertexBuffer> vbuffer = mFloor->GetVertexBuffer();
    vbuffer->SetUsage(Resource::DYNAMIC_UPDATE);
    unsigned int numVertices = vbuffer->GetNumElements();
    Vertex* vertex = vbuffer->Get<Vertex>();
    for (unsigned int i = 0; i < numVertices; ++i)
    {
        vertex[i].tcoord[0] *= 64.0f;
        vertex[i].tcoord[1] *= 256.0f;
    }

    std::string textureName = mEnvironment.GetPath("Grating.png");
    std::shared_ptr<Texture2> texture(WICFileIO::Load(textureName, true));
    texture->AutogenerateMipmaps();
    std::shared_ptr<Texture2Effect> effect = std::make_shared<Texture2Effect>(
        mProgramFactory, texture, SamplerState::MIN_L_MAG_L_MIP_L,
        SamplerState::WRAP, SamplerState::WRAP);
    mFloor->SetEffect(effect);

    mCameraRig.Subscribe(mFloor->worldTransform, effect->GetPVWMatrixConstant());
    for (auto const& subscriber : mManager->GetSubscribers())
    {
        mCameraRig.Subscribe(subscriber.first->worldTransform, subscriber.second);
    }

    GetMeshes(mScene);

    mTrackball.Attach(mScene);
    mTrackball.Update(mApplicationTime);
}
예제 #3
0
bool Fluids3DWindow::CreateNestedBoxes()
{
    std::string path = mEnvironment.GetPath("VolumeRender.hlsl");
    std::shared_ptr<VisualProgram> program =
        mProgramFactory.CreateFromFiles(path, path, "");
    if (!program)
    {
        return false;
    }

    mPVWMatrixBuffer = std::make_shared<ConstantBuffer>(
        sizeof(Matrix4x4<float>), true);
    *mPVWMatrixBuffer->Get<Matrix4x4<float>>() = Matrix4x4<float>::Identity();

    mTrilinearClampSampler = std::make_shared<SamplerState>();
    mTrilinearClampSampler->filter = SamplerState::MIN_L_MAG_L_MIP_P;
    mTrilinearClampSampler->mode[0] = SamplerState::CLAMP;
    mTrilinearClampSampler->mode[1] = SamplerState::CLAMP;
    mTrilinearClampSampler->mode[2] = SamplerState::CLAMP;

    program->GetVShader()->Set("PVWMatrix", mPVWMatrixBuffer);
    program->GetPShader()->Set("volumeTexture", mFluid.GetState());
    program->GetPShader()->Set("trilinearClampSampler",
        mTrilinearClampSampler);

    std::shared_ptr<VisualEffect> effect =
        std::make_shared<VisualEffect>(program);

    struct Vertex { Vector3<float> position, tcoord; };
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32B32_FLOAT, 0);

    MeshFactory mf;
    mf.SetVertexFormat(vformat);
    int const numBoxes = 128;
    for (int i = 1; i <= numBoxes; ++i)
    {
        float extent = 0.5f*i/(numBoxes - 1.0f);
        std::shared_ptr<Visual> visual(mf.CreateBox(extent, extent, extent));
        VertexBuffer* vbuffer = visual->GetVertexBuffer().get();
        Vertex* vertex = vbuffer->Get<Vertex>();
        for (unsigned int j = 0; j < vbuffer->GetNumElements(); ++j, ++vertex)
        {
            Vector3<float>& tcd = vertex->tcoord;
            Vector3<float> pos = vertex->position;
            Vector4<float> tmp{ pos[0] + 0.5f, pos[1] + 0.5f, pos[2] + 0.5f,
                0.0f };
            for (int k = 0; k < 3; ++k)
            {
                tcd[k] = 0.5f*(tmp[k] + 1.0f);
            }
        }

        visual->SetEffect(effect);
        mVisible.push_back(visual);
    }

    return true;
}
예제 #4
0
void Delaunay3DWindow::CreateTetra(int index)
{
    std::vector<int> const& dindices = mDelaunay.GetIndices();

    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0);

    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat,
        static_cast<unsigned int>(mVertices.size())));
    vbuffer->SetUsage(Resource::DYNAMIC_UPDATE);
    Vertex* vertex = vbuffer->Get<Vertex>();
    for (int j = 0; j < 4; ++j)
    {
        vertex[j].position = mVertices[dindices[4 * index + j]];
        vertex[j].color = mLightGray;
    }

    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRIMESH, 4,
        sizeof(unsigned int)));
    unsigned int* indices = ibuffer->Get<unsigned int>();
    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;

    mWireTetra[index] = std::make_shared<Visual>(vbuffer, ibuffer,
        mVCEffect);
    mScene->AttachChild(mWireTetra[index]);
}
예제 #5
0
//----------------------------------------------------------------------------
void PerformanceAMDWindow::CreateScene()
{
    struct Vertex
    {
        Vector3<float> position;
        Vector2<float> tcoord;
    };
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);
    unsigned int const numTriangles = 1024;
    unsigned int const numVertices = 3 * numTriangles;
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat,
        numVertices));

    // Randomly generate positions and texture coordinates.
    std::mt19937 mte;
    std::uniform_real_distribution<float> unirnd(0.0f, 1.0f);
    std::uniform_real_distribution<float> symrnd(-1.0f, 1.0f);
    Vertex* vertex = vbuffer->Get<Vertex>();
    for (unsigned int i = 0; i < numVertices; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            vertex[i].position[j] = symrnd(mte);
        }
        for (int j = 0; j < 2; ++j)
        {
            vertex[i].tcoord[j] = unirnd(mte);
        }
    }

    // The vertices are not indexed.  Each consecutive triple is a triangle.
    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRIMESH,
        numTriangles));

    // Use a standard texture effect.
    std::shared_ptr<Texture2Effect> effect(new Texture2Effect(
        mProgramFactory, mBlurredTexture, SamplerState::MIN_L_MAG_L_MIP_P,
        SamplerState::CLAMP, SamplerState::CLAMP));
    mPVWMatrix = effect->GetPVWMatrixConstant();

    mTriangles.reset(new Visual(vbuffer, ibuffer, effect));
    SubscribeCW(mTriangles, mPVWMatrix);

    EnableObjectMotion();
}
void MinimumVolumeSphere3DWindow::CreateScene()
{
    // Create the points.
    std::mt19937 mte;
    std::uniform_real_distribution<float> rnd(-1.0f, 1.0f);
    for (auto& v : mVertices)
    {
        v = { rnd(mte), rnd(mte), rnd(mte) };
    }

    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);

    MeshFactory mf;
    mf.SetVertexFormat(vformat);

    std::shared_ptr<ConstantColorEffect> effect;
    for (int i = 0; i < NUM_POINTS; ++i)
    {
        mPoints[i] = mf.CreateSphere(6, 6, 0.01f);
        effect = std::make_shared<ConstantColorEffect>(mProgramFactory,
            Vector4<float>({ 0.5f, 0.5f, 0.5f, 1.0f }));
        mPoints[i]->SetEffect(effect);
        mCameraRig.Subscribe(mPoints[i]->worldTransform,
            effect->GetPVWMatrixConstant());

        std::shared_ptr<VertexBuffer> vbuffer = mPoints[i]->GetVertexBuffer();
        Vector3<float>* vertex = vbuffer->Get<Vector3<float>>();
        Vector3<float> offset = mVertices[i];
        for (unsigned int j = 0; j < vbuffer->GetNumElements(); ++j)
        {
            vertex[j] += offset;
        }
    }

    // Create the segments.
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 12));
    vbuffer->SetUsage(Resource::DYNAMIC_UPDATE);
    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(
        IP_POLYSEGMENT_DISJOINT, 6));
    effect = std::make_shared<ConstantColorEffect>(mProgramFactory,
        Vector4<float>({ 0.5f, 0.0f, 0.0f, 1.0f }));
    mSegments = std::make_shared<Visual>(vbuffer, ibuffer, effect);
    mCameraRig.Subscribe(mSegments->worldTransform,
        effect->GetPVWMatrixConstant());
    mSegments->Update();

    // Create the sphere.
    mSphere = mf.CreateSphere(16, 16, 1.0f);

    effect = std::make_shared<ConstantColorEffect>(mProgramFactory,
        Vector4<float>({ 0.0f, 0.0f, 0.5f, 1.0f }));

    mSphere->SetEffect(effect);
    mCameraRig.Subscribe(mSphere->worldTransform,
        effect->GetPVWMatrixConstant());
}
예제 #7
0
void Delaunay3DWindow::CreateSphere()
{
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_COLOR, DF_R32G32B32_FLOAT, 0);

    MeshFactory mf;
    mf.SetVertexFormat(vformat);

    mSphere = mf.CreateSphere(8, 8, 0.025f);
    std::shared_ptr<VertexColorEffect> effect =
        std::make_shared<VertexColorEffect>(mProgramFactory);
    mSphere->SetEffect(effect);

    // Move the sphere offscreen initially.
    mSphere->localTransform.SetTranslation(0.0f, 0.0f, -1000.0f);
    mSphere->Update();
    mCameraRig.Subscribe(mSphere->worldTransform,
        effect->GetPVWMatrixConstant());
    mScene->AttachChild(mSphere);
}
예제 #8
0
//----------------------------------------------------------------------------
bool WireMeshWindow::CreateScene()
{
    std::string path = mEnvironment.GetPath("WireMesh.hlsl");
    std::shared_ptr<VertexShader> vshader(ShaderFactory::CreateVertex(path));
    if (!vshader)
    {
        return false;
    }

    std::shared_ptr<GeometryShader> gshader(ShaderFactory::CreateGeometry(
        path));
    if (!gshader)
    {
        return false;
    }

    std::shared_ptr<PixelShader> pshader(ShaderFactory::CreatePixel(path));
    if (!pshader)
    {
        return false;
    }

    std::shared_ptr<ConstantBuffer> parameters(
        new ConstantBuffer(3 * sizeof(Vector4<float>), false));
    Vector4<float>* data = parameters->Get<Vector4<float>>();
    data[0] = Vector4<float>(0.0f, 0.0f, 1.0f, 1.0f);  // mesh color
    data[1] = Vector4<float>(0.0f, 0.0f, 0.0f, 1.0f);  // edge color
    data[2] = Vector4<float>((float)mXSize, (float)mYSize, 0.0f, 0.0f);
    vshader->Set("WireParameters", parameters);
    gshader->Set("WireParameters", parameters);
    pshader->Set("WireParameters", parameters);

    std::shared_ptr<ConstantBuffer> cbuffer(
        new ConstantBuffer(sizeof(Matrix4x4<float>), true));
    vshader->Set("PVWMatrix", cbuffer);

    std::shared_ptr<VisualEffect> effect(new VisualEffect(vshader, pshader,
        gshader));

    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    MeshFactory mf;
    mf.SetVertexFormat(vformat);
    mMesh = mf.CreateSphere(16, 16, 1.0f);
    mMesh->SetEffect(effect);
    mMesh->Update();

    SubscribeCW(mMesh, cbuffer);
    return true;
}
예제 #9
0
void OverlayEffect::Initialize(int windowWidth, int windowHeight,
    int textureWidth, int textureHeight)
{
    if (windowWidth <= 0 || windowHeight <= 0
    ||  textureWidth <= 0 || textureHeight <= 0)
    {
        LogError("Invalid input rectangle.");

        // Use dummy sizes.
        windowWidth = 1;
        windowHeight = 1;
        textureWidth = 1;
        textureHeight = 1;
    }

    mInvTextureWidth = 1.0f/static_cast<float>(textureWidth);
    mInvTextureHeight = 1.0f/static_cast<float>(textureHeight);

    mOverlayRectangle[0] = 0;
    mOverlayRectangle[1] = 0;
    mOverlayRectangle[2] = windowWidth;
    mOverlayRectangle[3] = windowHeight;

    mTextureRectangle[0] = 0;
    mTextureRectangle[1] = 0;
    mTextureRectangle[2] = textureWidth;
    mTextureRectangle[3] = textureHeight;

    // Create the vertex buffer.
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);
    mVBuffer = std::make_shared<VertexBuffer>(vformat, 4);
    mVBuffer->SetUsage(Resource::DYNAMIC_UPDATE);
    UpdateVertexBuffer();

    // Create the index buffer.
    mIBuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, 2,
        sizeof(unsigned int));
    unsigned int* indices = mIBuffer->Get<unsigned int>();
    indices[0] = 0;  indices[1] = 2;  indices[2] = 3;
    indices[3] = 0;  indices[4] = 3;  indices[5] = 1;
}
//----------------------------------------------------------------------------
bool PlaneMeshIntersectionWindow::CreateScene()
{
    std::string path = mEnvironment.GetPath("PlaneMeshIntersection.hlsl");
    std::shared_ptr<VertexShader> vshader(ShaderFactory::CreateVertex(path));
    if (!vshader)
    {
        return false;
    }

    std::shared_ptr<PixelShader> pshader(ShaderFactory::CreatePixel(path));
    if (!pshader)
    {
        return false;
    }

    path = mEnvironment.GetPath("DrawIntersections.hlsl");
    mDrawIntersections.reset(ShaderFactory::CreateCompute(path));

    float planeDelta = 0.125f;
    mPMIParameters.reset(new ConstantBuffer(sizeof(PMIParameters), true));
    PMIParameters& p = *mPMIParameters->Get<PMIParameters>();
    p.pvMatrix = mCamera.GetProjectionViewMatrix();
    p.wMatrix = Matrix4x4<float>::Identity();
    p.planeVector0 = Vector4<float>(1.0f, 0.0f, 0.0f, 0.0f) / planeDelta;
    p.planeVector1 = Vector4<float>(0.0f, 1.0f, 0.0f, 0.0f) / planeDelta;
    vshader->Set("PMIParameters", mPMIParameters);

    std::shared_ptr<VisualEffect> effect(new VisualEffect(vshader, pshader));

    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    MeshFactory mf;
    mf.SetVertexFormat(vformat);
    mMesh = mf.CreateSphere(16, 16, 1.0f);
    mMesh->SetEffect(effect);
    mMesh->Update();
    return true;
}
//----------------------------------------------------------------------------
bool StructuredBuffersWindow::CreateScene()
{
    // Create the shaders and associated resources
    HLSLDefiner definer;
    definer.SetInt("WINDOW_WIDTH", mXSize);
    std::shared_ptr<VertexShader> vshader(ShaderFactory::CreateVertex(
        mEnvironment.GetPath("StructuredBuffers.hlsl"), definer));
    if (!vshader)
    {
        return false;
    }

    std::shared_ptr<PixelShader> pshader(ShaderFactory::CreatePixel(
        mEnvironment.GetPath("StructuredBuffers.hlsl"), definer));
    if (!pshader)
    {
        return false;
    }

    std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer(
        sizeof(Matrix4x4<float>), true));
    vshader->Set("PVWMatrix", cbuffer);

    // Create the pixel shader and associated resources.
    std::string path = mEnvironment.GetPath("StoneWall.png");
    std::shared_ptr<Texture2> baseTexture(WICFileIO::Load(path, false));
    pshader->Set("baseTexture", baseTexture);

    std::shared_ptr<SamplerState> baseSampler(new SamplerState());
    baseSampler->filter = SamplerState::MIN_L_MAG_L_MIP_P;
    baseSampler->mode[0] = SamplerState::CLAMP;
    baseSampler->mode[1] = SamplerState::CLAMP;
    pshader->Set("baseSampler", baseSampler);

    mDrawnPixels.reset(new StructuredBuffer(mXSize*mYSize,
        sizeof(Vector4<float>)));
    mDrawnPixels->SetUsage(Resource::SHADER_OUTPUT);
    mDrawnPixels->SetCopyType(Resource::COPY_BIDIRECTIONAL);
    memset(mDrawnPixels->GetData(), 0, mDrawnPixels->GetNumBytes());
    pshader->Set("drawnPixels", mDrawnPixels);

    // Create the visual effect for the square.
    std::shared_ptr<VisualEffect> effect(new VisualEffect(vshader, pshader));

    // Create a vertex buffer for a single triangle.  The PNG is stored in
    // left-handed coordinates.  The texture coordinates are chosen to reflect
    // the texture in the y-direction.
    struct Vertex
    {
        Vector3<float> position;
        Vector2<float> tcoord;
    };
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4));
    Vertex* vertex = vbuffer->Get<Vertex>();
    vertex[0].position = Vector3<float>(0.0f, 0.0f, 0.0f);
    vertex[0].tcoord = Vector2<float>(0.0f, 1.0f);
    vertex[1].position = Vector3<float>(1.0f, 0.0f, 0.0f);
    vertex[1].tcoord = Vector2<float>(1.0f, 1.0f);
    vertex[2].position = Vector3<float>(0.0f, 1.0f, 0.0f);
    vertex[2].tcoord = Vector2<float>(0.0f, 0.0f);
    vertex[3].position = Vector3<float>(1.0f, 1.0f, 0.0f);
    vertex[3].tcoord = Vector2<float>(1.0f, 0.0f);

    // Create an indexless buffer for a triangle mesh with two triangles.
    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2));

    // Create the geometric object for drawing.  Translate it so that its
    // center of mass is at the origin.  This supports virtual trackball
    // motion about the object "center".
    mSquare.reset(new Visual(vbuffer, ibuffer, effect));
    mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f);
    mSquare->Update();

    // Enable automatic updates of pvw-matrices and w-matrices.
    SubscribeCW(mSquare, cbuffer);

    // The structured buffer is written in the pixel shader.  This texture
    // will receive a copy of it so that we can write the results to disk
    // as a PNG file.
    mDrawnPixelsTexture = new Texture2(DF_R8G8B8A8_UNORM, mXSize, mYSize);
    return true;
}
예제 #12
0
bool TextureArraysWindow::CreateScene()
{
    // Create the shaders and associated resources.
    std::string filename = mEnvironment.GetPath("TextureArrays.hlsl");
    std::shared_ptr<VisualProgram> program =
        mProgramFactory.CreateFromFiles(filename, filename, "");
    if (!program)
    {
        return false;
    }

    // Create a vertex buffer for a single triangle.  The PNG is stored in
    // left-handed coordinates.  The texture coordinates are chosen to reflect
    // the texture in the y-direction.
    struct Vertex
    {
        Vector3<float> position;
        Vector2<float> tcoord;
    };
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4));
    Vertex* vertex = vbuffer->Get<Vertex>();
    vertex[0].position = { 0.0f, 0.0f, 0.0f };
    vertex[0].tcoord = { 0.0f, 1.0f };
    vertex[1].position = { 1.0f, 0.0f, 0.0f };
    vertex[1].tcoord = { 1.0f, 1.0f };
    vertex[2].position = { 0.0f, 1.0f, 0.0f };
    vertex[2].tcoord = { 0.0f, 0.0f };
    vertex[3].position = { 1.0f, 1.0f, 0.0f };
    vertex[3].tcoord = { 1.0f, 0.0f };

    // Create an indexless buffer for a triangle mesh with two triangles.
    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2));

    // Create an effect for the vertex and pixel shaders.  The texture is
    // bilinearly filtered and the texture coordinates are clamped to [0,1]^2.
    std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer(
        sizeof(Matrix4x4<float>), true));
    program->GetVShader()->Set("PVWMatrix", cbuffer);

    std::shared_ptr<PixelShader> pshader = program->GetPShader();
    std::shared_ptr<Texture1Array> t1array(new Texture1Array(2,
        DF_R8G8B8A8_UNORM, 2));
    unsigned int* t1data = t1array->Get<unsigned int>();
    t1data[0] = 0xFF000000;
    t1data[1] = 0xFFFFFFFF;
    pshader->Set("myTexture1", t1array);

    Texture2* stoneTexture = WICFileIO::Load(
        mEnvironment.GetPath("StoneWall.png"), false);
    std::shared_ptr<Texture2Array> t2array(new Texture2Array(2,
        DF_R8G8B8A8_UNORM, 256, 256));
    unsigned char* t2data = t2array->Get<unsigned char>();
    size_t const numBytes = stoneTexture->GetNumBytes();
    Memcpy(t2data, stoneTexture->GetData(), numBytes);
    t2data += numBytes;
    delete stoneTexture;
    for (size_t i = 0; i < numBytes; ++i)
    {
        *t2data++ = static_cast<unsigned char>(rand() % 256);
    }
    pshader->Set("myTexture2", t2array);

    std::shared_ptr<SamplerState> samplerState(new SamplerState());
    samplerState->filter = SamplerState::MIN_L_MAG_L_MIP_P;
    samplerState->mode[0] = SamplerState::CLAMP;
    samplerState->mode[1] = SamplerState::CLAMP;
    pshader->Set("mySampler", samplerState);

    std::shared_ptr<VisualEffect> effect =
        std::make_shared<VisualEffect>(program);

    // Create the geometric object for drawing.  Translate it so that its
    // center of mass is at the origin.  This supports virtual trackball
    // motion about the object "center".
    mSquare = std::make_shared<Visual>(vbuffer, ibuffer, effect);
    mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f);

    // Enable automatic updates of pvw-matrices and w-matrices.
    mCameraRig.Subscribe(mSquare->worldTransform, cbuffer);

    mTrackball.Attach(mSquare);
    mTrackball.Update();
    return true;
}
bool MultipleRenderTargetsWindow::CreateScene()
{
    // Create a visual effect that populates the draw target.
    std::string filename = mEnvironment.GetPath("MultipleRenderTargets.hlsl");
    std::shared_ptr<VisualProgram> program =
        mProgramFactory.CreateFromFiles(filename, filename, "");
    if (!program)
    {
        return false;
    }

    std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer(
        sizeof(Matrix4x4<float>), true));
    program->GetVShader()->Set("PVWMatrix", cbuffer);

    std::shared_ptr<PixelShader> pshader = program->GetPShader();
    std::shared_ptr<ConstantBuffer> farNearRatio(new ConstantBuffer(
        sizeof(float), false));
    pshader->Set("FarNearRatio", farNearRatio);
    farNearRatio->SetMember("farNearRatio",
        mCamera->GetDMax() / mCamera->GetDMin());

    std::string path = mEnvironment.GetPath("StoneWall.png");
    std::shared_ptr<Texture2> baseTexture(WICFileIO::Load(path, true));
    baseTexture->AutogenerateMipmaps();
    pshader->Set("baseTexture", baseTexture);

    std::shared_ptr<SamplerState> baseSampler(new SamplerState());
    baseSampler->filter = SamplerState::MIN_L_MAG_L_MIP_L;
    baseSampler->mode[0] = SamplerState::CLAMP;
    baseSampler->mode[1] = SamplerState::CLAMP;
    pshader->Set("baseSampler", baseSampler);

    std::shared_ptr<VisualEffect> effect =
        std::make_shared<VisualEffect>(program);

    // Create a vertex buffer for a two-triangle square.  The PNG is stored
    // in left-handed coordinates.  The texture coordinates are chosen to
    // reflect the texture in the y-direction.
    struct Vertex
    {
        Vector3<float> position;
        Vector2<float> tcoord;
    };
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4));
    Vertex* vertex = vbuffer->Get<Vertex>();
    vertex[0].position = { -1.0f, -1.0f, 0.0f };
    vertex[0].tcoord = { 0.0f, 1.0f };
    vertex[1].position = { 1.0f, -1.0f, 0.0f };
    vertex[1].tcoord = { 1.0f, 1.0f };
    vertex[2].position = { -1.0f, 1.0f, 0.0f };
    vertex[2].tcoord = { 0.0f, 0.0f };
    vertex[3].position = { 1.0f, 1.0f, 0.0f };
    vertex[3].tcoord = { 1.0f, 0.0f };

    // Create an indexless buffer for a triangle mesh with two triangles.
    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2));

    // Create the geometric object for drawing and enable automatic updates
    // of pvw-matrices and w-matrices.
    mSquare = std::make_shared<Visual>(vbuffer, ibuffer, effect);
    mTrackball.Attach(mSquare);
    mTrackball.Update();
    mCameraRig.Subscribe(mSquare->worldTransform, cbuffer);
    return true;
}
예제 #14
0
bool GeometryShadersWindow::CreateScene()
{
    std::string filename;
#if defined(USE_DRAW_DIRECT)
    filename = mEnvironment.GetPath("RandomSquares.hlsl");
#else
    filename = mEnvironment.GetPath("RandomSquaresIndirect.hlsl");
#endif
    std::shared_ptr<VisualProgram> program =
        mProgramFactory.CreateFromFiles(filename, filename, filename);
    if (!program)
    {
        return false;
    }

    // Create particles used by direct and indirect drawing.
    struct Vertex
    {
        Vector3<float> position;
        Vector3<float> color;
        float size;
    };

    // Use a Mersenne twister engine for random numbers.
    std::mt19937 mte;
    std::uniform_real_distribution<float> symr(-1.0f, 1.0f);
    std::uniform_real_distribution<float> unir(0.0f, 1.0f);
    std::uniform_real_distribution<float> posr(0.01f, 0.1f);

    int const numParticles = 128;
    std::vector<Vertex> particles(numParticles);
    for (auto& particle : particles)
    {
        particle.position = { symr(mte), symr(mte), symr(mte) };
        particle.color = { unir(mte), unir(mte), unir(mte) };
        particle.size = posr(mte);
    }

    // Create the constant buffer used by direct and indirect drawing.
    mMatrices = std::make_shared<ConstantBuffer>(
        2 * sizeof(Matrix4x4<float>), true);
    program->GetGShader()->Set("Matrices", mMatrices);

#if defined(USE_DRAW_DIRECT)
    // Create a mesh for direct drawing.
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_COLOR, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32_FLOAT, 0);
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat,
        numParticles));
    Memcpy(vbuffer->GetData(), &particles[0], numParticles*sizeof(Vertex));
#else
    // Create a mesh for indirect drawing.
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(numParticles));
    mParticles = std::make_shared<StructuredBuffer>(numParticles,
        sizeof(Vertex));
    Memcpy(mParticles->GetData(), &particles[0], numParticles*sizeof(Vertex));
    gshader->Set("particles", mParticles);
#endif

    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_POLYPOINT,
        numParticles));

    std::shared_ptr<VisualEffect> effect =
        std::make_shared<VisualEffect>(program);

    mMesh = std::make_shared<Visual>(vbuffer, ibuffer, effect);
    return true;
}
예제 #15
0
void MinimumVolumeBox3DWindow::CreateScene()
{
    mScene = std::make_shared<Node>();

    std::mt19937 mte;
    std::uniform_real_distribution<float> rnd(-1.0f, 1.0f);
    Vector3<float> center{ 0.0f, 0.0f, 0.0f };
    Vector3<float> extent{ 1.0f, 0.25f, 0.125f };
    Vector3<float> axis[3] = {
        { 1.0f, 1.0f, 0.0f },
        { -1.0f, 1.0f, 0.0f },
        { 0.0f, 0.0f, 1.0f }
    };
    Normalize(axis[0]);
    Normalize(axis[1]);
    Normalize(axis[2]);
    for (auto& v : mVertices)
    {
        float theta = rnd(mte) * (float)GTE_C_TWO_PI;
        float phi = rnd(mte) * (float)GTE_C_PI;
        float radius = 0.5f * (rnd(mte) + 1.0f);
        float x = extent[0] * cos(theta) * sin(phi);
        float y = extent[1] * sin(theta) * sin(phi);
        float z = extent[2] * cos(phi);
        v = center + radius * (x * axis[0] + y * axis[1] + z * axis[2]);
    }

    struct Vertex
    {
        Vector3<float> position;
        Vector4<float> color;
    };
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0);
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat,
        NUM_POINTS));
    Vertex* vertex = vbuffer->Get<Vertex>();
    for (int i = 0; i < NUM_POINTS; ++i)
    {
        vertex[i].position[0] = (float)mVertices[i][0];
        vertex[i].position[1] = (float)mVertices[i][1];
        vertex[i].position[2] = (float)mVertices[i][2];
        vertex[i].color[0] = 0.5f * (rnd(mte) + 1.0f);
        vertex[i].color[1] = 0.5f * (rnd(mte) + 1.0f);
        vertex[i].color[2] = 0.5f * (rnd(mte) + 1.0f);
        vertex[i].color[3] = 1.0f;
    }

    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_POLYPOINT,
        NUM_POINTS));

    std::shared_ptr<VertexColorEffect> effect =
        std::make_shared<VertexColorEffect>(mProgramFactory);

    mPoints = std::make_shared<Visual>(vbuffer, ibuffer, effect);
    mCameraRig.Subscribe(mPoints->worldTransform,
        effect->GetPVWMatrixConstant());
    mScene->AttachChild(mPoints);

    // Choose the number of threads to use.  The default constructor for
    // MinimumVolumeBox3 uses a default of 1, in which case all computations
    // are on the main thread.  The timings below are for a 64-bit release
    // build (no debugger attached) on Intel Core i7-3930K CPUs running at
    // 3.20 GHz.
    unsigned int numThreads = 1;

#if 0
    // Compute the convex hull internally using arbitrary precision
    // arithmetic.  This is slower than computing the hull explicitly using
    // the maximum fixed precision; see the other conditional block of code.
    Timer timer;
    typedef BSRational<UIntegerAP32> MVBRational;
    MinimumVolumeBox3<float, MVBRational> mvb3(numThreads);
    OrientedBox3<float> minBox = mvb3(NUM_POINTS, &mVertices[0]);
    std::cout << "mvb3 seconds = " << timer.GetSeconds() << std::endl;
    // numThreads = 1, seconds = 7.09
    // numThreads = 2, seconds = 6.22
#else
    // If mVertices were to use 'double', you would need the template type
    // UIntegerFP32<167> to compute the convex hull.
    Timer timer;
    typedef BSNumber<UIntegerFP32<27>> CHRational;
    ConvexHull3<float, CHRational> ch3(numThreads);
    ch3(NUM_POINTS, &mVertices[0], 0.0f);
    std::vector<TriangleKey<true>> const& triangles = ch3.GetHullUnordered();
    int const numIndices = static_cast<int>(3 * triangles.size());
    int const* indices = static_cast<int const*>(&triangles[0].V[0]);
    typedef BSRational<UIntegerAP32> MVBRational;
    MinimumVolumeBox3<float, MVBRational> mvb3(numThreads);
    OrientedBox3<float> minBox = mvb3(NUM_POINTS, &mVertices[0], numIndices,
        indices);
    std::cout << "mvb3 seconds = " << timer.GetSeconds() << std::endl;
    // numThreads = 1, seconds = 2.69
    // numThreads = 2, seconds = 2.01
#endif

    std::vector<int> const& hull = mvb3.GetHull();
    ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH,
        static_cast<int>(hull.size() / 3), sizeof(int));
    Memcpy(ibuffer->GetData(), &hull[0], ibuffer->GetNumBytes());
    mPolytope = std::make_shared<Visual>(vbuffer, ibuffer, effect);
    mScene->AttachChild(mPolytope);

    MeshFactory mf;
    mf.SetVertexFormat(vformat);
    mBoxMesh = mf.CreateBox(1.0f, 1.0f, 1.0f);
    vbuffer = mBoxMesh->GetVertexBuffer();
    vertex = vbuffer->Get<Vertex>();
    std::array<Vector3<float>, 8> corner;
    minBox.GetVertices(corner);
    for (int i = 0; i < 8; ++i)
    {
        vertex[i].position[0] = corner[i][0];
        vertex[i].position[1] = corner[i][1];
        vertex[i].position[2] = corner[i][2];
        vertex[i].color[0] = 0.5f * (rnd(mte) + 1.0f);
        vertex[i].color[1] = 0.5f * (rnd(mte) + 1.0f);
        vertex[i].color[2] = 0.5f * (rnd(mte) + 1.0f);
        vertex[i].color[3] = 1.0f;
    }
    mBoxMesh->SetEffect(effect);
    mScene->AttachChild(mBoxMesh);

    mTrackball.Attach(mScene);
    mTrackball.Update();
}
예제 #16
0
BipedManager::BipedManager(std::string const& rootPath,
    std::string const& bname, ProgramFactory& programFactory,
    SkinController::Updater const& postUpdate)
{
    // Vertex format shared by the two skins.
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_NORMAL, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);

    // Create the texture effects for the two skins.
    std::shared_ptr<Texture2> texture[2];
    std::shared_ptr<Texture2Effect> effect[2];
    for (int i = 0; i < 2; ++i)
    {
        std::string name = rootPath + "Skins/Skins" + std::to_string(i) + ".texture.png";
        texture[i].reset(WICFileIO::Load(name, true));
        texture[i]->AutogenerateMipmaps();
        effect[i] = std::make_shared<Texture2Effect>(programFactory,
            texture[i], SamplerState::MIN_L_MAG_L_MIP_L, SamplerState::WRAP,
            SamplerState::WRAP);
    }

    PreSpatialArray preSpatialArray;
    PreSkinArray preSkinArray;
    SpatialMap spatialMap;

    std::string filename = rootPath + bname + ".txt";
    std::ifstream inFile(filename);
    while (!inFile.eof())
    {
        std::string line;
        getline(inFile, line);
        if (line == "")
        {
            // The file contains no blank lines, except for the very last one.
            break;
        }

        // Strip off initial white space.
        std::string::size_type begin = line.find_first_not_of(" ");
        if (begin > 0)
        {
            line = line.substr(begin);
        }

        std::string::size_type end;
        std::string name;
        if (line.find("Node") == 0)
        {
            // Load the node.
            begin = line.find("<");
            end = line.find(">");
            name = line.substr(begin + 1, end - 1 - begin);
            if (name.back() == 'X')
            {
                // TODO: These nodes are not necessary.  Remove them from the
                // data sets.
                continue;
            }

            PreSpatial* preSpatial = LoadNode(rootPath, name);
            preSpatialArray.push_back(preSpatial);
            Node* node = reinterpret_cast<Node*>(preSpatial->Associate);
            spatialMap[name] = node;

            // Load the transform controllers.
            NodeCtrl nc;
            nc.first = node;

            nc.second.reset(LoadTransformController(rootPath, name, "Idle"));
            mIdleArray.push_back(nc);

            nc.second.reset(LoadTransformController(rootPath, name, "Walk"));
            mWalkArray.push_back(nc);

            nc.second.reset(LoadTransformController(rootPath, name, "Run"));
            mRunArray.push_back(nc);
        }
        else if (line.find("TriMesh") == 0)
        {
            // Load the mesh.
            begin = line.find("<");
            end = line.find(">");
            name = line.substr(begin + 1, end - 1 - begin);
            int suffix = name[name.length() - 1] - '0';
            PreSpatial* preSpatial = LoadMesh(rootPath, name, vformat, effect[suffix]);
            preSpatialArray.push_back(preSpatial);
            spatialMap[name] = preSpatial->Associate;

            // Load the skin controller.
            PreSkin* preSkin = LoadSkinController(rootPath, name, postUpdate);
            preSkinArray.push_back(preSkin);

            // Attach the skin controller to the mesh.
            preSpatial->Associate->AttachController(preSkin->Associate);
        }
    }

    // Resolve the bone links.
    for (auto preSkin : preSkinArray)
    {
        SkinController* ctrl = preSkin->Associate;
        Node** bones = ctrl->GetBones();
        int i = 0;
        for (auto const& boneName : preSkin->BoneNames)
        {
            auto iter = spatialMap.find(boneName);
            bones[i] = reinterpret_cast<Node*>(iter->second);
            ++i;
        }
    }

    // Assemble the biped hierarchy.
    for (auto preSpatial : preSpatialArray)
    {
        Node* node = dynamic_cast<Node*>(preSpatial->Associate);
        if (node)
        {
            for (auto const& childName : preSpatial->ChildNames)
            {
                if (childName.back() == 'X')
                {
                    // TODO: These nodes are not necessary.  Remove them from
                    // the data sets.
                    continue;
                }

                auto iter = spatialMap.find(childName);
                Visual* mesh = dynamic_cast<Visual*>(iter->second);
                if (mesh)
                {
                    std::shared_ptr<Visual> visual(mesh);
                    node->AttachChild(visual);
                    if (visual->GetEffect().get() == effect[0].get())
                    {
                        mSubscribers[0].first = visual;
                        mSubscribers[0].second = effect[0]->GetPVWMatrixConstant();
                    }
                    else
                    {
                        mSubscribers[1].first = visual;
                        mSubscribers[1].second = effect[1]->GetPVWMatrixConstant();
                    }
                }
                else
                {
                    node->AttachChild(std::shared_ptr<Spatial>(iter->second));
                }
            }
        }
    }

    mRoot.reset(reinterpret_cast<Node*>(preSpatialArray[0]->Associate));

    for (auto preSpatial : preSpatialArray)
    {
        delete preSpatial;
    }

    for (auto preSkin : preSkinArray)
    {
        delete preSkin;
    }

    // Create the blend controllers.
    int const numControllers = static_cast<int>(mIdleArray.size());
    mIdleWalkArray.resize(numControllers);
    mWalkRunArray.resize(numControllers);
    for (int i = 0; i < numControllers; ++i)
    {
        NodeCtrl const& nc0 = mIdleArray[i];
        NodeCtrl const& nc1 = mWalkArray[i];
        NodeCtrl const& nc2 = mRunArray[i];

        mIdleWalkArray[i].first = nc0.first;
        mIdleWalkArray[i].second = std::make_shared<BlendTransformController>(
            nc0.second, nc1.second, true, false);

        mWalkRunArray[i].first = nc0.first;
        mWalkRunArray[i].second = std::make_shared<BlendTransformController>(
            nc1.second, nc2.second, true, false);
    }
}
예제 #17
0
void BSplineSurfaceFitterWindow::CreateScene()
{
    // Begin with a flat 64x64 height field.
    int const numSamples = 64;
    float const extent = 8.0f;
    VertexFormat hfformat;
    hfformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    hfformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0);
    MeshFactory mf;
    mf.SetVertexFormat(hfformat);
    mHeightField = mf.CreateRectangle(numSamples, numSamples, extent, extent);
    int numVertices = numSamples * numSamples;
    VertexPT* hfvertices = mHeightField->GetVertexBuffer()->Get<VertexPT>();

    // Set the heights based on a precomputed height field.  Also create a
    // texture image to go with the height field.
    std::string path = mEnvironment.GetPath("BTHeightField.png");
    std::shared_ptr<Texture2> texture(WICFileIO::Load(path, false));
    std::shared_ptr<Texture2Effect> txeffect =
        std::make_shared<Texture2Effect>(mProgramFactory, texture,
        SamplerState::MIN_L_MAG_L_MIP_P, SamplerState::CLAMP,
        SamplerState::CLAMP);
    mHeightField->SetEffect(txeffect);

    std::mt19937 mte;
    std::uniform_real_distribution<float> symmr(-0.05f, 0.05f);
    std::uniform_real_distribution<float> intvr(32.0f, 64.0f);
    unsigned char* data = (unsigned char*)texture->Get<unsigned char>();
    std::vector<Vector3<float>> samplePoints(numVertices);
    for (int i = 0; i < numVertices; ++i)
    {
        unsigned char value = *data;
        float height = 3.0f*((float)value) / 255.0f + symmr(mte);
        *data++ = (unsigned char)intvr(mte);
        *data++ = 3 * (128 - value / 2) / 4;
        *data++ = 0;
        data++;

        hfvertices[i].position[2] = height;
        samplePoints[i] = hfvertices[i].position;
    }

    // Compute a B-Spline surface with NxN control points, where N < 64.
    // This surface will be sampled to 64x64 and displayed together with the
    // original height field for comparison.
    int const numControls = 32;
    int const degree = 3;
    BSplineSurfaceFit<float> fitter(degree, numControls, numSamples, degree,
        numControls, numSamples, &samplePoints[0]);

    VertexFormat ffformat;
    ffformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    ffformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0);
    mf.SetVertexFormat(ffformat);
    mFittedField = mf.CreateRectangle(numSamples, numSamples, extent, extent);
    VertexPC* ffvertices = mFittedField->GetVertexBuffer()->Get<VertexPC>();

    Vector4<float> translucent{ 1.0f, 1.0f, 1.0f, 0.5f };
    for (int i = 0; i < numVertices; ++i)
    {
        float u = 0.5f*(ffvertices[i].position[0] / extent + 1.0f);
        float v = 0.5f*(ffvertices[i].position[1] / extent + 1.0f);
        ffvertices[i].position = fitter.GetPosition(u, v);
        ffvertices[i].color = translucent;
    }

    std::shared_ptr<VertexColorEffect> vceffect =
        std::make_shared<VertexColorEffect>(mProgramFactory);
    mFittedField->SetEffect(vceffect);

    mCameraRig.Subscribe(mHeightField->worldTransform,
        txeffect->GetPVWMatrixConstant());
    mCameraRig.Subscribe(mFittedField->worldTransform,
        vceffect->GetPVWMatrixConstant());

    mTrackball.Attach(mHeightField);
    mTrackball.Attach(mFittedField);
    mTrackball.Update();
}
예제 #18
0
bool ConvexHull3DWindow::LoadData()
{
    std::string filename = "data";
    if (mCurrentFile < 10)
    {
        filename += "0";
    }
    filename += std::to_string(mCurrentFile) + ".txt";
    std::string path = mEnvironment.GetPath(filename);
    if (path == "")
    {
        return false;
    }

    std::ifstream input(path);
    if (!input)
    {
        return false;
    }

    Vector3<float> center{ 0.0f, 0.0f, 0.0f };
    unsigned int numVertices;
    input >> numVertices;
    std::vector<Vector3<float>> vertices(numVertices);
    for (auto& v : vertices)
    {
        for (int j = 0; j < 3; ++j)
        {
            input >> v[j];
        }
        center += v;
    }
    input.close();
    center /= static_cast<float>(numVertices);

    float radius = 0.0f;
    for (auto const& v : vertices)
    {
        Vector3<float> diff = v - center;
        float length = Length(diff);
        if (length > radius)
        {
            radius = length;
        }
    }

    // The worst-case number of words for UIntegerFP32<N> for 'float' input
    // to ConvexHull3 is N = 27.  For 'double', it is 'N = 197'.
    ConvexHull3<float, BSNumber<UIntegerFP32<27>>> ch;
    if (numVertices < 4 || !ch(numVertices, &vertices[0], 0.0f))
    {
        if (mMesh)
        {
            mTrackball.Detach(mMesh);
            mTrackball.Update();
            mCameraRig.Unsubscribe(mMesh->worldTransform);
            mMesh = nullptr;
        }

        mMessage = "File = " + std::to_string(mCurrentFile) +
            " has intrinsic dimension " + std::to_string(ch.GetDimension());
        return false;
    }
#if defined(GTE_COLLECT_BSNUMBER_STATISTICS)
    std::cout << "max size = " << gte::gBSNumberMaxSize << std::endl;
#endif

    std::vector<TriangleKey<true>> const& triangles = ch.GetHullUnordered();

    std::mt19937 mte;
    std::uniform_real_distribution<float> rnd(0.0f, 1.0f);

    struct Vertex
    {
        Vector3<float> position;
        Vector4<float> color;
    };
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0);
    std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat,
        numVertices));
    Vertex* vertex = vbuffer->Get<Vertex>();
    for (unsigned int i = 0; i < numVertices; ++i)
    {
        vertex[i].position = vertices[i];
        vertex[i].color[0] = rnd(mte);
        vertex[i].color[1] = rnd(mte);
        vertex[i].color[2] = rnd(mte);
        vertex[i].color[3] = 1.0f;
    }

    unsigned int numPrimitives = static_cast<unsigned int>(triangles.size());
    std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRIMESH,
        numPrimitives, sizeof(unsigned int)));
    Memcpy(ibuffer->GetData(), &triangles[0], ibuffer->GetNumBytes());

    // Update all information associated with the mesh transforms.
    if (mMesh)
    {
        mTrackball.Detach(mMesh);
        mTrackball.Update();
        mCameraRig.Unsubscribe(mMesh->worldTransform);
    }
    mMesh = std::make_shared<Visual>(vbuffer, ibuffer, mEffect);
    mMesh->localTransform.SetTranslation(-center);
    mMesh->worldTransform = mMesh->localTransform;
    mCameraRig.Subscribe(mMesh->worldTransform,
        mEffect->GetPVWMatrixConstant());

    // Move the camera for a centered view of the mesh.
    Vector4<float> camPosition = Vector4<float>{0.0f, 0.0f, 0.0f, 1.0f}
        - 2.5f*radius*mCamera->GetDVector();
    mCamera->SetPosition(camPosition);

    // Update the message for display.
    mMessage =
        "File = " + std::to_string(mCurrentFile) + " , " +
        "Vertices = " + std::to_string(numVertices) + " , " +
        "Triangles =" + std::to_string(numPrimitives);

    mTrackball.Attach(mMesh);
    mTrackball.Update();
    mCameraRig.UpdatePVWMatrices();
    return true;
}
예제 #19
0
void MassSprings3DWindow::CreateBoxFaces()
{
    // The vertex buffer will use the mass-spring position array for its
    // CPU data.
    int const numVertices = mDimension[0] * mDimension[1] * mDimension[2];

#if defined(DO_CPU_MASS_SPRING)
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    mVBuffer = std::make_shared<VertexBuffer>(vformat, numVertices, false);
    mVBuffer->SetUsage(Resource::DYNAMIC_UPDATE);
#else
    mVBuffer = std::make_shared<VertexBuffer>(numVertices);
#endif
    
    size_t const idxsize = sizeof(unsigned int);
    std::shared_ptr<IndexBuffer> ibuffer;
    int numTriangles, t, x, y, z, v0, v1, v2, v3;

    // box face z = 1
    numTriangles = 2 * (mDimension[0] - 1) * (mDimension[1] - 1);
    ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles,
        idxsize);
    for (y = 1, t = 0; y < mDimension[1] - 2; ++y)
    {
        for (x = 1; x < mDimension[0] - 2; ++x)
        {
            v0 = GetIndex(x, y, 1);
            v1 = GetIndex(x + 1, y, 1);
            v2 = GetIndex(x, y + 1, 1);
            v3 = GetIndex(x + 1, y + 1, 1);
            ibuffer->SetTriangle(t++, v0, v2, v3);
            ibuffer->SetTriangle(t++, v0, v3, v1);
        }
    }
    mBoxFace[0] = std::make_shared<Visual>(mVBuffer, ibuffer);

    // box face z = dim2 - 2
    numTriangles = 2 * (mDimension[0] - 1) * (mDimension[1] - 1);
    ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles,
        idxsize);
    for (y = 1, t = 0; y < mDimension[1] - 2; ++y)
    {
        for (x = 1; x < mDimension[0] - 2; ++x)
        {
            v0 = GetIndex(x, y, mDimension[2] - 2);
            v1 = GetIndex(x + 1, y, mDimension[2] - 2);
            v2 = GetIndex(x, y + 1, mDimension[2] - 2);
            v3 = GetIndex(x + 1, y + 1, mDimension[2] - 2);
            ibuffer->SetTriangle(t++, v0, v3, v2);
            ibuffer->SetTriangle(t++, v0, v1, v3);
        }
    }
    mBoxFace[1] = std::make_shared<Visual>(mVBuffer, ibuffer);

    // box face y = 1
    numTriangles = 2 * (mDimension[0] - 1) * (mDimension[2] - 1);
    ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles,
        idxsize);
    for (z = 1, t = 0; z < mDimension[2] - 2; ++z)
    {
        for (x = 1; x < mDimension[0] - 2; ++x)
        {
            v0 = GetIndex(x, 1, z);
            v1 = GetIndex(x + 1, 1, z);
            v2 = GetIndex(x, 1, z + 1);
            v3 = GetIndex(x + 1, 1, z + 1);
            ibuffer->SetTriangle(t++, v0, v3, v2);
            ibuffer->SetTriangle(t++, v0, v1, v3);
        }
    }
    mBoxFace[2] = std::make_shared<Visual>(mVBuffer, ibuffer);

    // box face y = dim1 - 2
    numTriangles = 2 * (mDimension[0] - 1) * (mDimension[2] - 1);
    ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles,
        idxsize);
    for (z = 1, t = 0; z < mDimension[2] - 2; ++z)
    {
        for (x = 1; x < mDimension[0] - 2; ++x)
        {
            v0 = GetIndex(x, mDimension[1] - 2, z);
            v1 = GetIndex(x + 1, mDimension[1] - 2, z);
            v2 = GetIndex(x, mDimension[1] - 2, z + 1);
            v3 = GetIndex(x + 1, mDimension[1] - 2, z + 1);
            ibuffer->SetTriangle(t++, v0, v2, v3);
            ibuffer->SetTriangle(t++, v0, v3, v1);
        }
    }
    mBoxFace[3] = std::make_shared<Visual>(mVBuffer, ibuffer);

    // box face x = 1
    numTriangles = 2 * (mDimension[1] - 1) * (mDimension[2] - 1);
    ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles,
        idxsize);
    for (z = 1, t = 0; z < mDimension[2] - 2; ++z)
    {
        for (y = 1; y < mDimension[1] - 2; ++y)
        {
            v0 = GetIndex(1, y, z);
            v1 = GetIndex(1, y + 1, z);
            v2 = GetIndex(1, y, z + 1);
            v3 = GetIndex(1, y + 1, z + 1);
            ibuffer->SetTriangle(t++, v0, v2, v3);
            ibuffer->SetTriangle(t++, v0, v3, v1);
        }
    }
    mBoxFace[4] = std::make_shared<Visual>(mVBuffer, ibuffer);

    // box face x = dim0 - 2
    numTriangles = 2 * (mDimension[1] - 1) * (mDimension[2] - 1);
    ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles,
        idxsize);
    for (z = 1, t = 0; z < mDimension[2] - 2; ++z)
    {
        for (y = 1; y < mDimension[1] - 2; ++y)
        {
            v0 = GetIndex(mDimension[0] - 2, y, z);
            v1 = GetIndex(mDimension[0] - 2, y + 1, z);
            v2 = GetIndex(mDimension[0] - 2, y, z + 1);
            v3 = GetIndex(mDimension[0] - 2, y + 1, z + 1);
            ibuffer->SetTriangle(t++, v0, v3, v2);
            ibuffer->SetTriangle(t++, v0, v1, v3);
        }
    }
    mBoxFace[5] = std::make_shared<Visual>(mVBuffer, ibuffer);

    Vector4<float> const color[6] =
    {
        { 1.0f, 0.0f, 0.0f, 1.0f },
        { 0.0f, 1.0f, 0.0f, 1.0f },
        { 0.0f, 0.0f, 1.0f, 1.0f },
        { 0.0f, 1.0f, 1.0f, 1.0f },
        { 1.0f, 0.0f, 1.0f, 1.0f },
        { 1.0f, 1.0f, 0.0f, 1.0f }
    };

#if defined(DO_CPU_MASS_SPRING)
    for (int i = 0; i < 6; ++i)
    {
        mEffect[i] = std::make_shared<ConstantColorEffect>(color[i]);
        mBoxFace[i]->SetEffect(mEffect[i]);
    }
#else
    std::string path = mEnvironment.GetPath("DrawUsingVertexID.hlsl");
    std::shared_ptr<ConstantBuffer> pvwMatrixBuffer;
    std::shared_ptr<ConstantBuffer> colorBuffer;
    std::shared_ptr<VisualProgram> program;
    std::shared_ptr<VertexShader> vshader;
    std::shared_ptr<PixelShader> pshader;
    for (int i = 0; i < 6; ++i)
    {
        pvwMatrixBuffer = std::make_shared<ConstantBuffer>(
            sizeof(Matrix4x4<float>), true);
        colorBuffer = std::make_shared<ConstantBuffer>(
            sizeof(Vector4<float>), false);
        *colorBuffer->Get<Vector4<float>>() = color[i];
        // TODO: Need to terminate application if 'program' is null.
        program = mProgramFactory.CreateFromFiles(path, path, "");
        vshader = program->GetVShader();
        vshader->Set("PVWMatrix", pvwMatrixBuffer);
        vshader->Set("ConstantColor", colorBuffer);
        vshader->Set("position", mMassSprings->GetPosition());
        mEffect[i] = std::make_shared<VisualEffect>(program);
        mBoxFace[i]->SetEffect(mEffect[i]);
    }
#endif
}
예제 #20
0
void LightsWindow::CreateScene()
{
    // Copper color for the planes.
    Vector4<float> planeAmbient{ 0.2295f, 0.08825f, 0.0275f, 1.0f };
    Vector4<float> planeDiffuse{ 0.5508f, 0.2118f, 0.066f, 1.0f };
    Vector4<float> planeSpecular{ 0.580594f, 0.223257f, 0.0695701f, 51.2f };

    // Gold color for the spheres.
    Vector4<float> sphereAmbient{ 0.24725f, 0.2245f, 0.0645f, 1.0f };
    Vector4<float> sphereDiffuse{ 0.34615f, 0.3143f, 0.0903f, 1.0f };
    Vector4<float> sphereSpecular{ 0.797357f, 0.723991f, 0.208006f, 83.2f };

    // Various parameters shared by the lighting constants.  The geometric
    // parameters are dynamic, modified by UpdateConstants() whenever the
    // camera or scene moves.  These include camera model position, light
    // model position, light model direction, and model-to-world matrix.
    Vector4<float> darkGray{ 0.1f, 0.1f, 0.1f, 1.0f };
    Vector4<float> lightGray{ 0.75f, 0.75f, 0.75f, 1.0f };
    float angle = 0.125f*(float)GTE_C_PI;
    Vector4<float> lightSpotCutoff{ angle, cos(angle), sin(angle), 1.0f };

    mLightWorldPosition[SVTX] = { 4.0f, 4.0f - 8.0f, 8.0f, 1.0f };
    mLightWorldPosition[SPXL] = { 4.0f, 4.0f + 8.0f, 8.0f, 1.0f };
    mLightWorldDirection = { -1.0f, -1.0f, -1.0f, 0.0f };
    Normalize(mLightWorldDirection);

    std::shared_ptr<Material> material[LNUM][GNUM];
    std::shared_ptr<Lighting> lighting[LNUM][GNUM];
    std::shared_ptr<LightCameraGeometry> geometry[LNUM][GNUM];
    for (int lt = 0; lt < LNUM; ++lt)
    {
        for (int gt = 0; gt < GNUM; ++gt)
        {
            material[lt][gt] = std::make_shared<Material>();
            lighting[lt][gt] = std::make_shared<Lighting>();
            geometry[lt][gt] = std::make_shared<LightCameraGeometry>();
        }
    }

    // Initialize the directional lighting constants.
    material[LDIR][GPLN]->ambient = planeAmbient;
    material[LDIR][GPLN]->diffuse = planeDiffuse;
    material[LDIR][GPLN]->specular = planeSpecular;
    lighting[LDIR][GPLN]->ambient = lightGray;
    material[LDIR][GSPH]->ambient = sphereAmbient;
    material[LDIR][GSPH]->diffuse = sphereDiffuse;
    material[LDIR][GSPH]->specular = sphereSpecular;
    lighting[LDIR][GSPH]->ambient = lightGray;

    // Initialize the point lighting constants.
    material[LPNT][GPLN]->ambient = planeAmbient;
    material[LPNT][GPLN]->diffuse = planeDiffuse;
    material[LPNT][GPLN]->specular = planeSpecular;
    lighting[LPNT][GPLN]->ambient = darkGray;
    material[LPNT][GSPH]->ambient = sphereAmbient;
    material[LPNT][GSPH]->diffuse = sphereDiffuse;
    material[LPNT][GSPH]->specular = sphereSpecular;
    lighting[LPNT][GSPH]->ambient = darkGray;

    // Initialize the spot lighting constants.
    material[LSPT][GPLN]->ambient = planeAmbient;
    material[LSPT][GPLN]->diffuse = planeDiffuse;
    material[LSPT][GPLN]->specular = planeSpecular;
    lighting[LSPT][GPLN]->ambient = darkGray;
    lighting[LSPT][GPLN]->spotCutoff = lightSpotCutoff;
    material[LSPT][GSPH]->ambient = sphereAmbient;
    material[LSPT][GSPH]->diffuse = sphereDiffuse;
    material[LSPT][GSPH]->specular = sphereSpecular;
    lighting[LSPT][GSPH]->ambient = darkGray;
    lighting[LSPT][GSPH]->spotCutoff = lightSpotCutoff;

    // Create the effects.
    for (int gt = 0; gt < GNUM; ++gt)
    {
        for (int st = 0; st < SNUM; ++st)
        {
            mEffect[LDIR][gt][st] = std::make_shared<DirectionalLightEffect>(
                mProgramFactory, mUpdater, st,
                material[LDIR][gt], lighting[LDIR][gt], geometry[LDIR][gt]);

            mEffect[LPNT][gt][st] = std::make_shared<PointLightEffect>(
                mProgramFactory, mUpdater, st,
                material[LPNT][gt], lighting[LPNT][gt], geometry[LPNT][gt]);

            mEffect[LSPT][gt][st] = std::make_shared<SpotLightEffect>(
                mProgramFactory, mUpdater, st,
                material[LSPT][gt], lighting[LSPT][gt], geometry[LSPT][gt]);
        }
    }

    // Create the planes and spheres.
    VertexFormat vformat;
    vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0);
    vformat.Bind(VA_NORMAL, DF_R32G32B32_FLOAT, 0);
    MeshFactory mf;
    mf.SetVertexFormat(vformat);

    mPlane[SVTX] = mf.CreateRectangle(128, 128, 8.0f, 8.0f);
    mPlane[SVTX]->localTransform.SetTranslation(0.0f, -8.0f, 0.0f);
    mTrackball.Attach(mPlane[SVTX]);

    mPlane[SPXL] = mf.CreateRectangle(128, 128, 8.0f, 8.0f);
    mPlane[SPXL]->localTransform.SetTranslation(0.0f, +8.0f, 0.0f);
    mTrackball.Attach(mPlane[SPXL]);

    mSphere[SVTX] = mf.CreateSphere(64, 64, 2.0f);
    mSphere[SVTX]->localTransform.SetTranslation(0.0f, -8.0f, 2.0f);
    mTrackball.Attach(mSphere[SVTX]);

    mSphere[SPXL] = mf.CreateSphere(64, 64, 2.0f);
    mSphere[SPXL]->localTransform.SetTranslation(0.0f, +8.0f, 2.0f);
    mTrackball.Attach(mSphere[SPXL]);

    mTrackball.Update();

    mCaption[LDIR] = "Directional Light (left per vertex, right per pixel)";
    mCaption[LPNT] = "Point Light (left per vertex, right per pixel)";
    mCaption[LSPT] = "Spot Light (left per vertex, right per pixel)";

    UseLightType(LDIR);
}