按照计划,今天是要写一篇博客的,可是实在不知道写啥,而且现在时间比较赶,等下还要准备明天深度学习课题组的报告,所以,就拿出一个上个星期写的比较挫的关于Bezier曲线曲面的C++基础类的实现,当然,这还是一个初始版本,所以功能还不齐全,只实现了一些基本的功能,后期可以继续更新。
首先,我写的程序中用到了智能指针数组shared_array,因为 比较讨厌动态指针的手动分配和对应的手动添加代码delete或者delete[],这个智能指针来自于boost准标准C++模板库,如果要直接使用代码的话,还需要配置下这个库,具体配置可以参考我的博客http://blog.youkuaiyun.com/chaojiwudixiaofeixia/article/details/49419895(C++智能指针shared_array),有了这个基本环境,下面我就直接上代码了,总共四个文件。
1. Bezier.h
// ----------------------------------------------------------------------------------------------------------------------------
//
// Version 1.00
//
// ----------------------------------------------------------------------------------------------------------------------------
#pragma once
#include <boost\smart_ptr.hpp>
#include "CGMath.h"
using namespace boost;
class BezierCurve3D {
public:
shared_array<vec3> cp;
int degree; // degree of the curves
BezierCurve3D();
~BezierCurve3D();
BezierCurve3D(shared_array<vec3> p, int dg);// p,dg分别表示控制点和曲线次数
void SetCurve(shared_array<vec3> p, int dg);// 类似于构造函数
vec3 Point(float u);// 用De Casteljau算法计算曲线上的点
};
class BezierSurface3D {
public:
int udeg, vdeg; // degree of the surface at diffrent directions
shared_array<vec3> cp; // 控制多边形,按照行扫描的方式构成的控制点,数目应该就是m*n
BezierSurface3D();
~BezierSurface3D();
BezierSurface3D(shared_array<vec3> p, int udg, int vdg);
void SetSurface(shared_array<vec3> p, int udg, int vdg);
vec3 Point(float u, float v);
};
2. Bezier.cpp
#include "Bezier.h"
///////////////////////////////// C U R V E //////////////////////////////////////////
BezierCurve3D::BezierCurve3D()
:degree(0)
{
}
BezierCurve3D::~BezierCurve3D()
{
}
BezierCurve3D::BezierCurve3D(shared_array<vec3> p, int dg)
{
degree = dg;
cp = shared_array<vec3>(new vec3[degree + 1]);
for (int i = 0; i <= degree; i++) {
cp[i] = p[i];
}
}
void BezierCurve3D::SetCurve(shared_array<vec3> p, int dg)
{
degree = dg;
cp = shared_array<vec3>(new vec3[degree + 1]);
for (int i = 0; i <= degree; i++) {
cp[i] = p[i];
}
}
vec3 BezierCurve3D::Point(float u)
{
shared_array<vec3> cq(new vec3[degree + 1]);
for (int i = 0; i <= degree; i++) {
cq[i] = cp[i];
}
for (int k = 1; k <= degree; k++) {
for (int i = 0; i <= degree - k; i++) {
cq[i] = (1 - u)*cq[i] + u*cq[i + 1];
}
}
return cq[0];
}
///////////////////////////////// S U R F A C E //////////////////////////////////////////
BezierSurface3D::BezierSurface3D()
{
}
BezierSurface3D::~BezierSurface3D()
{
}
BezierSurface3D::BezierSurface3D(shared_array<vec3> p, int udg, int vdg)
{
udeg = udg;
vdeg = vdg;
int count = (udg + 1)*(vdg + 1);
cp = shared_array<vec3>(new vec3[count]);
for (int i = 0; i < count; i++) {
cp[i] = p[i];
}
}
void BezierSurface3D::SetSurface(shared_array<vec3> p, int udg, int vdg)
{
udeg = udg;
vdeg = vdg;
int count = (udg + 1)*(vdg + 1);
cp = shared_array<vec3>(new vec3[count]);
for (int i = 0; i < count; i++) {
cp[i] = p[i];
}
}
vec3 BezierSurface3D::Point(float u,float v)
{
int count = (udeg + 1)*(vdeg + 1);
shared_array<vec3> cq(new vec3[count]);
for (int i = 0; i < count; i++) {
cq[i] = cp[i];
}
for (int j = 0; j <= udeg; j++) {
for (int k = 1; k <= vdeg; k++) {
for (int i = 0; i <= vdeg - k; i++) {
cq[i + j*(vdeg + 1)] = (1 - v)*cq[i + j*(vdeg + 1)] + v*cq[i + 1 + j*(vdeg + 1)];
}
}
}
for (int k = 1; k <= udeg; k++) {
for (int i = 0; i <= udeg - k; i++) {
cq[i*(vdeg + 1)] = (1 - u)*cq[i*(vdeg + 1)] + u*cq[(i + 1)*(vdeg + 1)];
}
}
return cq[0];
}
其中包含的CGMath头文件和对应的源文件如下,主要是实现三维数据的一些基本运算功能。
3. CGMath.h
// ----------------------------------------------------------------------------------------------------------------------------
//
// Version 1.00
//
// ----------------------------------------------------------------------------------------------------------------------------
#pragma once
#include <cmath>
// 三维向量,点类
class vec3{
public:
union{
struct{ float x, y, z; };
struct{ float s, t, p; };
struct{ float r, g, b; };
};
vec3() : x(0.0f), y(0.0f), z(0.0f){} // 默认构造函数
~vec3(){} // 析构
vec3(float x, float y, float z) : x(x), y(y), z(z){}
vec3(const vec3 &u) : x(u.x), y(u.y), z(u.z){}
// 运算符重载
vec3& operator = (const vec3 &u){ x = u.x; y = u.y; z = u.z; return *this; }
vec3 operator - (){ return vec3(-x, -y, -z); }
float* operator & (){ return (float*)this; }
vec3& operator += (float num){ x += num; y += num; z += num; return *this; }
vec3& operator += (const vec3 &u){ x += u.x; y += u.y; z += u.z; return *this; }
vec3& operator -= (float num){ x -= num; y -= num; z -= num; return *this; }
vec3& operator -= (const vec3 &u){ x -= u.x; y -= u.y; z -= u.z; return *this; }
vec3& operator *= (float num){ x *= num; y *= num; z *= num; return *this; }
vec3& operator *= (const vec3 &u){ x *= u.x; y *= u.y; z *= u.z; return *this; }
vec3& operator /= (float num){ x /= num; y /= num; z /= num; return *this; }
vec3& operator /= (const vec3 &u){ x /= u.x; y /= u.y; z /= u.z; return *this; }
friend vec3 operator + (const vec3 &u, float num){ return vec3(u.x + num, u.y + num, u.z + num); }
friend vec3 operator + (float num, const vec3 &u){ return vec3(num + u.x, num + u.y, num + u.z); }
friend vec3 operator + (const vec3 &u, const vec3 &v){ return vec3(u.x + v.x, u.y + v.y, u.z + v.z); }
friend vec3 operator - (const vec3 &u, float num){ return vec3(u.x - num, u.y - num, u.z - num); }
friend vec3 operator - (float num, const vec3 &u){ return vec3(num - u.x, num - u.y, num - u.z); }
friend vec3 operator - (const vec3 &u, const vec3 &v){ return vec3(u.x - v.x, u.y - v.y, u.z - v.z); }
friend vec3 operator * (const vec3 &u, float num){ return vec3(u.x * num, u.y * num, u.z * num); }
friend vec3 operator * (float num, const vec3 &u){ return vec3(num * u.x, num * u.y, num * u.z); }
friend vec3 operator * (const vec3 &u, const vec3 &v){ return vec3(u.x * v.x, u.y * v.y, u.z * v.z); }
friend vec3 operator / (const vec3 &u, float num){ return vec3(u.x / num, u.y / num, u.z / num); }
friend vec3 operator / (float num, const vec3 &u){ return vec3(num / u.x, num / u.y, num / u.z); }
friend vec3 operator / (const vec3 &u, const vec3 &v){ return vec3(u.x / v.x, u.y / v.y, u.z / v.z); }
};
// ----------------------------------------------------------------------------------------------------------------------------
vec3 cross(const vec3 &u, const vec3 &v); //
float dot(const vec3 &u, const vec3 &v);
float length(const vec3 &u);
float length2(const vec3 &u);
vec3 normalize(const vec3 &u);
// ----------------------------------------------------------------------------------------------------------------------------
4. CGMath.cpp
#include "CGMath.h"
// ----------------------------------------------------------------------------------------------------------------------------
vec3 cross(const vec3 &u, const vec3 &v)
{
return vec3(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x);
}
float dot(const vec3 &u, const vec3 &v)
{
return u.x * v.x + u.y * v.y + u.z * v.z;
}
float length(const vec3 &u)
{
return sqrt(u.x * u.x + u.y * u.y + u.z * u.z);
}
float length2(const vec3 &u)
{
return u.x * u.x + u.y * u.y + u.z * u.z;
}
vec3 normalize(const vec3 &u)
{
return u / sqrt(u.x * u.x + u.y * u.y + u.z * u.z);
}
至于怎么使用,我就不加代码了,因为还涉及到用OpenGL去做现实,基础代码比较多。功能比较简单,也没有做什么异常处理,将就下吧。。。