Open3D - C++: how to animate 3D point cloud - c++

In Open3D, with C++, how to animate 3D point cloud: same question that this one in python Open3d: How to update point cloud during window running? but can't get this to work.
The following code (inspired from github repo example examples/cpp/PointCloud.cpp) compile, run (the viewer and point appears), but animation is not rendered
>> cat ../examples/cpp/PtCloud.cpp
#include <Eigen/Dense>
#include <iostream>
#include <memory>
#include "open3d/Open3D.h"
#include <unistd.h> // sleep
using namespace open3d;
void PrintPointCloud(const std::shared_ptr<geometry::PointCloud> &pointcloud) {
using namespace open3d;
bool pointcloud_has_normal = pointcloud->HasNormals();
utility::LogInfo("Pointcloud has %d points.",
(int)pointcloud->points_.size());
Eigen::Vector3d min_bound = pointcloud->GetMinBound();
Eigen::Vector3d max_bound = pointcloud->GetMaxBound();
utility::LogInfo(
"Bounding box is: ({:.4f}, {:.4f}, {:.4f}) - ({:.4f}, {:.4f}, "
"{:.4f})",
min_bound(0), min_bound(1), min_bound(2), max_bound(0),
max_bound(1), max_bound(2));
for (size_t i = 0; i < pointcloud->points_.size(); i++) {
if (pointcloud_has_normal) {
const Eigen::Vector3d &point = pointcloud->points_[i];
const Eigen::Vector3d &normal = pointcloud->normals_[i];
utility::LogInfo("{:.6f} {:.6f} {:.6f} {:.6f} {:.6f} {:.6f}",
point(0), point(1), point(2), normal(0), normal(1),
normal(2));
} else {
const Eigen::Vector3d &point = pointcloud->points_[i];
utility::LogInfo("{:.6f} {:.6f} {:.6f}", point(0), point(1),
point(2));
}
}
utility::LogInfo("End of the list.");
}
std::shared_ptr<geometry::PointCloud> pointcloud(new geometry::PointCloud);
bool AnimatePointCloud(visualization::Visualizer * visualizer) {
if (!visualizer) return false;
for (int i = 0; i < 10; i++) {
sleep(2);
pointcloud->points_.push_back(Eigen::Vector3d(0.0, 0.0, i+1.0));
pointcloud->points_.push_back(Eigen::Vector3d(1.0, 0.0, i+1.0));
pointcloud->points_.push_back(Eigen::Vector3d(0.0, 1.0, i+1.0));
PrintPointCloud(pointcloud);
visualizer->UpdateGeometry(pointcloud);
visualizer->PollEvents();
visualizer->UpdateRender();
visualizer->Run();
}
return true;
}
int main(int argc, char *argv[]) {
// 1. test basic pointcloud functions.
pointcloud->points_.push_back(Eigen::Vector3d(0.0, 0.0, 0.0));
pointcloud->points_.push_back(Eigen::Vector3d(1.0, 0.0, 0.0));
pointcloud->points_.push_back(Eigen::Vector3d(0.0, 1.0, 0.0));
PrintPointCloud(pointcloud);
// 2. test pointcloud visualization
visualization::Visualizer visualizer;
visualizer.CreateVisualizerWindow("Open3D", 1600, 900);
visualizer.AddGeometry(pointcloud);
visualizer.RegisterAnimationCallback(AnimatePointCloud);
visualizer.Run();
visualizer.DestroyVisualizerWindow();
return 0;
}
The code is supposed to animate points that stack up in animated way: the viewer seems to freeze. Didn't find any C++ example. What's wrong?

Related

Physics update in cocos2d-x v3

