Retrieve Object Position for Projection Shadow Calculation - c++

I am working on a class project and I need to implement shadows into our project, using OpenGL-esque coding. Our specific project is a spider running around a house. I need to make shadows appear on the floor below the spider (don't care about shadows for anything else).
The main question I need answered is this: When calculating shadows, How do I retrieve a point on the spider? In our notes, it says we have 3 givens in order to begin our initial calculations: 1) Plane (we know A,B,C,D) 2) Light source at (Lx,Ly,Lz) 3) Point q in space: Shadow caster
I do not understand how to retrieve "q". We load the spider mesh using "Mesh" and "SuperMesh" classes, and pass the mesh onto the vertex shader, but I do not understand how to reference points on the spider while on the CPU side.
I'm hesitant to post all of my code, mainly because this project uses a special library "llgl" that's based on OpenGL that our teacher made explicity for this class (makes debugging super easy, right?), and I'm not entirely sure what all would be needed in order to have my question properly answered. I'll include the Mesh and SuperMesh classes, as well as the declarations of loading the spider and passing it to the vertex shader as a matrix (which is more relevant). If you need more code, please request it. Hopefully it's more of a "theory" response than a syntax response, so I don't frustrate anyone trying to understand our code, haha.
Thank you for your time.
Main: (literally all of the excess code is cut out for simplicity)
...
SuperMesh* spider = new SuperMesh("spider/SmoothSpider.spec.mesh");
mat4 spiderR = rotationY(M_PI); // Rotation matrix for spider
vec3 spiderT(0,-2.5,-8.0); // Translation for spider
...
... (in draw)
//prog1 simply defines the txt files for the vertex and fragment shader
prog1->setUniform("worldMatrix", // sets world matrix for spider
spiderR * translation(vec4(spiderT.x,
spiderT.y,
spiderT.z,
0.0)));
spider->draw(prog1);
...
Mesh: (Hopefully not needed)
#ifndef MESH_H
#define MESH_H
#include "llgl.h"
#include <string>
#include <vector>
using namespace std;
using namespace llgl;
class Mesh{
public:
string fname;
bool initialized;
vector<uint8_t> vdata;
vector<uint8_t> idata;
vec4 color;
vec4 scolor;
int isize;
GLenum ienum;
unsigned vbuff,ibuff;
uint32_t ni;
TextureX* diffusetex;
TextureX* ramp;//used for cell shading, this is the "gradient"
Mesh(string fname);
void setup();
void draw(Program& prog);
void draw(Program* prog){ draw(*prog); }
};
#endif
SuperMesh:
#pragma once
#include "Mesh.h"
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
struct SuperMesh
{
vector<Mesh*> m;
string fname;
bool loaded;
SuperMesh(string specfile)
{
fname = specfile;
loaded = false;
}
void load()
{
if(loaded)
return;
ifstream in(fname.c_str());
if(!in.good())
throw runtime_error("Cannot load file " + fname);
string pfx;
unsigned slashidx;
slashidx = fname.find("/");
if(slashidx == string::npos)
slashidx = fname.find("\\");
if(slashidx != string::npos)
pfx = fname.substr(0, slashidx) + "/";
while(1)
{
string s;
getline(in, s);
if(in.fail())
break;
if(s.find("binarymesh ") == 0)
{
string fname = s.substr(11);
m.push_back(new Mesh(pfx + fname));
m.back()->setup();
}
}
loaded = true;
}
void draw(Program* p)
{
if(!loaded)
load();
for(unsigned i = 0; i < m.size(); ++i)
{
m[i]->draw(p);
}
}
};

Related

How to make a vector of sf::sound

