GamePlay3d engine won't show model imported from fbx - c++

I am a newbie with gameplay3d and went through all tutorials, however I cant manage to display this simple(not much polygons and material) model that I encoded from Fbx. I checked the model with unity3D, and a closed source software that uses gameplay3d and all seems to fine. I guess I am missing some detail loading the scene.
This is the model file including also the original fbx file. I suspect if it has something to do with light
https://www.dropbox.com/sh/ohgpsfnkm3iv24s/AACApRcxwtbmpKu4_5nnp8rZa?dl=0
This is the class that loads the scene.
#include "Demo.h"
// Declare our game instance
Demo game;
Demo::Demo()
: _scene(NULL), _wireframe(false)
{
}
void Demo::initialize()
{
// Load game scene from file
Bundle* bundle = Bundle::create("KGN56AI30N.gpb");
_scene = bundle->loadScene();
SAFE_RELEASE(bundle);
// Get the box model and initialize its material parameter values and bindings
Camera* camera = Camera::createPerspective(45.0f, getAspectRatio(), 1.0f, 20.0f);
Node* cameraNode = _scene->addNode("camera");
// Attach the camera to a node. This determines the position of the camera.
cameraNode->setCamera(camera);
// Make this the active camera of the scene.
_scene->setActiveCamera(camera);
SAFE_RELEASE(camera);
// Move the camera to look at the origin.
cameraNode->translate(0,0, 10);
cameraNode->rotateX(MATH_DEG_TO_RAD(0.25f));
// Update the aspect ratio for our scene's camera to match the current device resolution
_scene->getActiveCamera()->setAspectRatio(getAspectRatio());
// Set the aspect ratio for the scene's camera to match the current resolution
_scene->getActiveCamera()->setAspectRatio(getAspectRatio());
Light* directionalLight = Light::createDirectional(Vector3::one());
_directionalLightNode = Node::create("directionalLight");
_directionalLightNode->setLight(directionalLight);
SAFE_RELEASE(directionalLight);
_scene->addNode(_directionalLightNode);
_scene->setAmbientColor(1.0, 1.0, 1.0);
_scene->visit(this, &Demo::initializeMaterials);
}
bool Demo::initializeMaterials(Node* node)
{
Model* model = dynamic_cast<Model*>(node->getDrawable());
if (model)
{
for(int i=0;i<model->getMeshPartCount();i++)
{
Material* material = model->getMaterial(i);
if(material)
{
// For this sample we will only bind a single light to each object in the scene.
MaterialParameter* colorParam = material->getParameter("u_directionalLightColor[0]");
colorParam->setValue(Vector3(0.75f, 0.75f, 0.75f));
MaterialParameter* directionParam = material->getParameter("u_directionalLightDirection[0]");
directionParam->setValue(Vector3(1, 1, 1));
}
}
}
return true;
}
void Demo::finalize()
{
SAFE_RELEASE(_scene);
}
void Demo::update(float elapsedTime)
{
// Rotate model
//_scene->findNode("box")->rotateY(MATH_DEG_TO_RAD((float)elapsedTime / 1000.0f * 180.0f));
}
void Demo::render(float elapsedTime)
{
// Clear the color and depth buffers
clear(CLEAR_COLOR_DEPTH, Vector4::zero(), 1.0f, 0);
// Visit all the nodes in the scene for drawing
_scene->visit(this, &Demo::drawScene);
}
bool Demo::drawScene(Node* node)
{
// If the node visited contains a drawable object, draw it
Drawable* drawable = node->getDrawable();
if (drawable)
drawable->draw(_wireframe);
return true;
}
void Demo::keyEvent(Keyboard::KeyEvent evt, int key)
{
if (evt == Keyboard::KEY_PRESS)
{
switch (key)
{
case Keyboard::KEY_ESCAPE:
exit();
break;
}
}
}
void Demo::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
{
switch (evt)
{
case Touch::TOUCH_PRESS:
_wireframe = !_wireframe;
break;
case Touch::TOUCH_RELEASE:
break;
case Touch::TOUCH_MOVE:
break;
};
}

