OPENGL+点云可视化

之前的文章写了如何在VS2015 下配置 opengl可视化环境,本文介绍如何使用opengl 来进行点云的简单显示,主要参考资料为:

 learnopengl: https://learnopengl-cn.github.io/。

 cloudcompare:https://github.com/CloudCompare/CloudCompare

首先需要构建一个点云类PointCloud,用于点云的读取,计算点的个数、重心等基本功能。

下面是PointCloud.h文件

#ifndef POINTCLOUD_H
#define POINTCLOUD_H
#include "Tuple.h"
#include 
#include 
#include 
#include 
using namespace std;
namespace CCLib
{
	class Octree;

	class PointCloud
	{
	public:
		PointCloud();
		~PointCloud();

		typedef std::vector cloud;
	public:

		float m_Xmin;
		float m_Ymin;
		float m_Zmin;
		CCVector3 Gravity;
		CCVector3 minCoordinate;
		CCVector3 maxCoordinate;
		CCVector3 bounding;
		unsigned numberOfpoints;
		Octree* octree;

		//functions
		void read(char*p);
		void save(char*q);
		void getMinXCoordinate();
		void getMinYCoordinate();
		void getMinZCoordinate();
		void getMaxXCoordinate();
		void getMaxYCoordinate();
		void getMaxZCoordinate();
		Octree* computeOctree(bool autoAddChild/*=true*/);
		CCVector3& computeGravity();
	    void getBounding(CCVector3&min,CCVector3&max);
		const CCVector3* getPoint(unsigned);
	    void ConstructMinCube(CCVector3& dimMin, CCVector3& dimMax, double enlargeFactor/*=0.01*/);
		unsigned size();
		//add Point
		void addPoint(CCVector3);
		float getWidth()
		{
			getMinXCoordinate();
			getMaxXCoordinate();
			return maxCoordinate.x - minCoordinate.x;
		}
		float getLength()
		{
			getMinYCoordinate();
			getMaxYCoordinate();
			return maxCoordinate.y - minCoordinate.y;
		}
		float getHeight()
		{
			getMinZCoordinate();
			getMaxZCoordinate();
			return maxCoordinate.z - minCoordinate.z;
		}
	private:	cloud c1;

	};
}
#endif

然后是PointCloud源文件:

#include "PointCloud.h"
#include "Octree.h"
using namespace CCLib;
PointCloud::PointCloud()
{
	
}
void PointCloud::read(char *p)
{
		CCVector3 temp;
		ifstream fin(p);
		
		if (!fin)
		{
			cout << "open file failed!";
			//return -1;
		}
		while (fin >> temp.x >> temp.y >> temp.z)
		{	
			c1.push_back(temp);
		}
		fin.close();
}
void PointCloud::save(char* q)
{
	ofstream fout(q);

	if (!fout)
	{
		cout << "open file failed!";
		//return -1;
	}
	for (unsigned i = 0; i < c1.size(); i++)
	{
		fout << c1[i].x<<" "<< c1[i].y <<" "<< c1[i].z<= c1[i].x)
			minCoordinate.x = c1[i].x;
	}


}
void PointCloud::getMinYCoordinate()
{

	minCoordinate.y = c1[0].y;
	for (unsigned i = 0; i < c1.size(); i++)
	{
		if (minCoordinate.y >= c1[i].y)
			minCoordinate.y = c1[i].y;
	}


}
void PointCloud::getMinZCoordinate()
{

	minCoordinate.z = c1[0].z;
	for (unsigned i = 0; i < c1.size(); i++)
	{
		if (minCoordinate.z>= c1[i].z)
			minCoordinate.z = c1[i].z;
	}


}
void PointCloud::getMaxXCoordinate()
{

	maxCoordinate.x = c1[0].x;
	for (unsigned i = 0; i < c1.size(); i++)
	{
		if (maxCoordinate.x <= c1[i].x)
			maxCoordinate.x = c1[i].x;
	}


}
void PointCloud::getMaxYCoordinate()
{

	maxCoordinate.y = c1[0].y;
	for (unsigned i = 0; i < c1.size(); i++)
	{
		if (maxCoordinate.y <= c1[i].y)
			maxCoordinate.y = c1[i].y;
	}


}
void PointCloud::getMaxZCoordinate()
{

	maxCoordinate.z = c1[0].z;
	for (unsigned i = 0; i < c1.size(); i++)
	{
		if (maxCoordinate.z <= c1[i].z)
			maxCoordinate.z = c1[i].z;
	}


}