I use the SFML library and more specifically the audio part of SFML. I would like to store multiple sf::Sound, so it occurred to me to make a class that handles sounds and to make a vector of sf::Sound.
However, when I try to play a sound, only the last element of the list of my vector can be played, the rest does not play.
I really can't understand why.
audio.hpp
#ifndef AUDIO_HPP
#define AUDIO_HPP
#pragma once
#include <SFML/Audio.hpp>
#include <vector>
#include <string>
enum {SELECTION_SOUND, DEAD_SOUND};
enum {MAIN_THEME_MUSIC, GAME_MUSIC, GAME_OVER_MUSIC};
class Audio
{
public:
Audio();
void setVolumeMusic(const float v);
void setVolumeSound(const float v);
float getVolumeSound() const;
float getVolumeMusic() const;
void playSound(const unsigned int soundExecute);
void stopMusic();
void deleteMusicTheme();
~Audio();
private:
bool m_musicThemeUse;
float m_volumeMusic, m_volumeSound;
std::vector <sf::SoundBuffer> m_buffer;
std::vector <bool> accessMusic, accessSound;
std::vector <sf::Sound> m_sound;
std::vector <sf::Music*> m_music;
std::vector <std::string> m_nameFileMusic, m_nameFileSound;
/*
* m_musicThemeUse : If this variable is equal to "true" then, the main menu music is deleted from memory.
* m_volumeMusic, m_volumeSound : Music/sound volume, it is fixed between 0.f and 100.f.
* m_buffer: vector containing the audio files of the sounds.
* accessMusic, accessSound : bool vector determining whether a music is available for playback or not. Useful when a file is deleted.
* m_sound: vector containing the audio files of the sounds.
* m_music: vector containing the audio files of the musics.
* m_nameFileMusic, m_nameFileSound : vector of string containing the path of the audio files.
*/
};
#endif
The constructor of the Audio class.
Audio::Audio() : m_nameFileMusic{ "data/mainTheme.ogg", "data/game.ogg", "data/gameOver.ogg" }, m_nameFileSound{"data/selectionSound.ogg", "data/dead.ogg" },
m_musicThemeUse(true), m_volumeMusic(0.f), m_volumeSound(100.f)
{
//Fill the values of accessMusic and accessSound to "true"
accessMusic.assign(std::size(m_nameFileMusic), true);
accessSound.assign(std::size(m_nameFileSound), true);
//Loads music files.
for (unsigned int i = 0; i < std::size(m_nameFileMusic); i++)
{
m_music.push_back(new sf::Music);
if (!m_music[i]->openFromFile(m_nameFileMusic[i]))
accessMusic[i] = false;
}
//Set the music files by setting the volume to them and activating repeat when the music files are finished.
setVolumeMusic(m_volumeMusic);
for(unsigned int i = 0; i < std::size(m_music); i++)
if(m_nameFileMusic[i] != "data/gameOver.ogg")
m_music[i]->setLoop(true);
//Load sound files.
const sf::SoundBuffer a;
const sf::Sound b;
for (unsigned int i = 0; i < std::size(m_nameFileSound); i++)
{
m_buffer.push_back(a);
m_sound.push_back(b);
if (!m_buffer[i].loadFromFile(m_nameFileSound[i]))
accessSound[i] = false;
else
m_sound[i].setBuffer(m_buffer[i]);
}
//Fix the volume of the sound files.
setVolumeSound(m_volumeSound);
//If the main menu music file is available then play the music file.
if(accessMusic[0])
m_music[0]->play();
m_sound[0].play();
}
When you copy SFML sound objects they stop playing. That's what happens when you relocate objects in an std::vector. I would recommend storing them in pointers as with
using SoundPtr = std::shared_ptr<sf::Sound>;
std::vector< SoundPtr > m_sound;
Yes I am coming back to tell you that I have solved the problem, in reality I had to separate the initialization phase of std::vector<sf::SoundBuffer> and the initialization phase of std::vector std::shared_ptr<sf::Sound>
Thank you everyone !
//Loads Buffer file
for (unsigned int i = 0; i < std::size(m_nameFileSound); i++)
{
m_buffer.push_back(sf::SoundBuffer{});
if (!m_buffer[i].loadFromFile(m_nameFileSound[i]))
accessSound[i] = false;
}
//Loads Sound file
for (unsigned int i = 0; i < std::size(m_buffer); i++)
{
m_sound.push_back(std::make_shared<sf::Sound>(sf::Sound{}));
if (accessSound[i])
m_sound[i]->setBuffer(m_buffer[i]);
}

Recursive function of tree with infinite childs. c++