I'm developing a game, using cocos2d-x 3.1.1 on Linux, that is going to have physics support.
I'm still at at the basics, but I'm already having many headaches.
The posted code is essentially what i have done so far, a ball influenced by gravity and a random velocity vector.
The problem is the simulation seems to never start, even if the sprite is rendered correctly. The ball does not move, in fact the position of the body is always the same (i log it). I tried to debug the application and to move blocks of code in other functions, without results.
Menu.cpp
#include "Menu.h"
#include "cocos2d.h"
#include <time.h>
#include <math.h>
#define COCOS2D_DEBUG 1
USING_NS_CC;
ScenaMenu *ScenaMenu::createWithPhysics() {
ScenaMenu *ret = new ScenaMenu();
if (ret && ret->initWithPhysics()) {
ret->autorelease();
return ret;
}
else {
CC_SAFE_DELETE(ret);
return nullptr;
}
}
ScenaMenu::ScenaMenu() {
frameSize = Director::getInstance()->getOpenGLView()->getFrameSize();
}
ScenaMenu::~ScenaMenu() {}
void ScenaMenu::onEnter() {
Scene::onEnter();
fisica = this->getPhysicsWorld();
fisica->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
fisica->setGravity(Vec2(0, -10.0f));
Texture2D::TexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
LayerColor *layerMenu = LayerColor::create(Color4B(255, 255, 255, 255));
layerMenu->setContentSize(frameSize);
textureSfera = Director::getInstance()->getTextureCache()->addImage("sfera2.png");
textureSfera->setTexParameters(&texParams);
textureSfera->generateMipmap();
float angolo;
srand(time(NULL));
PhysicsMaterial mat = PhysicsMaterial(1, 1, 0);
PhysicsBody *bodyFisica;
bodyFisica = PhysicsBody::createCircle(layerMenu->getContentSize().width * 0.1, mat, Vec2::ZERO);
angolo = (rand() % 628) / 100.0f;
bodyFisica->setVelocity(Vec2(10 * cos(angolo), 10 * sin(angolo)));
spriteSfera = Sprite::createWithTexture(textureSfera);
spriteSfera->setScale((layerMenu->getContentSize().width * 0.33) / spriteSfera->getContentSize().width);
spriteSfera->setPosition(layerMenu->getContentSize().width * 0.5, layerMenu->getContentSize().height * 0.5);
spriteSfera->setPhysicsBody(bodyFisica);
this->addChild(layerMenu);
layerMenu->addChild(spriteSfera);
}
void ScenaMenu::update(float dt) {
log("POS %f", spriteSfera->getPhysicsBody()->getPosition().y);
}
AppDelegate.cpp
#include "AppDelegate.h"
#include "Menu.h"
USING_NS_CC;
AppDelegate::AppDelegate() {
}
AppDelegate::~AppDelegate()
{
}
bool AppDelegate::applicationDidFinishLaunching() {
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if(!glview) {
glview = GLView::create("Test");
director->setOpenGLView(glview);
}
Size frameSize = Size(540, 960);
cocos2d::Size designResolutionSize = Size(1080, 1920);
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::FIXED_WIDTH);
glview->setFrameSize(frameSize.width, frameSize.height);
director->setDisplayStats(true);
director->setAnimationInterval(1.0 / 60);
ScenaMenu *scenaMenu = ScenaMenu::createWithPhysics();
director->runWithScene(scenaMenu);
return true;
}
// This function will be called when the app is inactive. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground() {
Director::getInstance()->stopAnimation();
// if you use SimpleAudioEngine, it must be pause
// SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
}
// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
Director::getInstance()->startAnimation();
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
}

Qwt - replot does not clear current plot

