按照計劃,今天是要寫一篇博客的,可是實在不知道寫啥,而且現在時間比較趕,等下還要準備明天深度學習課題組的報告,所以,就拿出一個上個星期寫的比較挫的關於Bezier曲線曲面的C++基礎類的實現,當然,這還是一個初始版本,所以功能還不齊全,只實現了一些基本的功能,後期可以繼續更新。
首先,我寫的程序中用到了智能指針數組shared_array,因爲 比較討厭動態指針的手動分配和對應的手動添加代碼delete或者delete[],這個智能指針來自於boost準標準C++模板庫,如果要直接使用代碼的話,還需要配置下這個庫,具體配置可以參考我的博客http://blog.csdn.net/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];
}
// ----------------------------------------------------------------------------------------------------------------------------
//
// 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);
// ----------------------------------------------------------------------------------------------------------------------------
#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去做現實,基礎代碼比較多。功能比較簡單,也沒有做什麼異常處理,將就下吧。。。