I've created a virtual filesystem that i made to simulate a hard drive. The problem i am getting is that when i format this "drive" i need to go though every folder and sub-folders and delete "files" that I've created and then deleting the folders without getting memory leaks :)
I've been at this for a few hours now and I've tried to make recursive functions but it won't delete everything. It keeps getting stuck somewhere :(
Any ideas would make my week!! Thanks.
Here is code example of my folder.h and recursive function.
folder.h :
#ifndef FOLDER_H
#define FOLDER_H
#include <iostream>
#include <string>
#include "file.h"
using namespace std;
class folder
{
private:
int CAP = 10;
int nrOfChildFolders;
int nrOfFiles;
string folderName;
folder * parentFolder;
folder * childFolder[10];
file * fileArray[10];
public:
folder();
folder(string folderName, folder * parent);
~folder();
void addFolder(string folderName);
void addFile(string fileName, int nr);
string getFolderAndFiles()const;
string getFolderName()const;
int getFileNr(string fileName)const;
void reset();
folder * getFolder(string name)const;
folder * getParentFolder()const;
void deleteFile(string name, int nr);
folder * getChildFolder(int pos);
int getNrOfChildFolders()const;
/* data */
};
#endif
Recursive function :
void FileSystem::recursiveFolderSwitcher(folder * newCurrentFolder)
{
int folders = newCurrentFolder->getNrOfChildFolders();
if (newCurrentFolder->getNrOfChildFolders() != 0)
{
for (int i = 0; i < folders; i++)
{
newCurrentFolder = newCurrentFolder->getChildFolder(i);
recursiveFolderSwitcher(newCurrentFolder);
}
}
newCurrentFolder->reset();
}
Thanks <3
You are reassigning newCurrentFolder in your for-loop.
newCurrentFolder = newCurrentFolder->getChildFolder(i);
This makes the final
newCurrentFolder->reset()
reset the last child instead.
Use
folder* child = newCurrentFolder->getChildFolder(i);
recursiveFolderSwitcher(child);
instead.
Also
if (newCurrentFolder->getNrOfChildFolders() != 0)
is unnecessary, the for-statement will take care of this for you.

OpenGL showing blank screen. Maybe due to shaders?

My OpenGL ES application isn't working. I'm using SDL for windowing management, and it holds the context. After looking around, I noticed that the vertex shader and the fragment shader showed up as 0 on the debugger. Even the program was 0. Could this be a reason? I followed my shader compiling and linking code to a template that was previously made.
If it is, what is wrong? Here is the code:
GLuint ShaderHelper::compileShader(GLenum type, std::string fileName) {
std::string fileContents;
std::ifstream fin;
std::string path;
// Getting the necessary path...
// These are abstractions for getting file contents
// from the main bundle.
if (type == GL_VERTEX_SHADER) {
FileOpener opener;
path = opener.retriveFileFromBundle(fileName, "vsh");
} else if (type == GL_FRAGMENT_SHADER) {
FileOpener opener;
path = opener.retriveFileFromBundle(fileName, "fsh");
} else {
std::cout << "ERROR: Invalid shader type at filename " << fileName << std::endl;
exit(1);
}
fin.open(path);
if (!fin.is_open()) {
std::cout << "ERROR: Failed to open file " << fileName << std::endl;
exit(1);
}
// Retrieving the string from the file...
while (!fin.eof()) {
char CLine[255];
fin.getline(CLine, 255);
std::string line = CLine;
fileContents = fileContents + line;
fileContents = fileContents + " \n";
}
fin.close();
// I'm creating these variables because a pointer is needed for
// glShaderSource
GLuint shaderHandle = glCreateShader(type);
const GLint shaderStringLength = (GLint)fileContents.size();
const GLchar *shaderCString = fileContents.c_str();
glShaderSource(shaderHandle, 1, &shaderCString, &shaderStringLength);
glCompileShader(shaderHandle);
return shaderHandle;
}
void ShaderHelper::linkProgram(std::vector<GLuint *> shaderArray) {
program = glCreateProgram();
for (int i = 0; i < shaderArray.size(); i++) {
glAttachShader(program, *shaderArray[i]);
}
glLinkProgram(program);
}
void ShaderHelper::addUniform(uniform_t uniform) {
std::string name = uniform.name;
uniforms[name] = uniform;
// With that step done, we need to assign the location...
uniforms[name].location = glGetUniformLocation(program, uniforms[name].name.c_str());
}
EDIT: After suggestions, I ran my code through glError(). I fixed an error, but I still got a blank screen. I'm no longer getting 0 as my shader values. I set glClearColor to a white image, and it's just appearing pure white. I adjusted numbers in the MV matrix and projection matrix, but there's still nothing at all. I disabled face culling, but still nothing. Also, shaders are compiling and linking fine. So now what?
The dreaded blank screen can be caused by a variety of problems:
Your context is not created correctly or you're not presenting your scene properly. Does changing your clear color to something else than black show anything?
Your transformation matrix is wrong. How are you setting up the position of the "camera"? Are you using something like GLM to set up a matrix? If so, have a look at glm::perspective() and glm:::lookAt(). Make sure you're passing the matrix to the shader and that you're using it to set gl_Position in your vertex shader.
The geometry you're trying to display is facing away from the viewer. Try glDisable(GL_CULL_FACE). If it works, reverse the order of your vertices.
An OpenGL call is failing somewhere. Make sure you check glGetError() after every call. I usually have something like the following:
struct gl_checker
{
~gl_checker()
{
const auto e = glGetError();
assert(e == GL_NO_ERROR);
}
};
template <class F>
inline auto gl_call(F f) -> decltype(f())
{
gl_checker gc;
return f();
}
which can be used like this:
gl_call([]{ glDisable(GL_CULL_FACE); });
Your shaders fail to compile or link. Have a look at glGetShaderiv() with GL_COMPILE_STATUS and glGetProgramiv() with GL_LINK_STATUS. If they report an error, have a look at glGetShaderInfoLog() and glGetProgramInfoLog().
As for the partial code you provided, I see nothing strictly wrong with it. Providing the shaders and a smaller, complete program might help with finding the problem.