This is my first question here and I believe that I havent seen anyone else asking for this specific problem but what I'm currently dealing with is a qwt plot that doesn't want to replot.
What I want to do: Call the replot() method to clear my current plot.
My problem: When calling replot() does not clear my current plot and my plots are drawn on top of eachother.
Here is a link to an image of my problem
As can be seen in the image, the new curves are drawn on top of the existing ones and this is what I want to solve.
Here is some of my code: (let me know if I missed some parts)
plot.cpp
#include "plot.h"
#include <qwt_plot.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_directpainter.h>
#include <qwt_curve_fitter.h>
#include <qwt_painter.h>
class CurveData: public QwtArraySeriesData<QPointF>
{
public:
CurveData()
{
}
virtual QRectF boundingRect() const
{
if ( d_boundingRect.width() < 0.0 )
d_boundingRect = qwtBoundingRect( *this );
return d_boundingRect;
}
inline void append( const QPointF &point )
{
d_samples += point;
}
void clear()
{
d_samples.clear();
d_samples.squeeze();
d_boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 );
}
};
Plot::Plot( QWidget *parent ):
QwtPlot( parent )
{
d_directPainter = new QwtPlotDirectPainter(this);
setAutoReplot(false);
setAxisScale(QwtPlot::yLeft, 0.014,0.016);
setAxisScale(QwtPlot::xBottom, 0, 1000);
d_curve = new QwtPlotCurve();
d_curve->setData(new CurveData());
d_curve->attach(this);
}
void Plot::AppendPoint(const QPointF &point)
{
CurveData *data = static_cast<CurveData *>(d_curve->data());
data->append(point);
}
void Plot::DrawCurveSegment()
{
CurveData *data = static_cast<CurveData *>(d_curve->data());
d_directPainter->drawSeries(d_curve, data->size()-11, data->size()-1);
}
void Plot::ClearPlot()
{
CurveData *data = static_cast<CurveData *>(d_curve->data());
data->clear();
QwtPlot::replot();
}
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent):
QWidget( parent )
{
d_plot = new Plot();
counter = 0;
loopCounter = 0;
// ... //
}
void MainWindow::timerEvent(QTimerEvent *) {
if (counter>0 && counter%1000==0)
{
d_plot->ClearPlot();
d_plot->replot();
loopCounter++;
qDebug()<<"clear!";
}
for (int ii=0; ii<10;ii++)
{
double y = someArray[counter];
double x = (double)counter-((double)loopCounter*1000);
counter++;
d_plot->AppendPoint(QPointF(x,y));
}
d_plot->DrawCurveSegment();
}
Would very much appreciate if someone can see what I'm doing wrong.
Best regards!
I solved the problem by changing the clearPlot method to the following:
void Plot::ClearPlot()
{
CurveData *data = static_cast<CurveData *>(d_curve->data());
data->clear();
QwtPlot::replot();
QwtPlot::repaint();
}
You can also do this:
QwtPlot::detachItems(QwtPlotItem::Rtti_PlotItem, true);

Change colour of an edge

I have an graph which consists of edges and vertices. When the clicks an edge in the graph, the edge is supposed to change colour. I have included some code samples to demonstrate my problem.
To draw the initial graph;
#include "StdAfx.h"
#include <vtkSmartPointer.h>
#include <vtkCallbackCommand.h>
#include <vtkAnnotationLink.h>
#include <vtkRenderedGraphRepresentation.h>
#include <vtkRenderer.h>
#include <vtkDoubleArray.h>
#include <vtkSelectionNode.h>
#include <vtkIdTypeArray.h>
#include <vtkSelection.h>
#include <vtkRenderWindow.h>
#include <vtkUnsignedCharArray.h>
#include <vtkObjectFactory.h>
#include <vtkGraphLayoutStrategy.h>
#include <vtkGraphLayoutView.h>
#include <vtkGraphWriter.h>
#include <vtkMutableUndirectedGraph.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkIntArray.h>
#include <vtkLookupTable.h>
#include <vtkDataSetAttributes.h>
#include <vtkViewTheme.h>
void SelectionCallbackFunction(vtkObject* caller, long unsigned int eventId, void* clientData, void* callData);
vtkSmartPointer<vtkMutableUndirectedGraph> g;
int main(int, char *[])
{
g =
vtkSmartPointer<vtkMutableUndirectedGraph>::New();
vtkIdType v1 = g->AddVertex();
vtkIdType v2 = g->AddVertex();
g->AddEdge(v1, v2);
g->AddEdge(v1, v2);
vtkSmartPointer<vtkCallbackCommand> selectionCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
selectionCallback->SetCallback (SelectionCallbackFunction);
// Create the color array
vtkSmartPointer<vtkIntArray> edgeColors =
vtkSmartPointer<vtkIntArray>::New();
edgeColors->SetNumberOfComponents(1);
edgeColors->SetName("Color");
vtkSmartPointer<vtkLookupTable> lookupTable =
vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetNumberOfTableValues(1);
lookupTable->SetTableValue(0, 1.0, 0.0, 0.0); // red
lookupTable->Build();
edgeColors->InsertNextValue(0);
// Add the color array to the graph
g->GetEdgeData()->AddArray(edgeColors);
vtkSmartPointer<vtkGraphLayoutView> view =
vtkSmartPointer<vtkGraphLayoutView>::New();
view->SetEdgeColorArrayName("Color");
view->ColorEdgesOn();
vtkSmartPointer<vtkViewTheme> theme =
vtkSmartPointer<vtkViewTheme>::New();
theme->SetCellLookupTable(lookupTable);
view->ApplyViewTheme(theme);
view->AddRepresentationFromInput(g);
view->SetLayoutStrategy("Simple 2D");
view->GetRepresentation()->GetAnnotationLink()->AddObserver("AnnotationChangedEvent", selectionCallback);
view->ResetCamera();
view->Render();
view->GetInteractor()->Start();
return EXIT_SUCCESS;
}
For the mouse click function I have used the below code;
vtkAnnotationLink* annotationLink =
static_cast<vtkAnnotationLink*>(caller);
vtkSelection* selection = annotationLink->GetCurrentSelection();
vtkSelectionNode* edges;
if(selection->GetNode(0)->GetFieldType() == vtkSelectionNode::EDGE)
{
edges = selection->GetNode(0);
}
if(selection->GetNode(1)->GetFieldType() == vtkSelectionNode::EDGE)
{
edges = selection->GetNode(1);
}
vtkIdTypeArray* edgeList = vtkIdTypeArray::SafeDownCast(edges->GetSelectionList());
for(vtkIdType i = 0; i < edgeList->GetNumberOfTuples(); i++)
{
//Change colour of the edge
}
My problem is that I cannot change the colour of the edge dynamically. I would be very grateful for any help regarding the matter.
The below code worked for me. First when I create the graph I set the colour of each and every edge,
edgeColors = vtkSmartPointer<vtkIntArray>::New();
edgeColors->SetNumberOfComponents(1);
edgeColors->SetName("Color");
vtkSmartPointer<vtkLookupTable> lookupTable =
vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetNumberOfTableValues(2);
lookupTable->SetTableValue(0, 0.5, 1.0, 0.5); // green
lookupTable->SetTableValue(1, 0.0, 1.0, 0.0); // white
lookupTable->Build();
//For each edge id insert colour
for(int i = 0;i<=graph->GetNumberOfEdges();i++)
edgeColors->InsertValue(i,0);
// Add the color array to the graph
graph->GetEdgeData()->AddArray(edgeColors);
Then in my mouse click function I get the vtkIdType of the clicked edge and set the colour of it.
vtkIdType edge = edgeList->GetValue(0);
edgeColors->InsertValue(edge.Id,1);//set colour of edge
graphLayoutView->GetInteractor()->Render();

