How to find transformation for static mesh?
I'll be using it for my picking function.
I have tried this but it didn't work...
void StaticMesh::Render(void)
{
D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);
device->SetTransform(D3DTS_WORLD, &matWorld);
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
}
s = &matWorld; // THIS WOULD BE THE TRANSFORMATION FOR THE OBJECT
}
thanks in advance.
Edit 2:
Here is full class
#include "StdAfx.h"
#include "StaticMesh.h"
StaticMesh::StaticMesh(LPDIRECT3DDEVICE9* dev)
{
d3ddev=dev;
device = *d3ddev;
}
StaticMesh::~StaticMesh(void)
{
}
void StaticMesh::Render(void)
{
LPDIRECT3DDEVICE9 device=*d3ddev;
D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);
device->SetTransform(D3DTS_WORLD, &matWorld);
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
}
s = matWorld;
}
StaticMesh* StaticMesh::LoadXFile(LPCWSTR fileName, LPDIRECT3DDEVICE9* dev)
{
StaticMesh *obj = this;
obj = new StaticMesh(dev);
obj->Load(fileName);
return obj;
}
void StaticMesh::Load(LPCWSTR fileName)
{
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();
}
EDIT 3:
void GUIDialog::Picking(HWND hWnd, int status)
{
LPDIRECT3DDEVICE9 device = *d3ddev;
D3DXMATRIX matProj;
POINT pt;
D3DVIEWPORT9 vp;
D3DXMATRIX *matWorld=NULL;
D3DXMATRIX matView;
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
device->GetTransform(D3DTS_PROJECTION, &matProj);
device->GetViewport(&vp);
device->GetTransform(D3DTS_VIEW, &matView);
for(int i=0; (int)edit.size() > i; i++)
{
matWorld=&edit.at(i)->staticMesh->s;
// Use inverse of matrix
D3DXVECTOR3 rayPos((float)pt.x, (float)pt.y,0); // near-plane position
D3DXVECTOR3 rayDir((float)pt.x, (float)pt.y,1); // far-plane position
D3DXVec3Unproject(&rayPos,&rayPos,&vp,&matProj,&matView,matWorld);
D3DXVec3Unproject(&rayDir,&rayDir,&vp,&matProj,&matView,matWorld);
rayDir -= rayPos; // make a direction from the 2 positions
D3DXVec3Normalize(&rayDir,&rayDir);
if(FAILED(D3DXIntersect(edit.at(i)->staticMesh->mesh, &rayPos, &rayDir, &edit.at(i)->staticMesh->hasHit, NULL, NULL, NULL, &edit.at(i)->staticMesh->
distanceToCollision, NULL, NULL)))
{
PostQuitMessage(0);
};
if(edit.at(i)->staticMesh->hasHit!=0&&status==WM_LBUTTONUP)
{
if(status==WM_LBUTTONUP)
EventProc(HIT, *edit.at(i));
}
}
}
Well your code above is correct matWorld IS the transform of the object. If you wish to transform a ray into object local space (ie to the space prior to the matWorld transformation) then you simply need to multiply your world space ray by the inverse of matWorld ...
Related
I have this function:
void Texture::render(int x, int y, int w, int h, SDL_Renderer *&renderer, double angle, SDL_Point* center, SDL_RendererFlip flip)
{
// Set a destination value to -1 to keep the current value
if (x < 0) { x = rect.x; }
if (y < 0) { y = rect.y; }
if (w < 0) { w = rect.w; }
if (h < 0) { h = rect.h; }
// Create destination rectangle
SDL_Rect dstRect = { x, y, w, h };
// Render to screen
SDL_RenderCopyEx(renderer, texture, &rect, &dstRect, angle, center, flip);
}
It works. It creates an image of the correct size at the location I want. But I want to add a chunk of code where it resizes the texture itself to be the size given in the destRect.
So, anyone who finds this and reads the conversation I had with Nelfeal in the comments will see that I had a misunderstanding of how SDL_RenderCopyEx works. There's no need to resize the texture. If you need to do something like that, you can just use the dstRect when you copy it.
Actually, as far as I can find, there isn't a method to resize the actual texture itself. I'm sure one exists, but it's definitely not something people are commonly using. Which is usually a sign that it's a bad idea.
I've tweaked my code to try and simplify it, for anybody who's trying to do something similar to me:
void render(SDL_Renderer *&renderer, SDL_Rect *dstRect=NULL, SDL_Rect &srcRect=NULL, double angle=0.0, SDL_Point* center=NULL, SDL_RendererFlip flip=SDL_FLIP_NONE);
void Texture::render(SDL_Renderer *&renderer, SDL_Rect *dstRect, SDL_Rect *srcRect, double angle, SDL_Point* center, SDL_RendererFlip flip)
{
// Check to see if a destination was provided
bool check = false;
if (dstRect == NULL)
{
check = true;
dstRect = new SDL_Rect();
dstRect->x = 0;
dstRect->y = 0;
dstRect->w = SCREEN_WIDTH;
dstRect->h = SCREEN_HEIGHT;
}
// Check to see if the entire texture is being copied
if (srcRect == NULL) { srcRect = ▭ }
// Render to screen
SDL_RenderCopyEx(renderer, texture, srcRect, dstRect, angle, center, flip);
// Free dstRect
if (check) delete dstRect;}
And it looks like this when using the function:
bgTex.render(renderer);
blobTex.render(renderer, &blobDstRect);
Hello everyone I am messing around with some DLL injection stuff. Therefore I downloaded a simple Direct3D 9 sample application (it shows only a cube), which I want to manipulate.
I already managed to hook the EndScene and Reset function of this application, and now simply want to add more light to the current drawn frame.
Here is my EndScene function:
HRESULT WINAPI myEndScene(LPDIRECT3DDEVICE9 pDevice) {
lightHackTest2(pDevice);
auto ret = origEndScene(pDevice);
placeHooks();
return ret;
}
and here is my lightHackTest2 function:
void lightHackTest2(LPDIRECT3DDEVICE9 pDevice) {
pDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(100, 100, 100));
}
void lightHackTest(LPDIRECT3DDEVICE9 pDevice) {
D3DLIGHT9 light;
ZeroMemory(&light, sizeof(light));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse.r = 0.5f;
light.Diffuse.g = 0.5f;
light.Diffuse.b = 0.5f;
light.Diffuse.a = 1.0f;
light.Direction.x = -1.0f;
light.Direction.y = -0.5f;
light.Direction.z = -1.0f;
pDevice->SetLight(0, &light);
pDevice->LightEnable(0, TRUE);
}
These functions do actually get called (checked it with some MessageBoxes) but everything does stay the same in the scene.
Am I applying the light wrong?
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a function ( AddChild(child) ) which is meant to take an object as a parameter and adds this object as a child of the parent object which invokes the function.
Code creating the scene and invoking the function
Scene *scene = new Scene();
// Create a light.
Light *light = new PointLight(vec3(10.0f));
light->SetPosition(vec3(-5.0f, 3.0f, 2.0f));
scene->AddChild(light);
So as you can see here, the scene should be adding a light as its child
In the AddChild(child) function, the Object is checked to see if it already has a parent, if it does, it needs to delete this parent (as later on in a different class there is a function that checks all objects in the heap and if the parent object isnt deleted it is still in the heap and causes errors) and update it's parent to be the object which invoked the function. You can see the code which will cause this heap error below:
void Raytracer::SimpleAccelerator::AddObject(const SceneObject *object)
{
if (object->IsInstanceOf(SceneObjectType_PhysicalObject))
physicalObjects.push_back((PhysicalObject *)object);
if (object->IsInstanceOf(SceneObjectType_Light))
lights.push_back((Light *)object);
foreach_c (SceneObject *, child, object->GetChildren())
AddObject(*child);
}
But the main problem I'm having is, when I check to see if the child has a parent, and the parent isnt the object invoking the function, then I want to delete the parent of this child and update accordingly. The only problem is when I try to delete the child's parent Visual Studio crashes and I debugged the code and its on the line indicated below that causes the error.
bool SceneObject::AddChild(SceneObject *child)
{
if (child == NULL) {
return false;
}
else if (child->GetParent() != this) {
delete child->parent; <------------This is the line which breaks the code
child->parent = this;
children.push_back(child);
child->UpdateTransformations();
return true;
}
else {
this->children.push_back(child);
child->parent = this;
child->UpdateTransformations();
return true;
}
}
child and parent are both members of the class SceneObject which you can see below
Class SceneObject
{
private:
glm::mat4x4 globalTransformation;
public:
std::vector<SceneObject *> children;
SceneObject * parent;
SceneObject *GetParent() const;
const std::vector<SceneObject *> &GetChildren() const;
};
What would be the best method of deleting this member so that it and it's member variables are not present in the Heap during the Accelerator function?
MCVC
SceneObject.h
#ifndef RAYTRACER_SCENES_SCENEOBJECT_H
#define RAYTRACER_SCENES_SCENEOBJECT_H
#include <Raytracer/Scenes/SceneObjectType.h>
#include <vector>
namespace Raytracer
{
namespace Scenes
{
class SceneObject
{
private:
glm::mat4x4 globalTransformation;
void UpdateTransformations();
public:
std::vector<SceneObject *> children;
SceneObject * parent;
SceneObject();
virtual ~SceneObject();
bool AddChild(SceneObject *child);
const std::vector<SceneObject *> &GetChildren() const;
const glm::vec3 GetGlobalPosition() const;
const glm::mat4x4 &GetGlobalToLocal() const;
const glm::mat4x4 &GetGlobalTransformation() const;
SceneObject *GetParent() const;
};
}
}
#endif // RAYTRACER_SCENES_SCENEOBJECT_H
SceneObject.cpp
#define RAYTRACER_USE_FOREACH
#include <iostream>
#include <Raytracer/Raytracer.h>
using namespace glm;
using namespace Raytracer::Scenes;
SceneObject::SceneObject()
{
SetGlobalTransformation(mat4x4(1.0f));
}
SceneObject::~SceneObject()
{
}
bool SceneObject::AddChild(SceneObject *child)
{
if (child == NULL) {
return false;
}
else if (child->GetParent() != this) {
child->parent = nullptr;
child->parent = this;
this->children.push_back(child);
child->UpdateTransformations();
return true;
}
else {
this->children.push_back(child);
child->parent = this;
child->UpdateTransformations();
return true;
}
}
void delete_pointed_to(SceneObject* const ptr)
{
delete ptr;
}
const std::vector<SceneObject *> &SceneObject::GetChildren() const
{
// TODO: Geben Sie eine Liste der Kindobjekte dieses Objekts zurück.
static std::vector<SceneObject *> empty = this->children;
return empty;
}
const mat4x4 &SceneObject::GetGlobalTransformation() const
{
return globalTransformation;
}
SceneObject *SceneObject::GetParent() const
{
// TODO: Geben Sie eine Zeiger auf das Elternobjekt zurück oder NULL, falls dieses Objekt kein
// Elternobjekt hat.
if (this->parent == NULL) {
return NULL;
}
else {
return this->parent;
}
}
main.cpp
#include <stdio.h>
#include <vector>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <Raytracer/Raytracer.h>
using namespace glm;
using namespace Raytracer;
using namespace Raytracer::Scenes;
using namespace Raytracer::Objects;
/**
* Creates a transformation matrix for a rotation around the x axis.
*
* #param a The rotation angle in degrees
*/
mat4x4 RotationX(float a)
{
return rotate(mat4x4(1.0f), a, vec3(1.0f, 0.0f, 0.0f));
}
/**
* Creates a transformation matrix for a rotation around the y axis.
*
* #param a The rotation angle in degrees
*/
mat4x4 RotationY(float a)
{
return rotate(mat4x4(1.0f), a, vec3(0.0f, 1.0f, 0.0f));
}
/**
* Creates a transformation matrix for a rotation around the z axis.
*
* #param a The rotation angle in degrees
*/
mat4x4 RotationZ(float a)
{
return rotate(mat4x4(1.0f), a, vec3(0.0f, 0.0f, 1.0f));
}
bool CreateSphereLevels(Sphere *parent, float childRadiusRatio, int levels,
Material** materials, int firstMaterial, int materialCount)
{
// TODO: Implementieren Sie die Funktion nach Ihrer in Aufgabe 1 definierten Vorschrift.
// Der Methodenaufruf CreateSphereLevels(...) in dieser Form ist nur ein Vorschlag,
// Sie können ihn beliebig anpassen und eine andere Logik verwenden
return true;
}
/**
* Places a few spheres in the scene and adds some lights.
*
* #param scene The scene
*/
Scene *BuildScene(int depth, float aspect)
{
const int materialCount = 6;
vec3 colors[materialCount] =
{
vec3(1.0f, 0.0f, 0.0f),
vec3(1.0f, 1.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f),
vec3(0.0f, 1.0f, 1.0f),
vec3(0.0f, 0.0f, 1.0f),
vec3(1.0f, 0.0f, 1.0f)
};
Material *materials[materialCount];
for (int i = 0; i < materialCount; i++)
{
materials[i] = new Material();
if (materials[i] == NULL)
return NULL;
vec3 ambient = colors[i] * 0.01f;
materials[i]->SetAmbient(ambient);
materials[i]->SetDiffuse(colors[i]);
materials[i]->SetShininess(25.0f);
}
if (depth <= 0)
return NULL;
// Create the scene.
Scene *scene = new Scene();
if (scene == NULL)
return NULL;
// TODO: Erstellen Sie hier die Kugelwolke der Tiefe depth und fügen Sie sie in die Szene ein.
// Verwenden Sie die Materialien in materials zum Einfärben der Kugeln.
// Impelementieren Sie hierfür z.B. die Funktion CreateSphereLevels(...) (s.o.)
// Create a light.
Light *light = new PointLight(vec3(10.0f));
if (light == NULL)
{
delete scene;
return NULL;
}
light->SetPosition(vec3(-5.0f, 3.0f, 2.0f));
scene->AddChild(light);
// Create a camera.
Camera *camera = new Camera(vec3(-2.0f, 2.0f, 4.0f), vec3(0.0f, 0.0f, 0.0f),
vec3(0.0f, 1.0f, 0.0f), Camera::DefaultFov, aspect);
if (camera == NULL)
{
delete scene;
return NULL;
}
scene->AddChild(camera);
scene->SetActiveCamera(camera);
return scene;
}
/**
* Renders the scene and saves the result to a BMP file.
*
* #param fileName The name of the file
* #param width The image width
* #param height The image height
*/
void Render(const char *fileName, int width, int height)
{
if (fileName == NULL || width <= 0 || height <= 0)
return;
SimpleRenderer renderer;
renderer.SetAccelerator(new SimpleAccelerator());
renderer.SetIntegrator(new PhongIntegrator());
puts("Generiere Szene...");
Scene *scene = BuildScene(3, (float)width / height);
if (scene == NULL)
return;
puts("Rendere Bild...");
Image *image = renderer.Render(*scene, width, height);
if (image != NULL)
{
puts("Speichere Ergebnis...");
image->SaveBMP(fileName, 2.2f);
delete image;
}
delete scene;
}
/**
* The main program
*/
int main()
{
Render("image.bmp", 512, 512);
return 0;
}
Simple Accelerator
#include <limits>
#define RAYTRACER_USE_FOREACH
#include <Raytracer/Raytracer.h>
using namespace Raytracer;
using namespace Raytracer::Scenes;
bool SimpleAccelerator::HitTest(const Ray &ray, RayHit *hit) const
{
if (hit == NULL)
{
// Search for any intersection.
foreach_c (PhysicalObject *, object, physicalObjects)
{
Ray objectRay = ray.Transform((*object)->GetGlobalToLocal());
if ((*object)->HitTest(objectRay, NULL))
return true;
}
return false;
}
else
{
// Search for the closest intersection.
hit->Set(ray, 0, NULL);
foreach_c (PhysicalObject *, object, physicalObjects)
{
Ray objectRay = ray.Transform((*object)->GetGlobalToLocal());
RayHit objectHit;
if ((*object)->HitTest(objectRay, &objectHit) &&
(hit->GetObject() == NULL || objectHit.GetDistance() < hit->GetDistance()))
{
*hit = objectHit;
}
}
return (hit->GetObject() != NULL);
}
}
void Raytracer::SimpleAccelerator::SetScene(const Scenes::Scene *scene)
{
this->scene = scene;
physicalObjects.clear();
lights.clear();
if (scene == NULL)
return;
AddObject(scene);
}
void Raytracer::SimpleAccelerator::AddObject(const SceneObject *object)
{
if (object->IsInstanceOf(SceneObjectType_PhysicalObject))
physicalObjects.push_back((PhysicalObject *)object);
if (object->IsInstanceOf(SceneObjectType_Light))
lights.push_back((Light *)object);
foreach_c (SceneObject *, child, object->GetChildren())
AddObject(*child);
}
const std::vector<Light *> &SimpleAccelerator::GetLights() const
{
return lights;
}
Renderer.cpp
#include <Raytracer/Raytracer.h>
using namespace glm;
using namespace Raytracer;
using namespace Raytracer::Scenes;
Renderer::Renderer()
{
accelerator = NULL;
integrator = NULL;
}
Renderer::~Renderer()
{
delete accelerator;
delete integrator;
}
vec3 Renderer::RenderPixel(const Camera &camera, float x, float y) const
{
Ray ray;
camera.SpawnRay(x, y, ray);
return integrator->GetColor(ray, *accelerator);
}
IIntegrator *Renderer::GetIntegrator() const
{
return integrator;
}
void Renderer::SetIntegrator(IIntegrator *integrator)
{
delete this->integrator;
this->integrator = integrator;
}
Accelerator *Raytracer::Renderer::GetAccelerator() const
{
return accelerator;
}
void Raytracer::Renderer::SetAccelerator(Accelerator *accelerator)
{
delete this->accelerator;
this->accelerator = accelerator;
}
Image *Renderer::Render(const Scenes::Scene &scene, int width, int height)
{
Camera *camera = scene.GetActiveCamera();
if (camera == NULL || accelerator == NULL || integrator == NULL || width <= 0 || height <= 0)
return NULL;
Image *image = new Image(width, height);
if (image == NULL)
return NULL;
accelerator->SetScene(&scene);
RenderImage(*camera, image);
return image;
}
PhongIntegrator.cpp
Raytracer::PhongIntegrator::PhongIntegrator()
{
backgroundColor = vec3(0, 0, 0);
}
Renderer.h
#ifndef RAYTRACER_RENDERER_H
#define RAYTRACER_RENDERER_H
#include <glm.hpp>
#include <Raytracer/Image.h>
#include <Raytracer/Scenes/Camera.h>
#include <Raytracer/Scenes/Scene.h>
namespace Raytracer
{
/**
* Renders an image of a scene. The renderer object is not thread-safe.
*/
class Renderer
{
private:
Accelerator *accelerator;
IIntegrator *integrator;
protected:
/**
* Renders a single pixel.
*
* #param camera The camera
* #param x The normalized x coordinate of the pixel in the 0-1 range
* #param y The normalized y coordinate of the pixel in the 0-1 range
*
* #return The color of the pixel
*/
virtual glm::vec3 RenderPixel(const Scenes::Camera &camera, float x, float y) const;
/**
* Renders an image.
*
* #param camera The camera to use for the rendering
* #param image The image to be filled with rendered pixels
*/
virtual void RenderImage(const Scenes::Camera &camera, Image *image) const = 0;
public:
/**
* Constructs a new Renderer object.
*/
Renderer();
/**
* Destructs a Renderer object.
*/
virtual ~Renderer();
/**
* Retrieves the IIntegrator interface used for rendering.
*
* #return The IIntegrator interface used for rendering. The Renderer object owns this
* interface.
*/
IIntegrator *GetIntegrator() const;
/**
* Sets the IIntegrator interface used for rendering.
*
* #param integrator The IIntegrator interface used for rendering. The Renderer object
* takes ownership of this interface.
*/
void SetIntegrator(IIntegrator *integrator);
/**
* Retrieves the Accelerator object used for rendering.
*
* #return The Accelerator object used for rendering. The Renderer object owns the
* accelerator.
*/
Accelerator *GetAccelerator() const;
/**
* Sets the Accelerator object used for rendering.
*
* #param accelerator The Accelerator object used for rendering. The Renderer object takes
* ownership of the accelerator.
*/
void SetAccelerator(Accelerator *accelerator);
/**
* Renders an image of a scene.
*
* #param scene The scene
* #param width The image width in pixels
* #param height The image height in pixels
* #return The rendered image or NULL if the rendering failed
* #remarks You cannot use the same Renderer object to render different scenes
* simultaneously.
*/
Image *Render(const Scenes::Scene &scene, int width, int height);
};
}
#endif // RAYTRACER_RENDERER_H
SimpleAccelerator.h
#ifndef RAYTRACER_SIMPLEACCELERATOR_H
#define RAYTRACER_SIMPLEACCELERATOR_H
#include <vector>
#include <Raytracer/Accelerator.h>
// #include <Raytracer/Ray.h>
namespace Raytracer
{
class Ray;
class RayHit;
namespace Scenes
{
class Light;
class PhysicalObject;
class Scene;
class SceneObject;
}
/**
* A simple accelerator that uses brute force testing of all objects to find intersections.
*/
class SimpleAccelerator : public Accelerator
{
private:
/**
* A list of all physical objects in the scene
*/
std::vector<Scenes::PhysicalObject *> physicalObjects;
std::vector<Scenes::Light *> lights;
void AddObject(const Scenes::SceneObject *object);
public:
virtual const std::vector<Scenes::Light *> &GetLights() const;
virtual bool HitTest(const Ray &ray, RayHit *hit) const;
virtual void SetScene(const Scenes::Scene *scene);
};
}
#endif // RAYTRACER_SIMPLEACCELERATOR_H
Phong Integrator.h
#ifndef RAYTRACER_PHONGINTEGRATOR_H
#define RAYTRACER_PHONGINTEGRATOR_H
#include <glm.hpp>
#include <Raytracer/IIntegrator.h>
namespace Raytracer
{
namespace Scenes
{
class Scene;
}
/**
* Calculates the visible color seen by a ray using the Phong illumination model.
*/
class PhongIntegrator : public IIntegrator
{
private:
/**
* The background color seen by rays that exit the scene
*/
glm::vec3 backgroundColor;
public:
/**
* Constructs a new PhongIntegrator object.
*/
PhongIntegrator();
glm::vec3 GetColor(Ray &ray, const Accelerator &accelerator);
};
}
#endif // RAYTRACER_PHONGINTEGRATOR_H
Light.cpp
#include <Raytracer/Raytracer.h>
using namespace Raytracer::Scenes;
bool Light::IsInstanceOf(SceneObjectType type) const
{
return (type == SceneObjectType_Light);
}
Light.h
#ifndef RAYTRACER_SCENES_LIGHT_H
#define RAYTRACER_SCENES_LIGHT_H
#include <glm.hpp>
#include <Raytracer/Intersection.h>
#include <Raytracer/Scenes/SceneObject.h>
namespace Raytracer
{
struct Sample;
namespace Scenes
{
class Scene;
/**
* A light source
*/
class Light : public SceneObject
{
public:
/**
* Computes the direct contribution of this light in the illumination of a surface
* point.
*
* #param accelerator An accelerator object that can be used to trace secondary rays
* through the scene
* #param intersection An intersection of a view ray with an object
* #return A color value representing the direct contribution
*/
virtual glm::vec3 ComputeDirectContribution(const Accelerator *accelerator,
const Intersection &intersection) = 0;
virtual bool IsInstanceOf(SceneObjectType type) const;
};
}
}
#endif // RAYTRACER_SCENES_LIGHT_H
Scene.h
#ifndef RAYTRACER_SCENES_SCENE_H
#define RAYTRACER_SCENES_SCENE_H
#include <Raytracer/Scenes/SceneObject.h>
namespace Raytracer
{
class Ray;
namespace Scenes
{
class Camera;
class Scene : public SceneObject
{
private:
/**
* The camera that is to be used for rendering the scene
*/
Camera *activeCamera;
public:
/**
* Constructs a new Scene object.
*/
Scene();
/**
* Retrieves the active camera, i.e. the camera object to be used for rendering the
* scene.
*
* #return The active camera or NULL if there is no active camera
*/
Camera *GetActiveCamera() const;
virtual bool IsInstanceOf(SceneObjectType type) const;
/**
* Sets the active camera, i.e. the camera object to be used for rendering the scene.
*
* #param camera The new active camera or NULL to set no active camera
*/
void SetActiveCamera(Camera *camera);
};
}
}
#endif // RAYTRACER_SCENES_SCENE_H
Scene.cpp
#define RAYTRACER_USE_FOREACH
#include <Raytracer/Raytracer.h>
using namespace Raytracer;
using namespace Raytracer::Scenes;
Scene::Scene()
{
activeCamera = NULL;
}
Camera *Scene::GetActiveCamera() const
{
return activeCamera;
}
bool Scene::IsInstanceOf(SceneObjectType type) const
{
return (type == SceneObjectType_Scene);
}
void Scene::SetActiveCamera(Camera *camera)
{
this->activeCamera = camera;
}
You need to tell the old parent that this object is no longer its child, and that parent must then update its list of children to no longer contain a pointer to this object.
For example:
bool SceneObject::AddChild(SceneObject *child)
{
if (child == NULL) {
return false;
}
else if (child->GetParent() != this) {
child->parent->RemoveChild(child);
child->parent = this;
children.push_back(child);
child->UpdateTransformations();
return true;
}
else {
this->children.push_back(child);
child->parent = this;
child->UpdateTransformations();
return true;
}
}
and
bool SceneObject::RemoveChild(SomeObject* child)
{
auto iter = std::find(children.begin(), children.end(), child);
if (iter == children.end())
return false;
else
{
children.erase(iter);
return true;
}
}
If the parent is supposed to own the children, I would change the member to be
std::vector<std::unique_ptr<SceneObject>> children;
Then when the SceneObject falls out of scope, it will make sure to implicitly delete each of the children without any further effort on your part.
So you could change the AddChild method to be
bool SceneObject::AddChild(std::unique_ptr<SceneObject> child)
and to call it
scene->AddChild(std::make_unique<PointLight>(vec3(10.0f)));
Inside the AddChild method you can pass the pointer on such that this now owns that pointer
children.push_back(std::move(child));
I need a double buffer because i'm starting to notice tearing when I want to move my texture made tile map around the screen via mouse click.
I'm using SDL2 and this is a SDL2 specific question, check out my code that produces tearing, whats wrong?
//set up buffer and display
bufferTexture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_STREAMING,800,600);
displayTexture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET,800,600);
while(running)
{
handleEvents();
SDL_SetRenderTarget(renderer,bufferTexture); // everything goes into this buffer
SDL_RenderClear(renderer); // clear buffer before draw
gTileMovement.updateMapCoordinates();
for(int i = 0; i < MAP_ROWS; i++)//rows
{
for(int j = 0; j < MAP_COLUMNS; j++)//columns
{
x = (j * 100) - (i * 100);
y = ((i * 100) + (j * 100)) / 2;
drawTiles(i,j,x,y);
}
}
//move from buffer to display texture
memcpy(&displayTexture,&bufferTexture,sizeof((&bufferTexture)+1));
//change render target back to display texture
SDL_SetRenderTarget(renderer,displayTexture);
//show it all on screen
SDL_RenderPresent(renderer);
}
for all it matters here is my drawTiles function too, is this not conventional? :
void drawTiles(int i,int j,int x,int y)
{
//updates based on a mouse clicks xy coords
gTileMovement.updateMapCoordinates();
if(tileMap[i][j] == 1) // grass?
{
gSpriteSheetTexture.render(x+gTileMovement.getUpdatedX(),y+gTileMovement.getUpdatedY(),&gSpriteClips[1]);
}
if(tileMap[i][j] == 0) // wall?
{
gSpriteSheetTexture.render(x+gTileMovement.getUpdatedX(),y+gTileMovement.getUpdatedY(),&gSpriteClips[0]);
}
if(tileMap[i][j] == 2) // tree?
{
gSpriteSheetTexture.render(x+gTileMovement.getUpdatedX(),y+gTileMovement.getUpdatedY(),&gSpriteClips[2]);
}
}
Which followes into how I SDL_RenderCopy the tiles through a class. This copies the textures onto the current targeted renderer does it not? Which is the buffer texture if i'm not mistaken.
void LTexture::render(int x, int y, SDL_Rect * clip)
{
SDL_Rect renderQuad = {x, y, mWidth, mHeight};
if(clip != NULL)
{
renderQuad.w = clip->w;
renderQuad.h = clip->h;
}
SDL_RenderCopy(renderer, mTexture, clip, &renderQuad);
}
My dynamic body is not falling down after setting the world. It is not following the gravity. Even I apply force on the body it isn't work.
b2Vec2 gravity(0.0f, -9.8f);
b2World world(gravity);
//PineCone
class PineCone
{
private:
//Surface box
SDL_Rect box;
//Real position
float rX, rY;
//Velocity
float xVel, yVel;
//Physics world
b2World* world;
//Body
b2Body* pBodyPineCone;
public:
//Specify
void specify(int w, int h, SDL_Surface* source, SDL_Surface* dest, b2World* world);
//Input
void handle_input();
//Motion
void updatepos();
//void checkStanding(SDL_Rect env[], int N_SOLIDS);
//Render
void show();
};
void PineCone::specify(int w, int h, SDL_Surface* source, SDL_Surface* dest, b2World* world)
{
//Source
pPineCone = source;
//Destination
pScreen = dest;
// Define the dynamic pinecone. We set its position and call the body factory.
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
// Define a ball shape for our dynamic body.
b2CircleShape dynamicPineCone;
dynamicPineCone.m_p.Set(0, 0); //position, relative to body position
dynamicPineCone.m_radius = 0.5; //radius
// Define the dynamic body fixture.
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicPineCone;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
// Add the shape to the body.
bodyDef.position.Set(0, 20);
pBodyPineCone = world->CreateBody(&bodyDef);
pBodyPineCone->CreateFixture(&fixtureDef);
}
void PineCone::show()
{
int blit = SDL_BlitSurface( pPineCone, NULL, pScreen, &box );
if( blit < 0 )
{
exit(1);
}
}
I am not sure if I missed something in Main.
int main(int argc, char *argv[])
{
B2_NOT_USED(argc);
B2_NOT_USED(argv);
// Prepare for simulation. Typically we use a time step of 1/60 of a
// second (60Hz) and 10 iterations. This provides a high quality simulation
// in most game scenarios.
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;
// Start the timer
g_dwStartTicks = SDL_GetTicks();
init();
load_files();
//PineCone
PineCone myPineCone;
myPineCone.specify(g_iPineConeSize, g_iPineConeSize, pPineCone, pScreen, &world);
//
// The Main Game Loop
//
do
{
// Record the current time
g_dwStartTime = SDL_GetTicks();
//
// Handle they keyboard events here
//
while (SDL_PollEvent(&event) > 0)
{
if (event.type == SDL_QUIT)
{
// Quit event! (Window close, kill signal, etc.)
g_iLoopDone = TRUE;
}
}
world.Step(timeStep, velocityIterations, positionIterations);
myPineCone.handle_input();
if (g_bPlaying || g_bEnd)
{
//Show pinecone
myPineCone.show();
}
// Update the display
SDL_Flip(pScreen);
g_dwEndTime = SDL_GetTicks();
if (g_dwEndTime < g_dwStartTime + (1000 / 60))
{
SDL_Delay(g_dwStartTime + (1000 / 60) - g_dwEndTime);
}
}while (!g_iLoopDone);
//Clean Up
clean_up();
return 0;
}
I can think for example that the physical self is updating're not visualizing
what the Sprite (Image) not update the corresponding value of its physical body.
Try to give it a Box2D body position if the image does not move you do not
have to be the update of physics.
Try this:
void setL1b2SpritePosition(Point position)
{
pBodyPineCone->SetAwake (true);
pBodyPineCone->setPosition(position);
//update box2d
pBodyPineCone->SetTransform(
b2Vec2(position.x / PTM_RATIO, position.y/ PTM_RATIO),
_body->GetAngle());
}
void updatePhysics()
{
_world->Step(.1, 10, 10);
for (b2Body *b = _world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL)
{
Sprite *ballData = dynamic_cast<Sprite*> ((Sprite *) b->GetUserData());
ballData->setPosition(b->GetPosition().x * PTM_RATIO,
b->GetPosition().y * PTM_RATIO);
ballData->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));
}
}
}