Using boost wave

I'm trying to get my head around boost wave, and so far, I'm not having much luck.
I tried the sample code from the site. It is below:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
///////////////////////////////////////////////////////////////////////////////
// Include Wave itself
#include <boost/wave.hpp>
///////////////////////////////////////////////////////////////////////////////
// Include the lexer stuff
#include <boost/wave/cpplexer/cpp_lex_token.hpp> // token class
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer class
int main () {
// The following preprocesses a given input file.
// Open the file and read it into a string variable
std::ifstream instream("lex_infile");
std::string input(
std::istreambuf_iterator<char>(instream.rdbuf()),
std::istreambuf_iterator<char>());
// The template boost::wave::cpplexer::lex_token<> is the
// token type to be used by the Wave library.
// This token type is one of the central types throughout
// the library, because it is a template parameter to some
// of the public classes and templates and it is returned
// from the iterators.
// The template boost::wave::cpplexer::lex_iterator<> is
// the lexer iterator to use as the token source for the
// preprocessing engine. In this case this is parametrized
// with the token type.
typedef boost::wave::cpplexer::lex_iterator<
boost::wave::cpplexer::lex_token<> >
lex_iterator_type;
typedef boost::wave::context<
std::string::iterator, lex_iterator_type>
context_type;
context_type ctx(input.begin(), input.end(), "lex_infile");
// At this point you may want to set the parameters of the
// preprocessing as include paths and/or predefined macros.
//ctx.add_include_path("...");
//ctx.add_macro_definition(...);
// Get the preprocessor iterators and use them to generate
// the token sequence.
context_type::iterator_type first = ctx.begin();
context_type::iterator_type last = ctx.end();
std::cout << "HERE" << std::endl;
// The input stream is preprocessed for you during iteration
// over [first, last)
while (first != last) {
std::cout << (*first).get_value() << std::endl;
++first;
}
}
It compiles ok, but when I feed a file into it, I get the following error:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl >'
what(): boost::wave::preprocess_exception
Aborted
The code I'm trying to 'preprocess' is in a file called lex_infile, with the following contents:
#include <oglre>
#include <light>
#include <material>
in vec3 in_Position;
in vec2 in_Texture;
in vec3 in_Normal;
out vec2 textureCoord;
out vec4 pass_Color;
void main() {
gl_Position = pvmMatrix * vec4(in_Position, 1.0);
textureCoord = in_Texture;
vec3 normalDirection = normalize(normalMatrix * in_Normal);
vec3 lightDirection = normalize(vec3(lightSources[0].direction));
vec3 diffuseReflection = vec3(lightSources[0].diffuse) * vec3(mymaterial.diffuse) * max(0.0, dot(normalDirection, lightDirection));
/*
float bug = 0.0;
bvec3 result = equal( diffuseReflection, vec3(0.0, 0.0, 0.0) );
if(result[0]) bug = 1.0;
diffuseReflection.x += bug;
*/
pass_Color = vec4(diffuseReflection, 1.0);
}
I imagine I need to define the include locations....how would i even do that?
Sorry if this is simple stuff, I'm just a little lost.
Figured it out.
I need to extend the class public wave::context_policies::default_preprocessing_hooks, and then override the method found_unknown_directive.
Once that was done, I needed to pass my new preprocessing hooks class into typedef boost::wave::context as a template parameter.
It looks like this:
typedef boost::wave::context<
std::string::iterator,
lex_iterator_type,
load_file_to_string,
custom_directives_hooks
> context_type;
and
class custom_directives_hooks
: public wave::context_policies::default_preprocessing_hooks
{
public:
template <typename ContextT, typename ContainerT>
bool
found_unknown_directive(ContextT const& ctx, ContainerT const& line,
ContainerT& pending)
{
typedef typename ContainerT::const_iterator iterator_type;
iterator_type it = line.begin();
wave::token_id id = wave::util::impl::skip_whitespace(it, line.end());
if (id != wave::T_IDENTIFIER)
return false; // nothing we could do
if (it->get_value() == "version" || it->get_value() == "extension") {
// Handle #version and #extension directives
std::copy(line.begin(), line.end(), std::back_inserter(pending));
return true;
}
if (it->get_value() == "type") {
// Handle type directive
return true;
}
// Unknown directive
return false;
}
};
Hope that helps anyone else having this problem.