I can't download your dropbox .fbx file. How many models do you have in the scene? Here's a simple way of doing what you want to do -- not optimal, but it'll get you started...
So first off, I can't see where in your code you actually assign a Shader to be used with the material. I use something like this:
material = model->setMaterial("Shaders/Animation/ADSVertexViewAnim.vsh", "Shaders/Animation/ADSVertexViewAnim.fsh");
You need to assign a Shader, and the above code will take the vertex and fragment shaders and use that when the object needs to be drawn.
I went about it a slightly different way by not loading the scene file automatically, but creating an empty scene and then extracting my model from the bundle and adding it to the scene manually. That way, I can see exactly what is happening and I'm in control of each step. GamePlay3D has some fancy property files, but use them only once you know how the process works manually..
Initially, I created a simple cube in a scene, and created a scene manually, and added the monkey to the node graph, as follows:
void GameMain::ExtractFromBundle()
{
/// Create a new empty scene.
_scene = Scene::create();
// Create the Model and its Node
Bundle* bundle = Bundle::create("res/monkey.gpb"); // Create the bundle from GPB file
/// Create the Cube
{
Mesh* meshMonkey = bundle->loadMesh("Character_Mesh"); // Load the mesh from the bundle
Model* modelMonkey = Model::create(meshMonkey);
Node* nodeMonkey = _scene->addNode("Monkey");
nodeMonkey->setTranslation(0,0,0);
nodeMonkey->setDrawable(modelMonkey);
}
}
Then I want to search the scene graph and only assign a material to the object that I want to draw (the monkey). Use this if you want to assign different materials to different objects manually...
bool GameMain::initializeScene(Node* node)
{
Material* material;
std::cout << node->getId() << std::endl;
// find the node in the scene
if (strcmp(node->getId(), "Monkey") != 0)
return false;
Model* model = dynamic_cast<Model*>(node->getDrawable());
if( !model )
return false;
material = model->setMaterial("Shaders/Animation/ADSVertexViewAnim.vsh", "Shaders/Animation/ADSVertexViewAnim.fsh");
material->getStateBlock()->setCullFace(true);
material->getStateBlock()->setDepthTest(true);
material->getStateBlock()->setDepthWrite(true);
// The World-View-Projection Matrix is needed to be able to see view the 3D world thru the camera
material->setParameterAutoBinding("u_worldViewProjectionMatrix", "WORLD_VIEW_PROJECTION_MATRIX");
// This matrix is necessary to calculate normals properly, but the WORLD_MATRIX would also work
material->setParameterAutoBinding("u_worldViewMatrix", "WORLD_VIEW_MATRIX");
material->setParameterAutoBinding("u_viewMatrix", "VIEW_MATRIX");
return true;
}
Now the object is ready to be drawn.... so I use these functions:
void GameMain::render(float elapsedTime)
{
// Clear the color and depth buffers
clear(CLEAR_COLOR_DEPTH, Vector4(0.0, 0.0, 0.0, 0.0), 1.0f, 0);
// Visit all the nodes in the scene for drawing
_scene->visit(this, &GameMain::drawScene);
}
bool GameMain::drawScene(Node* node)
{
// If the node visited contains a drawable object, draw it
Drawable* drawable = node->getDrawable();
if (drawable)
drawable->draw(_wireframe);
return true;
}
I use my own shaders, so I don't have to worry about Light and DirectionalLight and all that stuff. Once I can see the object, then I'll add dynamic lights, etc, but for starters, start simple.
Regards.

Related

Error with ue4 c++ fps tutorial section 3.2, what should I do?