void PointCloud:: getBounding(CCVector3&min,CCVector3&max)
{
	getMinXCoordinate();
	getMinYCoordinate();
	getMinZCoordinate();
	getMaxXCoordinate();
	getMaxYCoordinate();
	getMaxZCoordinate();
	
	min = minCoordinate;
	max = maxCoordinate;

}
const CCVector3* PointCloud::getPoint(unsigned i)
{
	size();
	CCVector3* theGettingPoint=NULL;
	if (numberOfpoints == 0)
	{
		cout << "NO POINTS IN THE CLOUD" << endl;
		
	}
	else
	{
		 theGettingPoint= &c1[i];

	}

	
	return theGettingPoint;
}
unsigned PointCloud::size()
{
	numberOfpoints = c1.size();
	return numberOfpoints;

}
CCVector3& PointCloud::computeGravity()
{
	for (unsigned i = 0; i < size(); i++)
	{
		Gravity.x += c1[i].x;
		Gravity.y += c1[i].y;
		Gravity.z += c1[i].z;
	}
	Gravity.x = Gravity.x / numberOfpoints;
	Gravity.y = Gravity.y / numberOfpoints;
	Gravity.z = Gravity.z / numberOfpoints;
	return Gravity;                                                          

}
void PointCloud::ConstructMinCube(CCVector3& dimMin, CCVector3& dimMax, double enlargeFactor/*=0.01*/)
{
	float maxDD = 0;
	getBounding(dimMin, dimMax);
	{
		CCVector3 diag = dimMax - dimMin;
		maxDD = std::max(diag.x, diag.y);
		maxDD = std::max(maxDD, diag.z);
	}
	if (enlargeFactor > 0)
		maxDD = static_cast(static_cast(maxDD)* (1.0 + enlargeFactor));

	//build corresponding 'square' box
	{
		CCVector3 dd(maxDD, maxDD, maxDD);
		CCVector3 md = dimMax + dimMin;

		dimMin = (md - dd) * static_cast(0.5);
		dimMax = dimMin + dd;
	}


}
 Octree* PointCloud::computeOctree(bool autoAddChild/*=true*/)
{
	Octree* octree = new Octree(this);
	 getMinXCoordinate();
	 getMinYCoordinate();
	 getMinZCoordinate();
	 getMaxXCoordinate();
	 getMaxYCoordinate();
	 getMaxZCoordinate();

	int a = octree->build(minCoordinate,maxCoordinate);
	if (a > 0)
		cout << "compute Octree sucessful" << endl;
	return octree;
	

}
 void PointCloud::addPoint(CCVector3 point)
 {
	
		 c1.push_back(point);

	
	 
 }
PointCloud::~PointCloud()
{
}

读取的点云通过std::point 容器保存,CCVECTOR 的定义在Tuple头文件,这部分完全参考CC:

#ifndef Tuple_H
#define Tuple_H
#include 
template  class Tuple3
{
	public:
		union 
		{
			struct
			{
				Type x, y, z;
			};
			 Type u[3];
		};
		inline Tuple3() :x(0), y(0), z(0)  {}
		inline Tuple3(Type a, Type b, Type c) :x(a), y(b), z(c) {}
		inline explicit Tuple3(const Type P[]) :x(P[0]), y(P[1]), z(P[2]) {}
		inline Tuple3(const Tuple3& v) :x(v.x), y(v.y), z(v.z) {}

		//Invers operator
		inline Tuple3 operator -() const  { Tuple3 V(-x, -y, -z); return V; }
		inline Tuple3 operator +=(const Tuple3& V) { x += V.x;  y += V.y;  z += V.z; return *this; }
		inline Tuple3 operator *=(Type v)   { x *=v;  y *= v;  z *= v; return *this; }
		inline Tuple3 operator /=(Type v)   { x /=v;  y /= v;  z /= v; return *this; }
		inline Tuple3 operator -=(const Tuple3& V) { x -= V.x;  y -= V.y;  z -= V.z; return *this; }
		inline Tuple3 operator +(const Tuple3& V) const  { V.x = x + V.x; V.y = y + V.y;V.z=z+V.z; return V; }
		inline Tuple3 operator -(const Tuple3& V) const  { return V(x - V.x, y - V.y, z - V.z); }
		inline Tuple3 operator *(Type s) const  { return Tuple3(x*s, y*s, z*s); }
		inline Tuple3 operator /(Type s) const  { return Tuple3(x/s, y/s, z/s); }		
};
	
		typedef Tuple3 Tuple3ub;
		typedef Tuple3 Tuple3s;
		typedef Tuple3 Tuple3i;
		typedef Tuple3 Tuple3ui;

template  class Vector3 :public Tuple3
{
public:
	using Tuple3::x;
	using Tuple3::y;
	using Tuple3::z;
	using Tuple3::u;

	inline Vector3() : Tuple3() {}
	inline Vector3(Type _a, Type _b, Type _c) : Tuple3(_a, _b, _c)  {}
	inline explicit Vector3(const Type P[]) : Tuple3(P) {}
	inline Vector3(const Vector3& v) : Tuple3(v) {}

	static inline Vector3 fromArray(const int a[3]) { return Vector3(static_cast(a[0]), static_cast(a[1]), static_cast(a[2])); }
	//! Constructor from a float array
	static inline Vector3 fromArray(const float a[3]) { return Vector3(static_cast(a[0]), static_cast(a[1]), static_cast(a[2])); }
	//! Constructor from a double array
	static inline Vector3 fromArray(const double a[3]) { return Vector3(static_cast(a[0]), static_cast(a[1]), static_cast(a[2])); }
	// you can add other options here dot product,cross product and so on

	inline Type dot(const Vector3& v) const { return (x*v.x) + (y*v.y) + (z*v.z); }
	//! Cross product
	inline Vector3 cross(const Vector3 &v) const { return Vector3((y*v.z) - (z*v.y), (z*v.x) - (x*v.z), (x*v.y) - (y*v.x)); }
	inline Type norm2() const { return (x*x) + (y*y) + (z*z); }
	inline double norm2d() const { return static_cast(x)*x + static_cast(y)*y + static_cast(z)*z ; }

	inline Vector3 operator -(const Vector3& V) const { return Vector3(x - V.x, y - V.y, z - V.z); }
	inline Vector3 operator +(const Vector3& V) const { return Vector3(x + V.x, y + V.y, z + V.z); }
	inline Vector3 operator *(Type s) const { return Vector3(s*x,s*y,s*z); }
	inline Type& operator [](unsigned i)  { return u[i]; }
	inline const Type& operator []  (unsigned i) const { return u[i]; }

	inline void normalize() { Type n = norm2(); if (n>0) *this /= sqrt(n); }
	//! Returns a normalized vector which is orthogonal to this one
	static inline void vdivide(Type p[], Type s) { p[0] /= s; p[1] /= s; p[2] /= s; }
	static inline void vdivide(const Type p[], Type s, Type r[]) { r[0] = p[0] / s; r[1] = p[1] / s; r[2] = p[2] / s; }
	static inline Type vnorm2(const Type p[]) { return (p[0] * p[0]) + (p[1] * p[1]) + (p[2] * p[2]); }
	inline Vector3 orthogonal() const { Vector3 ort; vorthogonal(u, ort.u); return ort; }
	static inline void vnormalize(Type p[]) { Type n = vnorm2(p); if (n>0) vdivide(p, sqrt(n)); }
	static inline void vorthogonal(const Type p[], Type q[])
	{
		if (fabs(p[0]) <= fabs(p[1]) && fabs(p[0]) <= fabs(p[2]))
		{
			q[0] = 0; q[1] = p[2]; q[2] = -p[1];
		}
		else if (fabs(p[1]) <= fabs(p[0]) && fabs(p[1]) <= fabs(p[2]))
		{
			q[0] = -p[2]; q[1] = 0; q[2] = p[0];
		}
		else
		{
			q[0] = p[1]; q[1] = -p[0]; q[2] = 0;
		}
		vnormalize(q);
	}


};
//! Default 3D Vector
typedef Vector3 CCVector3;
//! Double 3D Vector
typedef Vector3 CCVector3d;


