Cinder how to texture an .obj trimesh - c++

I am new to c++/cinder and I am trying to import a 3ds .obj file into cinder and apply a simple texture. I really cant find any simple tutorials on how to do this and it seems to be slightly different to freeGLUT.
gl::Texture sTexture;
sTexture = gl::Texture(loadImage(loadAsset("texture.jpg")));
cinder::TriMesh mySphere;
ObjLoader loader( loadFile( "mySphere/sphere.obj" ) );
loader.load( &mySphere );
gl::draw( mySphere );
I understand that mySphere constains the texture co-ords as a vector and I need to bind the texture to the object, but I cant find a clear example of how? Everything I have tried has left me with a white circle.
Thanks.

Found my solution. I was using sTexture.bind(); but sTexture.enableAndBind(); is needed.
gl::Texture sTexture;
sTexture = gl::Texture(loadImage(loadAsset("texture.jpg")));
sTexture.enableAndBind();
cinder::TriMesh mySphere;
ObjLoader loader( loadFile( "mySphere/sphere.obj" ) );
loader.load( &mySphere );
gl::draw( mySphere );
sTexture.unbind();

Related

Qt3D texture parameter

I am using Qt3D (5.11), and I am experiencing asserts when I try to set a QParameter value to be used by a custom fragment shader. Here is the section of code that doesn't seem to be working:
auto entity = new Qt3DRender::QEntity( mRootEntity );
auto material = new Qt3DRender::QMaterial( entity );
// Set up the custom geometry and material for the entity, which works
// fine in tests as long as the fragment shader does not use texture mapping
auto image = new Qt3DRender::QTextureImage( entity );
image->setSource( QString( "qrc:/image.png" ) );
auto texture = new Qt3DRender::QTexture2D( entity );
texture->addTextureImage( image );
material->addParameter( new QParameter( "imageTexture", texture, entity ) );
I've included only the bits of code needed for this question:
Is this a valid way to set a simple texture parameter? If not, what am I missing to set a simple image?
Note that qrc:/image.png is a 256x256 image that I have used elsewhere in this project without a problem.
The code compiles fine, but when I run it I get an assert with the following message: ASSERT: "texture" in file texture\textureimage.cpp, line 94
I am using VS2017 on Windows 10 with Qt 5.11.
I stumbled upon the issue. Parenting the QTextureImage to entity leads to the assert. Leaving off the parent completely (effectively setting it to nullptr) or parenting it to texture fixes the issue.
Here is some working code:
auto texture = new Qt3DRender::QTexture2D( entity );
auto image = new Qt3DRender::QTextureImage( texture );
image->setSource( QString( "qrc:/image.png" ) );
texture->addTextureImage( image );
material->addParameter( new QParameter( "imageTexture", texture, entity ) );
This is probably a bug? If someone knows why the QTextureImage cannot be safely parented to entity, please add a comment.

Loading a texture using OpenGL

I am trying to load a texture via OpenGL for a 2d platformer and the code seems to be crashing on this exact part, but the lack of knowledge in C++ or openGL seems to be my problem, pls help!
bool Texture::LoadTextureFromFile( std::string path )
{
//Texture loading success
bool textureLoaded = false;
//Generate and set current image ID
GLuint imgID = 0;
glGenTextures( 1, &imgID );
glBindTexture(GL_TEXTURE_2D ,imgID );
//Load image
GLboolean success = glLoadTextures( path.c_str() );
//Image loaded successfully
if( success == GL_TRUE )
{
//Convert image to RGBA
// success = ilConvertImage( IL_RGBA, IL_UNSIGNED_BYTE );
if( success == GL_TRUE )
{
//Create texture from file pixels
textureLoaded = LoadTextureFromPixels32
( (GLuint*)glGetDoublev, (GLuint*)glGetIntegerv( GL_TEXTURE_WIDTH ), GLuint*(glGetIntegerv( GL_TEXTURE_HEIGHT )) );
}
//Delete file from memory
glDeleteTextures( 1, &imgID );
}
//Report error
if( !textureLoaded )
{
printf( "Unable to load %s\n", path.c_str() );
}
return textureLoaded;
}
There are a few possible issues.
Firstly, where do you get glLoadTextures() from? And what does it do? That's not part of the OpenGL specification. It's not clear to me what it does. It's possible that this function does the entire texture loading for you, and the code below just screws things up.
Next, your first parameter to LoadTextureFromPixels32() is glGetDoubleV. You're passing it a pointer to the function glGetDoubleV, which is definitely NOT right. I assume that parameter expects a pointer to the loaded image data.
Finally, your code deletes the texture you just created with glDeleteTextures(). That makes no sense. Your texture object's ID is stored in imgID, which is a local variable. You're deleting it so the texture's gone.
The normal procedure for creating a texture is:
Load the texture data (using something like SDL_image, or another image loading library)
Create the texture object using glGenTextures(); NOTE: This is your handle to the texture; you MUST store this for future use
Bind it glBindTexture()
Load in the image data glTexture2D()
That's it.