I am up to section 3.2 of the fps tutorial on unreal engine 4. In this section I'm supposed to implement shooting into the code via the fire function so that i can shoot projectiles in-game. However, after typing the code the tutorial provided, I got one error when compiling it. The error is as follows
/Users/apple/Documents/Unreal Projects/FPSProject/Source/FPSProject/FPSCharacter.cpp:120:38: 'Instigator' is a private member of 'AActor'
When I remove this line and compile the code it does so successfully, but when I test it out on unreal, I can't shoot projectiles at all.
Here is the code
FPSCharacter.cpp
include "FPSCharacter.h"
include "FPSProject.h" #include "FPSCharacter.generated.h" #include "FPSProjectile.h" #include "GameFramework/Actor.h"
// Sets default values AFPSCharacter::AFPSCharacter() { // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true;
// Create a first person camera component.
FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
// Attach the camera component to our capsule component.
FPSCameraComponent->SetupAttachment(GetCapsuleComponent());
// Position the camera slightly above the eyes.
FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
// Allow the pawn to control camera rotation.
FPSCameraComponent->bUsePawnControlRotation = true;
// Create a first person mesh component for the owning player.
FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh"));
// Only the owning player sees this mesh.
FPSMesh->SetOnlyOwnerSee(true);
// Attach the FPS mesh to the FPS camera.
FPSMesh->SetupAttachment(FPSCameraComponent);
// Disable some environmental shadowing to preserve the illusion of having a single mesh.
FPSMesh->bCastDynamicShadow = false;
FPSMesh->CastShadow = false;
// The owning player doesn't see the regular (third-person) body mesh.
GetMesh()->SetOwnerNoSee(true);
}
// Called when the game starts or when spawned void AFPSCharacter::BeginPlay() { Super::BeginPlay();
if (GEngine)
{
// Put up a debug message for five seconds. The -1 "Key" value (first argument) indicates that we will never need to update or refresh this message.
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
}
}
// Called every frame void AFPSCharacter::Tick( float DeltaTime ) { Super::Tick( DeltaTime );
}
// Called to bind functionality to input void AFPSCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent);
// Set up "movement" bindings.
PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);
// Set up "look" bindings.
PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);
// Set up "action" bindings.
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire);
}
void AFPSCharacter::MoveForward(float Value) { // Find out which way is "forward" and record that the player wants to move that way. FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X); AddMovementInput(Direction, Value); }
void AFPSCharacter::MoveRight(float Value) { // Find out which way is "right" and record that the player wants to move that way. FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y); AddMovementInput(Direction, Value); }
void AFPSCharacter::StartJump() { bPressedJump = true; }
void AFPSCharacter::StopJump() { bPressedJump = false; }
void AFPSCharacter::Fire() { // Attempt to fire a projectile. if (ProjectileClass) { // Get the camera transform. FVector CameraLocation; FRotator CameraRotation; GetActorEyesViewPoint(CameraLocation, CameraRotation);
// Transform MuzzleOffset from camera space to world space.
FVector MuzzleLocation = CameraLocation + FTransform(CameraRotation).TransformVector(MuzzleOffset);
FRotator MuzzleRotation = CameraRotation;
// Skew the aim to be slightly upwards.
MuzzleRotation.Pitch += 10.0f;
UWorld* World = GetWorld();
if (World)
{
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
SpawnParams.Instigator = Instigator;
// Spawn the projectile at the muzzle.
AFPSProjectile* Projectile = World->SpawnActor<AFPSProjectile>(ProjectileClass, MuzzleLocation, MuzzleRotation, SpawnParams);
if (Projectile)
{
// Set the projectile's initial trajectory.
FVector LaunchDirection = MuzzleRotation.Vector();
Projectile->FireInDirection(LaunchDirection);
}
}
}
}

How to test what material is applied to an object in Unity

I have a diamond-sprite and I want to be able to change the colour of the diamond from white, it's original colour to green. However, I can not figure out how to do this.
public class MoveControl : MonoBehaviour {
// Update is called once per frame
void Update () {
if (Input.GetKey(KeyCode.A) )
{
if (GetComponent<Renderer>().material.color == Color.white)
{
GetComponent<Renderer>().material.color = Color.green;
}
}
}
}
This above code is what I have right now and it only works if the material applied to the sprite, being white, is a sprites/default shader. This may not sound like a big problem but whenever I apply a different material of a different colour, such as blue, and change its settings so it has a sprites/default shader, the sprite becomes invisible.
I'm new at Unity and if someone could help me out, it would be very much appreciated
I'm not sure what you're trying to do but this may help you.
public class Material : MonoBehaviour {
Renderer renderer;
Color currentColor;
Color originalColor;
// Use this for initialization
void Start () {
renderer = gameObject.GetComponent<Renderer>(); //If you don't know the gameObject is the object this script is attached to
originalColor = renderer.material.color; //The original color ( in your case white )
}
// Update is called once per frame
void Update () {
if (Input.GetKey(KeyCode.A)) {
if (renderer.material.color == originalColor) { //Here we are checking if the color on the object is the original color
renderer.material.color = Color.blue;
currentColor = renderer.material.color; //Here we are assining the current color
}
}
}
}
I created a material and assigned it to the gameObject in the editor.

In OpenTK, multiple meshes are not transforming when imported using Assimp

I'm sure there is an answer to this on the web but I can't find it.
I'm importing a scene from Blender that has multiple meshes, into OpenTK.
The library I'm using to import is Assimp-net, and the file format is Collada (.dae).
I have created a spaceship with multiple parts, each part being a mesh.
Now when I import and draw, the geometry of the objects looks fine and materials work as expected. However, the different parts are not rotated, scaled, or translated as they appear in Blender. What happens is the different parts are not connected, and some appear larger/smaller than they should, in the wrong place etc.
Is there a setting I'm missing when I export from Blender, or is there some Assimp member/function I can use to transform the meshes before I render them?
Importing the file:
string filename = #"C:\Path\ship.dae";
Scene ship;
//Create a new importer
AssimpImporter importer = new AssimpImporter();
//This is how we add a configuration (each config is its own class)
NormalSmoothingAngleConfig config = new NormalSmoothingAngleConfig(66.0f);
importer.SetConfig(config);
//Import the model
ship = importer.ImportFile(filename, PostProcessPreset.TargetRealTimeMaximumQuality);
//End of example
importer.Dispose();
Drawing the meshes(entire "RenderFrame" event handler in OpenTK):
// Clear color/depth buffers
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// Define world space
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-15.0, 15.0, -15.0, 15.0, 15.0, -15.0);
// Rotate around X and Y axes for better viewing
rotateX(xrot);
rotateY(yrot);
GL.Enable(EnableCap.ColorMaterial);
var rootnode = wes10.RootNode;
foreach (Node node in rootnode.Children)
{
//for each node, do
GL.MatrixMode(MatrixMode.Modelview); //ensure your current matrix is the model matrix.
GL.PushMatrix(); //save current model matrix so you can undo next transformations;
var meshIndices = node.MeshIndices;
if (meshIndices == null)
continue;
else
{
Matrix4d convertedTransform = new Matrix4d();
getConvertedMatrix(node.Transform, ref convertedTransform);
GL.MultMatrix(ref convertedTransform);
GL.Begin(BeginMode.Triangles);
foreach (uint i in meshIndices)
{
Mesh mesh = wes10.Meshes[i];
Material mat = wes10.Materials[mesh.MaterialIndex];
// Material setup
var spec_color = mat.ColorSpecular;
var amb_color = mat.ColorAmbient;
var diff_color = mat.ColorDiffuse;
float[] mat_specular = { spec_color.R, spec_color.G, spec_color.B, spec_color.A };
float[] mat_ambient = { amb_color.R, amb_color.G, amb_color.B, amb_color.A };
float[] mat_diffuse = { diff_color.R, diff_color.G, diff_color.B, diff_color.A };
float[] mat_shininess = { 0.0f };
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, mat_specular);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Ambient, mat_ambient);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, mat_diffuse);
GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, mat_shininess);
foreach (Face face in mesh.Faces)
{
foreach (uint indice in face.Indices)
{
var normal = mesh.Normals[indice];
var pos = mesh.Vertices[indice];
//var tex = mesh.GetTextureCoords(0)[v];
//GL.TexCoord2(tex.X, tex.Y);
GL.Normal3(normal.X, normal.Y, normal.Z);
GL.Vertex3(pos.X, pos.Y, pos.Z);
}
}
}
}
GL.PopMatrix();
}
GL.End();
game.SwapBuffers();
Updated to use suggestions.
In the c example, there is a transformation matrix per node...
aiMultiplyMatrix4(trafo,&nd->mTransformation);
Check this:
Data structure
scene graph.
If you don't know what to do with that matrix, check this to learn about matrix stack. (Be aware that modern OpenGL recommand to implement your own transformation matrix)
Golobaly, you need the folowing steps for rendering (read the c example for details):
//for each node, do
glMatrixMode (GL_MODELVIEW); //ensure your current matrix is the model matrix.
glPushMatrix (); //save current model matrix so you can undo next transformations;
glMultMatrixf(Transformation);//apply your node matrix
//render your node, in your example it's surely a mesh
glPopMatrix (); //restore model matrix