Using a custom C++ extension with python

I have a problem with this code:
#include "PolyVoxCore/MaterialDensityPair.h"
#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h"
#include "PolyVoxCore/SurfaceMesh.h"
#include "PolyVoxCore/SimpleVolume.h"
#include "geomVertexData.h"
#include "geomVertexWriter.h"
#include "geomTriangles.h"
#include "py_panda.h"
#include "pandaNode.h"
#include "geomNode.h"
//Use the PolyVox namespace
using namespace PolyVox;
using namespace std;
static void createSphereInVolume(SimpleVolume<MaterialDensityPair44>& volData, float fRadius)
{
//This vector hold the position of the center of the volume
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
//This three-level for loop iterates over every voxel in the volume
for (int z = 0; z < volData.getWidth(); z++)
{
for (int y = 0; y < volData.getHeight(); y++)
{
for (int x = 0; x < volData.getDepth(); x++)
{
//Store our current position as a vector...
Vector3DFloat v3dCurrentPos(x,y,z);
//And compute how far the current position is from the center of the volume
float fDistToCenter = (v3dCurrentPos - v3dVolCenter).length();
uint8_t uDensity = 0;
uint8_t uMaterial = 0;
//If the current voxel is less than 'radius' units from the center then we make it solid.
if(fDistToCenter <= fRadius)
{
//Our new density value
uDensity = VoxelTypeTraits<MaterialDensityPair44>::maxDensity();
uMaterial = 1;
}
//Get the old voxel
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
//Modify the density and material
voxel.setDensity(uDensity);
voxel.setMaterial(uMaterial);
//Write the voxel value into the volume
volData.setVoxelAt(x, y, z, voxel);
}
}
}
}
static PyObject* CreateSphere(PyObject* self, PyObject* args)
{
PyObject* pandaNodeWrapper;
if (!PyArg_ParseTuple(args, "0", &pandaNodeWrapper))
return NULL;
//Create an empty volume and then place a sphere in it
SimpleVolume<MaterialDensityPair44> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63)));
createSphereInVolume(volData, 30);
//Extract the surface
SurfaceMesh<PositionMaterialNormal> mesh;
CubicSurfaceExtractorWithNormals<SimpleVolume, MaterialDensityPair44 > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
surfaceExtractor.execute();
const vector<PositionMaterialNormal>& vertices = mesh.getVertices();
const vector<uint32_t>& indices = mesh.getIndices();
CPT(GeomVertexFormat) vertexFormat = GeomVertexFormat::get_v3n3();
PT(GeomVertexData) vertexData = new GeomVertexData("ProceduralMesh", vertexFormat, GeomEnums::UH_static);
GeomVertexWriter vertex, normal;
vertex = GeomVertexWriter(vertexData, "vertex");
normal = GeomVertexWriter(vertexData, "normal");
for(vector<PositionMaterialNormal>::const_iterator it = vertices.begin(); it != vertices.end(); ++it)
{
vertex.add_data3f(it->position.getX(), it->position.getY(), it->position.getZ());
normal.add_data3f(it->normal.getX(), it->position.getY(), it->position.getZ());
}
PT(GeomTriangles) chunk = new GeomTriangles(GeomEnums::UH_static);
for(int i = 0; i < indices.size(); ++i)
{
chunk->add_vertex(indices[i]);
}
PT(Geom) geom = new Geom(vertexData);
geom->add_primitive(chunk);
PT(GeomNode) geomNode = new GeomNode("chunk");
PandaNode* node = ((PandaNode*)((Dtool_PyInstDef*)pandaNodeWrapper)->_ptr_to_object);
node->add_child(geomNode);
Py_RETURN_NONE;
}
static PyMethodDef module_methods[] = {
{"CreateSphere", CreateSphere, METH_VARARGS, "CreateSphere"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
initpolyvox(void)
{
(void) Py_InitModule("polyvox", module_methods);
}
It's a c++ extension module i'm trying to write, i used the setup.py method to compile it and install it, the problem is that when i import it in python and run it, python says "SystemError: dynamic module not initialized properly".
I know that this error should be that module name doesn't correspond with the init function name, but it isn't like that if you see the code. So what could be the problem?
I'm on Windows 7, using python 2.7.2, the module is compiled on VS2008 but it requires some .lib i had to compile with vs2010 since some modern c++ features are required.

C++ OpenGL: Ray Trace Shading Isn't Properly Shading

I'm a CS student and for our final we were told to construct the reflections on multiple spheres via ray tracing. That's almost literally what we got for directions except a picture for how it should look when finished. So I need spheres, with they're reflections (using ray tracing) mapped on them with the proper shading from a light.
Well I have all of it working, except having multiple spheres and the fact that it doesn't look like the picture he gave us for a rubric.
The multiple spheres thing I'm not too sure how to do, but I'd say I need to store them in a 2D array and modify a few sections of code.
What I thought was modifying the sphere_intersect and find_reflect to include which sphere is being analyzed. Next, modify find_reflect so that when the new vector u is calculated its starting point (P0) is also updated. Then if the ray hits a sphere it will have to count how many times the ray has been reflected. At some point terminate (after 10 times maybe) and then I'll just draw the pixel. For an added touch I'd like to add solid colors to the spheres which would call for finding the normal of a sphere I believe.
Anyways I'm going to attach a picture of his, a picture of mine, and the source code. Hopefully someone can help me out on this one.
Thanks in advance!
Professor's spheres
My spheres
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <math.h>
#include <string>
#define screen_width 750
#define screen_height 750
#define true 1
#define false 0
#define perpendicular 0
int gridXsize = 20;
int gridZsize = 20;
float plane[] = {0.0, 1.0, 0.0, -50.0,};
float sphere[] = {250.0, 270.0, -100.0, 100.0};
float eye[] = {0.0, 400.0, 550.0};
float light[] = {250.0, 550.0, -200.0};
float dot(float *u, float *v)
{
return u[0]*v[0] + u[1]*v[1] + u[2]*v[2];
}
void norm(float *u)
{
float norm = sqrt(abs(dot(u,u)));
for (int i =0; i <3; i++)
{
u[i] = u[i]/norm;
}
}
float plane_intersect(float *u, float *pO)
{
float normt[3] = {plane[0], plane[1], plane[2]};
float s;
if (dot(u,normt) == 0)
{
s = -10;
}
else
{
s = (plane[3]-(dot(pO,normt)))/(dot(u,normt));
}
return s;
}
float sphere_intersect(float *u, float *pO)
{
float deltaP[3] = {sphere[0]-pO[0],sphere[1]-pO[1],sphere[2]-pO[2]};
float deltLen = sqrt(abs(dot(deltaP,deltaP)));
float t=0;
float answer;
float det;
if ((det =(abs(dot(u,deltaP)*dot(u,deltaP))- (deltLen*deltLen)+sphere[3]*sphere[3])) < 0)
{
answer = -10;
}
else
{
t =-1*dot(u,deltaP)- sqrt(det) ;
if (t>0)
{
answer = t;
}
else
{
answer = -10;
}
}
return answer;
}
void find_reflect(float *u, float s, float *pO)
{
float n[3] = {pO[0]+s *u[0]-sphere[0],pO[1]+s *u[1]-sphere[1],pO[2]+s *u[2]- sphere[2]};
float l[3] = {s *u[0],s *u[1],s *u[2]};
u[0] =(2*dot(l,n)*n[0])-l[0];
u[1] = (2*dot(l,n)*n[1])-l[1];
u[2] = (2*dot(l,n)*n[2])-l[2];
}
float find_shade(float *u,float s, float *pO)
{
float answer;
float lightVec[3] = {light[0]-(pO[0]+s *u[0]), light[1]-(pO[1]+s *u[1]), light[2]-(pO[2]+s *u[2])};
float n[3] = {pO[0]+s *u[0]-sphere[0],pO[1]+s *u[1]-sphere[1],pO[2]+s *u[2]-sphere[2]};
answer = -1*dot(lightVec,n)/(sqrt(abs(dot(lightVec,lightVec)))*sqrt(abs(dot(n,n))));
return answer;
}
void init()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,screen_width,0,screen_height);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (int i=0; i < screen_width; i++)
{
for (int j=0; j < screen_height; j++)
{
float ray[3] = {1*(eye[0]-i),-1*(eye[1]-j),1*eye[2]};
float point[3] = {i,j,0};
norm(ray);
int plotted = false;
while (!plotted)
{
float s_plane = plane_intersect(ray, point);
float s_sphere = sphere_intersect(ray, point);
if (s_plane <= 0 && s_sphere <=0)
{
glColor3f(0,0,0);
glBegin(GL_POINTS);
glVertex3f(i,j,0);
glEnd();
plotted = true;
}
else if (s_sphere >= 0 && (s_plane <=0 || s_sphere <= s_plane))
{
find_reflect(ray, s_sphere, point);
}
else if (s_plane >=0 && (s_sphere <=0 ||s_plane <= s_sphere))
{
float shade = find_shade(ray, s_plane, point);
float xx = s_plane*ray[0] + eye[0];
float z = s_plane*ray[2] + eye[2];
if (abs((int)xx/gridXsize)%2 == abs((int)z/gridZsize)%2)
{
glColor3f(shade,0,0);
}
else
{
glColor3f(shade,shade,shade);
}
glBegin(GL_POINTS);
glVertex3f(i,j,0);
glEnd();
plotted = true;
}
}
}
}
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutCreateWindow("Ray Trace with Sphere.");
glutInitWindowSize(screen_width,screen_height);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutDisplayFunc(display);
init();
glutMainLoop();
return 0;
}
The professor did not tell you too much, because such a topic is covered thousands of time over the web, just check-out "Whitted Raytracing" ;) It's homework, and 5mn of googling around would solve the issue... Some clues to help without doing your homework for you
Do it step by step, don't try to reproduce the picture in one step
Get one sphere working, if hit the plane green pixel, the sphere red pixel, nothing, black. It's enough to get the intersections computing right. It looks like, from your picture, that you don't have the intersections right, for a start
Same as previous, with several spheres. Same as one sphere : check intersection for all objects, keep the closest intersection from the point of view.
Same as previous, but also compute the amount of light received for each intersection found, to have shade of red for spheres, and shade of green for the plane. (hint: dot product ^^)
Texture for the plane
Reflection for the spheres. Protip: a mirror don't reflect 100% of the light, just a fraction of it.