//2D Vector
//! 2D Vector
template  class Vector2Tpl
{
public:

	union
	{
		struct
		{
			Type x, y;
		};
		Type u[2];
	};

	//! Default constructor
	/** Inits vector to (0,0).
	\param s default init value for both coordinates
	**/
	inline Vector2Tpl(Type s = 0) : x(s), y(s) {}

	//! Constructor from a couple of coordinates
	/** Inits vector to (x,y).
	\param _x x coordinate
	\param _y y coordinate
	**/
	inline Vector2Tpl(Type _x, Type _y) : x(_x), y(_y) {}

	//! Copy constructor
	inline Vector2Tpl(const Vector2Tpl& v) : x(v.x), y(v.y) {}

	//! Returns vector square norm
	inline Type norm2() const { return (x*x) + (y*y); }
	//! Returns vector norm
	inline Type norm() const { return sqrt(norm2()); }
	//! Sets vector norm to unity
	inline void normalize() { Type n = norm2(); if (n>0) *this /= sqrt(n); }

	//! Dot product
	inline Type dot(const Vector2Tpl& v) const { return (x*v.x) + (y*v.y); }

	//! Inverse operator
	inline Vector2Tpl& operator - () { x = -x; y = -y; return *this; }
	//! In-place addition operator
	inline Vector2Tpl& operator += (const Vector2Tpl& v) { x += v.x; y += v.y; return *this; }
	//! In-place substraction operator
	inline Vector2Tpl& operator -= (const Vector2Tpl& v) { x -= v.x; y -= v.y; return *this; }
	//! In-place multiplication (by a scalar) operator
	inline Vector2Tpl& operator *= (Type v) { x *= v; y *= v; return *this; }
	//! In-place division (by a scalar) operator
	inline Vector2Tpl& operator /= (Type v) { x /= v; y /= v; return *this; }
	//! Addition operator
	inline Vector2Tpl operator + (const Vector2Tpl& v) const { return Vector2Tpl(x + v.x, y + v.y); }
	//! Substraction operator
	inline Vector2Tpl operator - (const Vector2Tpl& v) const { return Vector2Tpl(x - v.x, y - v.y); }
	//! Multiplication operator
	inline Vector2Tpl operator * (Type s) const { return Vector2Tpl(x*s, y*s); }
	//! Division operator
	inline Vector2Tpl operator / (Type s) const { return Vector2Tpl(x / s, y / s); }
	//! Copy operator
	inline Vector2Tpl& operator = (const Vector2Tpl &v) { x = v.x; y = v.y; return *this; }
	//! Direct coordinate access
	inline Type& operator [] (unsigned i) { return u[i]; }
	//! Direct coordinate access (const)
	inline const Type& operator [] (unsigned i) const { return u[i]; }
};

//! Default 2D Vector
typedef Vector2Tpl CCVector2;

//! Int 2D Vector
typedef Vector2Tpl CCVector2i;

#endif

最后重点来了,在main函数里面实现点云的可视化,根据learnopengl的相关教程,定义了一个相机类Camera.h:

#pragma once

// Std. Includes
#include 

// GL Includes
#include 
#include 
#include 



// Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods
enum Camera_Movement {
	FORWARD,
	BACKWARD,
	LEFT,
	RIGHT
};

// Default camera values
const GLfloat YAW = -90.0f;
const GLfloat PITCH = 0.0f;
const GLfloat ROLL = 0.0f;
const GLfloat SPEED = 3.0f;
const GLfloat SENSITIVTY = 0.25f;
const GLfloat ZOOM = 30.0f;


// An abstract camera class that processes input and calculates the corresponding Eular Angles, Vectors and Matrices for use in OpenGL
class Camera
{
public:
	// Camera Attributes
	glm::vec3 Position;
	glm::vec3 TargetPositon;
	glm::vec3 Front;
	glm::vec3 Up;
	glm::vec3 Right;
	glm::vec3 WorldUp;
	// Eular Angles
	GLfloat Yaw;
	GLfloat Pitch;
	GLfloat Roll;
	// Camera options
	GLfloat MovementSpeed;
	GLfloat MouseSensitivity;
	GLfloat Zoom;
	//Front(glm::vec3(0.0f, 0.0f, -1.0f)
	// Constructor with vectors
	Camera(glm::vec3 position , glm::vec3 up , glm::vec3 target , GLfloat yaw , GLfloat pitch , GLfloat roll ) : MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
	{
		this->Position = position;
		this->WorldUp = up;
		this->TargetPositon = target;
		this->Yaw = yaw;
		this->Pitch = pitch;
		this->Roll = roll;
		this->updateCameraVectors();
	}
	// Constructor with scalar values
	Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
	{
		this->Position = glm::vec3(posX, posY, posZ);
		this->WorldUp = glm::vec3(upX, upY, upZ);
		this->Yaw = yaw;
		this->Pitch = pitch;
		this->updateCameraVectors();
	}

	// Returns the view matrix calculated using Eular Angles and the LookAt Matrix
	glm::mat4 GetViewMatrix()
	{
		//return glm::lookAt(this->Position, this->Position + this->Front, this->Up);
		return glm::lookAt(this->Position, this->TargetPositon, this->WorldUp);
	}

	// Processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
	void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
	{
		GLfloat velocity = this->MovementSpeed * deltaTime;
		if (direction == FORWARD)
			this->Position += this->Front * velocity;
		if (direction == BACKWARD)
			this->Position -= this->Front * velocity;
		if (direction == LEFT)
			this->Position -= this->Right * velocity;
		if (direction == RIGHT)
			this->Position += this->Right * velocity;
	}

	// Processes input received from a mouse input system. Expects the offset value in both the x and y direction.
	void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch = true)
	{
		xoffset *= this->MouseSensitivity;
		yoffset *= this->MouseSensitivity;

		this->Yaw += xoffset;
		this->Pitch += yoffset;

		// Make sure that when pitch is out of bounds, screen doesn't get flipped
		if (constrainPitch)
		{
			if (this->Pitch > 89.0f)
				this->Pitch = 89.0f;
			if (this->Pitch < -89.0f)
				this->Pitch = -89.0f;
		}

		// Update Front, Right and Up Vectors using the updated Eular angles
		this->updateCameraVectors();
	}

	// Processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
	void ProcessMouseScroll(GLfloat yoffset)
	{
		if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)
			this->Zoom -= yoffset;
		if (this->Zoom <= 1.0f)
			this->Zoom = 1.0f;
		if (this->Zoom >= 45.0f)
			this->Zoom = 45.0f;
	}

	// Calculates the front vector from the Camera's (updated) Eular Angles
private:	void updateCameraVectors()
	{
		




		// Calculate the new Front vector
		glm::vec3 front;
		front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
		front.y = sin(glm::radians(this->Pitch));
		front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
		this->Front = glm::normalize(front);
		this->Position = this->TargetPositon - this->Front;
		this->WorldUp.x = sin(glm::radians(Roll));
		this->WorldUp.y = cos(glm::radians(Roll));
		this->WorldUp.z = 0;
		// Also re-calculate the Right and Up vector
		//this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));  // Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
		//this->Up = glm::normalize(glm::cross(this->Right, this->Front));
	}
};