Issue with setting speed to DifferentialWheels in Webots C++

Small community here, but hopefully somebody sees this. I'm attempting to do a pure C++ implementation of a Webots simulation for an E-puck. The C++ documentation is sorely lacking, and I can't seem to find a resolution for this issue (the C implementation is stellar, but all the function calls were changed for C++).
Essentially, I'm just trying to get a simple application up and running...I want to make the E-puck move forward. I will post the entirety of my code below...all I'm doing is instantiating a Robot entity, printing out all the IR sensor values, and attempting to move it forward.
The issue is that it does not move. I'd think that there would be some call to link the DifferentialWheel object to the E-puck (similar to the camera = getCamera("camera") call).
If I comment out my call to setSpeed, the program works perfectly (doesn't move, but prints values). If I leave it in, the simulation freezes up after a single step, once it gets to that call. I'm not exactly sure what I'm doing wrong, to be honest.
// webots
#include <webots/Robot.hpp>
#include <webots/Camera.hpp>
#include <webots/DistanceSensor.hpp>
#include <webots/DifferentialWheels.hpp>
#include <webots/LED.hpp>
// standard
#include <iostream>
using namespace webots;
#define TIME_STEP 16
class MyRobot : public Robot
{
private:
Camera *camera;
DistanceSensor *distanceSensors[8];
LED *leds[8];
DifferentialWheels *diffWheels;
public:
MyRobot() : Robot()
{
// camera
camera = getCamera("camera");
// sensors
distanceSensors[0] = getDistanceSensor("ps0");
distanceSensors[1] = getDistanceSensor("ps1");
distanceSensors[2] = getDistanceSensor("ps2");
distanceSensors[3] = getDistanceSensor("ps3");
distanceSensors[4] = getDistanceSensor("ps4");
distanceSensors[5] = getDistanceSensor("ps5");
distanceSensors[6] = getDistanceSensor("ps6");
distanceSensors[7] = getDistanceSensor("ps7");
for (unsigned int i = 0; i < 8; ++i)
distanceSensors[i]->enable(TIME_STEP);
// leds
leds[0] = getLED("led0");
leds[1] = getLED("led1");
leds[2] = getLED("led2");
leds[3] = getLED("led3");
leds[4] = getLED("led4");
leds[5] = getLED("led5");
leds[6] = getLED("led6");
leds[7] = getLED("led7");
}
virtual ~MyRobot()
{
// cleanup
}
void run()
{
double speed[2] = {20.0, 0.0};
// main loop
while (step(TIME_STEP) != -1)
{
// read sensor values
for (unsigned int i = 0; i < 8; ++i)
std::cout << " [" << distanceSensors[i]->getValue() << "]";
std::cout << std::endl;
// process data
// send actuator commands
// this call kills the simulation
// diffWheels->setSpeed(1000, 1000);
}
}
};
int main(int argc, char* argv[])
{
MyRobot *robot = new MyRobot();
robot->run();
delete robot;
return 0;
}
Now, if this were the C implementation, I would call wb_differential_wheels_set_speed(1000, 1000); However, that call isn't available in the C++ header files.
The problem causing the freeze is due to the use of the uninitialized variable diffWheels.
DifferentialWheels (as well as Robot and Supervisor) doesn't need to be initialized.
You have to change the base class of your MyRobot class to DifferentialWheels
class MyRobot : public DifferentialWheels
and then simply call
setSpeed(1000, 1000)
and not
diffWheels->setSpeed(1000, 1000)
It doesn't seem as though you've initialized diffWheels, so I would imagine you're getting a segfault from dereferencing a garbage pointer. Try putting
diffWheels = new DifferentialWheels;
in the constructor of MyRobot.