Shape manipulation with openFrameworks

I'm a openFrameworks newbie. I am learning basic 2d drawing which is all great so far. I have drawn a circle using:
ofSetColor(0x333333);
ofFill;
ofCircle(100,650,50);
My question is how do I give the circle a variable name so that I can manipulate in the mousepressed method? I tried adding a name before the ofCircle
theball.ofSetColor(0x333333);
theball.ofFill;
theball.ofCircle(100,650,50);
but get I 'theball' was not declared in this scope error.
As razong pointed out that's not how OF works. OF (to the best of my knowledge) provides a handy wrapper to a lot of OpenGL stuff. So you should use OF calls to effect the current drawing context (as opposed to thinking of a canvas with sprite objects or whatever). I usually integrate that kind of thing into my objects. So lets say you have a class like this...
class TheBall {
protected:
ofColor col;
ofPoint pos;
public:
// Pass a color and position when we create ball
TheBall(ofColor ballColor, ofPoint ballPosition) {
col = ballColor;
pos = ballPosition;
}
// Destructor
~TheBall();
// Make our ball move across the screen a little when we call update
void update() {
pos.x++;
pos.y++;
}
// Draw stuff
void draw(float alpha) {
ofEnableAlphaBlending(); // We activate the OpenGL blending with the OF call
ofFill(); //
ofSetColor(col, alpha); // Set color to the balls color field
ofCircle(pos.x, pos.y, 5); // Draw command
ofDisableAlphaBlending(); // Disable the blending again
}
};
Ok cool, I hope that makes sense. Now with this structure you can do something like the following
testApp::setup() {
ofColor color;
ofPoint pos;
color.set(255, 0, 255); // A bright gross purple
pos.x, pos.y = 50;
aBall = new TheBall(color, pos);
}
testApp::update() {
aBall->update()
}
testApp::draw() {
float alpha = sin(ofGetElapsedTime())*255; // This will be a fun flashing effect
aBall->draw(alpha)
}
Happy programming.
Happy designing.
You can't do it that way. ofCircle is a global drawing method and draws just a circle.
You can declare a variable (or better three int for rgb - since you can't use ofColor as an argument for ofSetColor) that store the color for the circle and modify it in the mousepressed method.
Inside the draw method use your variables for ofSetColor before rendering the circle.

C++ Meshes getting animated when they are not suppose too

I have two meshes. One of them is animated and the other one is not animated. When i render them the inanimate mesh gets animated the same way the animated mesh is animating.
So, let just the animated mesh goes to left than comes back, my inanimate mesh does the same thing!
This is my code class for the inanimate meshes.
main class
class StaticMesh
{
public:
StaticMesh(LPDIRECT3DDEVICE9* device);
~StaticMesh(void);
void Render(void);
void Load(LPCWSTR fileName);
void CleanUp(void);
private:
LPDIRECT3DDEVICE9* d3ddev; // the pointer to the device class
LPD3DXMESH mesh; // define the mesh pointer
D3DMATERIAL9* material; // define the material object
DWORD numMaterials; // stores the number of materials in the mesh
LPDIRECT3DTEXTURE9* texture; // a pointer to a texture
LPD3DXBUFFER bufMeshMaterial;
};
#include "StdAfx.h"
#include "StaticMesh.h"
StaticMesh::StaticMesh(LPDIRECT3DDEVICE9* device)
{
d3ddev=device;
}
StaticMesh::~StaticMesh(void)
{
}
void StaticMesh::Render(void)
{
LPDIRECT3DDEVICE9 device=*d3ddev;
for(DWORD i = 0; i < numMaterials; i++) // loop through each subset
{
device->SetMaterial(&material[i]); // set the material for the subset
device->SetTexture(0, texture[i]); // ...then set the texture
mesh->DrawSubset(i); // draw the subset
}
}
void StaticMesh::Load(LPCWSTR fileName)
{
LPDIRECT3DDEVICE9 device=*d3ddev;
D3DXLoadMeshFromX(fileName, // load this file
D3DXMESH_SYSTEMMEM, // load the mesh into system memory
device, // the Direct3D Device
NULL, // we aren't using adjacency
&bufMeshMaterial, // put the materials here
NULL, // we aren't using effect instances
&numMaterials, // the number of materials in this model
&mesh); // put the mesh here
// retrieve the pointer to the buffer containing the material information
D3DXMATERIAL* tempMaterials = (D3DXMATERIAL*)bufMeshMaterial->GetBufferPointer();
// create a new material buffer and texture for each material in the mesh
material = new D3DMATERIAL9[numMaterials];
texture = new LPDIRECT3DTEXTURE9[numMaterials];
for(DWORD i = 0; i < numMaterials; i++) // for each material...
{
// Copy the material
material[i] = tempMaterials[i].MatD3D;
// Set the ambient color for the material (D3DX does not do this)
material[i].Ambient = material[i].Diffuse;
// Create the texture if it exists - it may not
texture[i] = NULL;
if (tempMaterials[i].pTextureFilename)
{
D3DXCreateTextureFromFileA(device, tempMaterials[i].pTextureFilename,&texture[i]);
}
}
}
void StaticMesh::CleanUp(void)
{
mesh->Release();
}
The anination comes from a transformation matrix.
You either pass that directly to the device (if using fixed function) or to a shader/effect.
All meshes you draw after the matrix has been set will undergo the same transform.
So, if you want to have one mesh stay inanimate you have to change the transform before drawing the mesh.
Pseudo-code:
SetTransform( world* view * projection );
DrawMesh();
SetTransform( identity * view * projection );
DrawMesh();