相应的顶点着色器(texture.vs)和片段着色器(texture.frag)也是少不了的,对读入的点云设置为统一颜色,因此顶点着色器文件中只读入顶点并进行相应的坐标变换:texture.vs文件如下;

#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
	gl_Position = projection*view* model*vec4(position, 1.0f);
	
	
}

texture.frag文件如下:

#version 330 core
out vec4 color;
void main()
{
    color = vec4(1.0f,1.0f,0.1f, 1.0f);
}

主函数包括点云数据的读取,opengl显示窗口的设置,点云坐标的转换,以及鼠标键盘的响应函数:

#include 
#include 
// GLEW
#define GLEW_STATIC
#include 
// GLFW
#include 
//GLM
#include 
#include 
#include 
// Other Libs
#include 
// Other includes
#include "Shader.h"
#include "Camera.h"
//pointCloud
#include "PointCloud.h"
#include 
#include 
#include "Octree.h"
#include "Neighborhood.h"
#include 
#include "Tuple.h"
#include "triangle.h"
#ifdef SINGLE
#define REAL float
#else /* not SINGLE */
#define REAL double
#endif /* not SINGLE */

#include 
#include "triangle.h"
#define TRILIBABRY
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void do_movement();
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mode);
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
GLfloat lastX = 400, lastY = 300;

bool firstMouse = true;

bool keys[1024];
bool buttons[1024];
//
GLfloat deltaTime = 0.0f;   // 当前帧与上一帧的时间差
GLfloat lastFrame = 0.0f;   // 上一帧的时间
GLfloat mix = 0.2f;
//camera Para
CCVector3 g;
GLfloat phi = asin(fabs(64 / sqrt(349*349 + 217*217 + 64*64)));
GLfloat theta = acos(fabs(3349 * 349 / sqrt(349 * 349 + 217 * 217)));
//Camera camera(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(-3.499, 2.178f, 0.642f), 0.0f, 0.0f, 0.0f);
Camera camera(glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), 0.0, 0.0, 0.0f);

// The MAIN function, from here we start the application and run the game loop
int main()
{


	// Init GLFW
	glfwInit();
	// Set all the required options for GLFW
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	// Create a GLFWwindow object that we can use for GLFW's functions
	GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
	glfwMakeContextCurrent(window);


	// Set the required callback functions
	glfwSetKeyCallback(window, key_callback);
	glfwSetMouseButtonCallback(window, mouse_button_callback);
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetScrollCallback(window, scroll_callback);
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);

	// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
	glewExperimental = GL_TRUE;
	// Initialize GLEW to setup the OpenGL Function pointers
	glewInit();

	// Define the viewport dimensions
	glViewport(0, 0, WIDTH, HEIGHT);


	// Build and compile our shader program
	Shader ourShader("textures.vs", "textures.frag");

	//pointCloud process
	CCLib::PointCloud* cloud = new CCLib::PointCloud;
	char* p = "wyt.xyz";
	cloud->read(p);
	cloud->computeGravity();
	g = cloud->Gravity;
	int pointCount = cloud->size();
	std::vectorvertice;
	//set point color acoording Cloudindex

	for (unsigned i = 0; i < cloud->size();i++)
	{
		const CCVector3* p = cloud->getPoint(i);
		vertice.push_back(p->x);
		vertice.push_back(p->y);
		vertice.push_back(p->z);
		
		
	}


	//dispaly

	GLuint VBO, VAO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);

	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertice[0])*vertice.size(), &vertice[0], GL_STATIC_DRAW);
	

	// Position attribute
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0); // Unbind VAO
	glEnable(GL_DEPTH_TEST);

	//dispaly in GL_line mode
	glPolygonMode(GL_FRONT_AND_BACK, GL_POLYGON);


	// Game loop
	while (!glfwWindowShouldClose(window))
	{
		
		GLfloat currentFrame = glfwGetTime();
		deltaTime = currentFrame - lastFrame;
		lastFrame = currentFrame;
		// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
		glfwPollEvents();

		do_movement();
		// Render
		// Clear the colorbuffer
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		//glClear(GL_COLOR_BUFFER_BIT);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		ourShader.use();
		glBindVertexArray(VAO);
		
		glm::mat4 model(1);
		model = glm::translate(model, glm::vec3(-g.x,-g.y,-g.z));
		GLint modelLoc = glGetUniformLocation(ourShader.Program(), "model");
		glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

		glm::mat4 view;
		view = camera.GetViewMatrix();
		GLint viewLoc = glGetUniformLocation(ourShader.Program(), "view");
		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));

		glm::mat4 projection;
		projection = glm::perspective(glm::radians(camera.Zoom), (GLfloat)WIDTH / (GLfloat)HEIGHT,0.1f, 100.0f);
		GLint projectionLoc = glGetUniformLocation(ourShader.Program(), "projection");
		glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));

		glDrawArrays(GL_POINTS, 0,pointCount);
		glfwSwapBuffers(window);
	}
	// Properly de-allocate all resources once they've outlived their purpose
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	// Terminate GLFW, clearing any resources allocated by GLFW.
	glfwTerminate();
	return 0;
}

// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{

	if (action == GLFW_PRESS)
		keys[key] = true;
	else if (action == GLFW_RELEASE)
		keys[key] = false;

	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(window, GL_TRUE);
	if (key == GLFW_KEY_UP && action == GLFW_PRESS)
	{
		if (mix < 1.0f)
		{
			mix = mix + 0.1;
		}
	}
	
	if (key == GLFW_KEY_DOWN && action == GLFW_PRESS)

	{
		if (mix > 0.0f)
		{
			mix = mix - 0.1;
		}
	}
	/*GLfloat cameraSpeed = 0.05f;
	if (key == GLFW_KEY_W)
		cameraPos += cameraSpeed * cameraFront;
	if (key == GLFW_KEY_S)
		cameraPos -= cameraSpeed * cameraFront;
	if (key == GLFW_KEY_A)
		cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
	if (key == GLFW_KEY_D)
		cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;*/

}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mode)
{
	if (action == GLFW_PRESS)
		buttons[button] = true;
	else if (action == GLFW_RELEASE)
		buttons[button] = false;
	

}
void do_movement()
{
	// 摄像机控制
	GLfloat cameraSpeed = 5.0f * deltaTime;
	//GLfloat cameraSpeed = 0.1f;
	
	if (keys[GLFW_KEY_W])
		camera.ProcessKeyboard(Camera_Movement(0), deltaTime);
	//cameraPos += cameraSpeed * cameraFront;
	if (keys[GLFW_KEY_S])
		camera.ProcessKeyboard(Camera_Movement(1), deltaTime);
	//cameraPos -= cameraSpeed * cameraFront;
	if (keys[GLFW_KEY_A])
		camera.ProcessKeyboard(Camera_Movement(2), deltaTime);
	//cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
	if (keys[GLFW_KEY_D])
		camera.ProcessKeyboard(Camera_Movement(3), deltaTime);
	//cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	
		if (firstMouse)
		{
			lastX = xpos;
			lastY = ypos;
			firstMouse = false;
		}
		

			GLfloat xoffset = xpos - lastX;
			GLfloat yoffset = lastY - ypos;
			lastX = xpos;
			lastY = ypos;
		

			if (buttons[GLFW_MOUSE_BUTTON_LEFT])
			{
				GLfloat sensitivity = 0.05;
				camera.ProcessMouseMovement(xoffset, yoffset);
			}
	
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	
	camera.ProcessMouseScroll(yoffset);
	
}

最后显示的点云如图所示:

OPENGL+点云可视化_第1张图片

笔者在实验时,卡在坐标变换那儿好久,有兴趣的同学门可以尝试以下

你可能感兴趣的:(vs+opengl,PointCloud)