Cannot both rotate and translate my scene - direct3d

I have drawn a cube onto the screen and I want to both rotate and translate the scene:
// Translation
XMStoreFloat4x4( &m_constantBufferData.model, XMMatrixTranspose( XMMatrixTranslation( placement->GetPosX(), placement->GetPosY(), placement->GetPosZ() ) ) );
// Rotation
XMStoreFloat4x4( &m_constantBufferData.model, XMMatrixTranspose(XMMatrixRotationX( placement->GetRotX() ) ) );
XMStoreFloat4x4( &m_constantBufferData.model, XMMatrixTranspose(XMMatrixRotationY( placement->GetRotY() ) ) );
XMStoreFloat4x4( &m_constantBufferData.model, XMMatrixTranspose(XMMatrixRotationZ( placement->GetRotZ() ) ) );
the problem is, only the translation is working... Do I have to set something somehow before doing the rotations too.
I have used the default Windows 8 Phone Direct3D C++ Project in Visual Studio 2012 Windows Phone.
I have passed in a few more variables and thanks to intellisense, found out there was a matrixtransaltion function
I added my positioning to this matrix and also hooked up the rotation to some custom variables too
The cube will move (translate) but I am guessing I need to save this movement somehow and THEN do the rotation.
Anything I can add to this to help solve the issue?
You are overwriting the contents of m_constantBufferData.model every time. You need to call XMMatrixMultiply on the four matrices to combine the transformations into a single matrix, then store the final result. For example:
// Rotation
XMMATRIX m = XMMatrixRotationX( placement->GetRotX() );
m = XMMatrixMultiply(m, XMMatrixRotationY( placement->GetRotY() );
m = XMMatrixMultiply(m, XMMatrixRotationZ( placement->GetRotZ() );
// Translation
m = XMMatrixMultiply(m, XMMatrixTranslation( placement->GetPosX(), placement->GetPosY(), placement->GetPosZ() ) );
XMStoreFloat4x4( &m_constantBufferData.model, XMMatrixTranspose(m) );

Draw stroke characters with outlines in openGL

I am using openGL to draw fonts. My fonts need to be rotatable and I cannot use glut, so I created a static class that has vertex lists for every needed character. I then render these using GL_LINE_STRIP.
Recently I've been asked to allow my characters to have outlines, sort of like they would if you went into word, created a bold character and then under Font, gave it an outline.
Not sure how to put a picture of that in stack overflow.
I was wondering if there was a way to do that given my current method of drawing characters using lines. Is it possible to have a line border, or is that inherently nonsense?
Two passes:
const float OUTLINE_WIDTH = 3.0f;
const float INNER_WIDTH = 1.0f;
glLineWidth( OUTLINE_WIDTH );
glColor3ub( outline.r, outline.g, outline.b );
DrawText();
glLineWidth( INNER_WIDTH );
glColor3ub( inner.r, inner.g, inner.b );
DrawText();

Direct3D rendering 2D images with "multiply" blending mode and alpha

I'm trying to replicate the Photoshop filter multiply with Direct3D. I've been reading and googling about the different render states and I've got the effect almost working. The problem is that it's ignoring the alpha value of the textures.
Here's an image that explains the sitution:
http://www.kloonigames.com/petri/stackoverflow_doesnt_allow_.jpg
I found one solution to this, which was to save the images with no transparency and white background. But I'm not satisfied with this solution. The problem is that I really need to use the alpha value. I want to fade out the images gradually. And I cannot do this if the blending mode is ignoring the alpha value.
So the question is how to render the images with alpha?
Here's the blending mode code:
dev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);
Edit added the SetTextureStageState
dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
dev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
dev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
You can achieve this effect in one step by premultipling alpha in your pixel shader, or by using textures with pre-multiplied alpha.
For example if you have 3 possible blend operations for a shader, and you want each one to take alpha into account.
Blend = ( src.rgb * src.a ) + ( dest.rgb * (1-src.a) )
Add = ( src.rgb * src.a ) + ( dest.rgb )
Multiply = (src.rgb * dest.rgb * src.a) + (dest.rgb * (1-src.a) )
You'll notice that Multiply is impossible with a single pass because there are two operations on the source color. But if you premultiply alpha in your shader you can extract the alpha component from the blending operation and it becomes possible to blend all three operations in the same shader.
In your pixel shader you can pre-multiply alpha manually. Or use a tool like DirectXTex texconv to modify your textures.
return float4(color.rgb*color.a, color.a);
The operations become:
Blend = ( src.rgb ) + ( dest.rgb * (1-src.a) )
Add = ( src.rgb ) + ( dest.rgb )
Multiply = ( src.rgb * dest.rgb ) + (dest.rgb * (1-src.a) )
It sounds like you want:
dst.rgb = (src.a * src.rgb) * ((1 - src.a) * dst.rgb)
You would use D3DRS_BLENDOP to do that, but unfortunately there isn't a D3DBLENDOP_MULTIPLY. I don't think this operation is possible without a fragment shader.
OK this is not as simple as you would think. I would use an Effect & two renderTargets for this...
I'm amusing your using one render pass to try to do this, which will not work.
Photoshop has layers & each layers have an alpha channel. BTW it would be nice to know what kind of app your making.
So first in D3D I would create 2 RGBA_32bit renderTargets of the same size as your window & clear them to color white. Make it an array like so (new RenderTarget[2];) for swapping.
Now set the blending state to (AlphaFunc=Add, Src=SrcAlpha, Dst=InvSrcAlpha). For the first circle you draw it into renderTarget[0] using renderTarget[1] as a texture/sampler input source. You will render the circle with an Effect that will take the circles color & multiply it with renderTarget[1]'s sampler color. After you draw circle one you swap the renderTarget[0] with renderTarget[1] by simple indexing, so now renderTarget[1] is the one you draw to & renderTarget[0] is the one you sample from. Then you repeat the drawing process for circle 2 & so on.
After you draw ever circle you copy the last drawn renderTarget to the backBuffer & present the scene.
Here is an example of logically how you would do it. If you need reference for coding http://www.codesampler.com/ is a good place.
void TestLayering()
{
bool rtIndex = false;
RenderTarget* renderTarget = new RenderTarget[2];
Effect effect = new Effect("multiplyEffect.fx");
effect.Enable();
BlendingFunc = Add;
BlendingSource = SrcAlpha;
BlendingDest = InvSrcAlpha;
for(int i = 0; i != circleCount; ++i)
{
renderTarget[rtIndex].EnableAsRenderTarget();
renderTarget[!rtIndex].EnableAsSampler();
circle[i].Draw();
rtIndex = !rtIndex;
}
//Use D3D9's StretchRect for this...
backBuffer.CopyFromSurface(renderTarget[rtIndex]);
}
//Here is the effects pixel shader
float4 PS_Main(InStruct In) : COLOR
{
float4 backGround = tex2D(someSampler, In.UV);
return circleColor * backGround;
}
dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Will do the trick. You cannot use the 'alpha' from the diffuse vertex color anymore though. Setting a low alpha on the vertex colors will actually brighten your overlaying pixels.