#ifndef _CLOTH_H_
#define _CLOTH_H_
//#include "ClothNew.h"
class Cloth : public Ogre::SimpleRenderable
{
public:
Cloth(int w = 20, int h = 20);
~Cloth();
void update(float delta_time);
virtual void getRenderOperation(Ogre::RenderOperation& rend);
//重载renderable及Moveable方法
Ogre::Real getBoundingRadius() const;
Ogre::Real getSquaredViewDepth(const Ogre::Camera* cam) const;
protected:
class Particle;
class Spring
{
public:
float RestLength;
Particle *a, *b;
void ApplyConstraints();
};
class Particle {
public:
Ogre::Vector3 OldPosition;
Ogre::Vector3 Position;
Ogre::Vector3 Force;
bool Fixed;
};
int mWidth;
int mHeight;
// 所有质点
std::vector<std::vector<Particle> >mParticles;
// 所有弹簧
std::vector<Spring> mSprings;
//ClothImpl mImpl;
// 渲染相关
Ogre::HardwareVertexBufferSharedPtr mPositionBuffer;
Ogre::HardwareVertexBufferSharedPtr mUvBuffer;
Ogre::HardwareIndexBufferSharedPtr mIndexBuffer;
};
#endif
#include "stdafx.h"
#include "Cloth.h"
using namespace Ogre;
Cloth::Cloth(int w, int h)
:mWidth(w),
mHeight(h)
{
mParticles.resize(h);
for (int i = 0; i < h; ++i)
mParticles[i].resize(w);
for (int i = 0; i < h; ++i)
{
for (int j = 0; j < w; ++ j)
{
mParticles[i][j].Position = mParticles[i][j].OldPosition = Vector3(j, -i, 0);
if (i == 0)
mParticles[i][j].Fixed = 1;
else mParticles[i][j].Fixed = 0;
}
}
mRenderOp.indexData = new Ogre::IndexData;
mRenderOp.vertexData = new Ogre::VertexData;
mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
mRenderOp.useIndexes = true;
mRenderOp.vertexData->vertexCount = w * h;
mRenderOp.vertexData->vertexStart = 0;
Ogre::VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
decl->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
decl->addElement(1, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
HardwareBufferManager& mgr = HardwareBufferManager::getSingleton();
mIndexBuffer = mgr.createIndexBuffer(HardwareIndexBuffer::IT_32BIT, 6 * (h - 1) * (w - 1), HardwareBuffer::HBU_STATIC_WRITE_ONLY);
mPositionBuffer = mgr.createVertexBuffer( sizeof(Vector3), w * h, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
mUvBuffer = mgr.createVertexBuffer( sizeof(Vector2), h * w, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
mRenderOp.indexData->indexCount = 6 * (h - 1) * (w - 1);
mRenderOp.indexData->indexStart = 0;
mRenderOp.indexData->indexBuffer = mIndexBuffer;
mRenderOp.vertexData->vertexBufferBinding->setBinding(0, mPositionBuffer);
mRenderOp.vertexData->vertexBufferBinding->setBinding(1, mUvBuffer);
Vector2* pUv = (Vector2*)mUvBuffer->lock(HardwareBuffer::HBL_NORMAL);
for (int i = 0; i < h; ++i)
{
for (int j = 0; j < w; ++ j)
{
*pUv++ = Vector2(j / (float)w, i / (float)h);
}
}
mUvBuffer->unlock();
mBox.setNull();
mBox.merge(Vector3(0, 0, 0));
mBox.merge(Vector3(w - 1, h - 1, 0));
uint32 *pIndex = (uint32*) mIndexBuffer->lock(HardwareBuffer::HBL_NORMAL);
for (int i = 0; i < h - 1; ++i)
{
for (int j = 0; j < w - 1; ++ j)
{
*pIndex++ = i * w + j;
*pIndex++ = i * w + w + j;
*pIndex++ = i * w + w + j + 1;
*pIndex++ = i * w + j;
*pIndex++ = i * w + w + j + 1;
*pIndex++ = i * w + j + 1;
}
}
mIndexBuffer->unlock();
Vector3* pPos = (Vector3*)mPositionBuffer->lock(HardwareBuffer::HBL_NORMAL);
for (int i = 0; i < h; ++i)
{
for (int j = 0; j < w; ++ j)
{
*pPos++ = mParticles[i][j].Position;
}
}
mPositionBuffer->unlock();
for (int i = 0; i < mHeight - 1; ++i)
{
for (int j = 0; j < mWidth - 1; ++ j)
{
Spring s;
s.a = &mParticles[i][j];
s.b = &mParticles[i][j+1];
s.RestLength = 1;
mSprings.push_back(s);
s.b = &mParticles[i+1][j];
mSprings.push_back(s);
s.b = &mParticles[i+1][j+1];
s.RestLength = sqrt(2.0f);
mSprings.push_back(s);
if (j > 0)
{
s.b = &mParticles[i+1][j-1];
mSprings.push_back(s);
}
}
}
}
Cloth::~Cloth()
{
delete mRenderOp.indexData;
delete mRenderOp.vertexData;
}
void Cloth::getRenderOperation(RenderOperation& rend)
{
rend = mRenderOp;
}
Ogre::Real Cloth::getSquaredViewDepth(const Camera* cam) const
{
return mParentNode->getSquaredViewDepth( cam );
}
Ogre::Real Cloth::getBoundingRadius() const
{
return mBox.getHalfSize().length();
}
void Cloth::update(float delta_time)
{
static float mass = 1.0f;
// 应用重力
for (int i = 0; i < mHeight; ++i)
{
for (int j = 0; j < mWidth; ++ j)
{
Particle &p = mParticles[i][j];
if (!p.Fixed)
p.Force = Vector3(0, -1.8, 0);
}
}
// 应用弹簧
std::vector<Spring>::iterator it, iend = mSprings.end();
for (it = mSprings.begin(); it != iend; ++it)
{
it->ApplyConstraints();
}
// 计算新位置
for (int i = 0; i < mHeight; ++i)
{
for (int j = 0; j < mWidth; ++ j)
{
Particle &p = mParticles[i][j];
if (p.Fixed) continue;
Vector3 tmp = p.Position;
p.Position = p.Position + (p.Position - p.OldPosition) * 0.99 + p.Force / mass * delta_time;
p.OldPosition = tmp;
}
}
Vector3* pPos = (Vector3*)mPositionBuffer->lock(HardwareBuffer::HBL_NORMAL);
for (int i = 0; i < mHeight; ++i)
{
for (int j = 0; j < mWidth; ++ j)
{
*pPos++ = mParticles[i][j].Position;
}
}
mPositionBuffer->unlock();
//static float timeStored = 0.0f;
//if (timeStored > TIME_STEPSIZE2)
//{
// timeStored -= TIME_STEPSIZE2;
// mImpl.addForce(Vector3(0, -2.8, 0));
// // 随机风向
// Vector3 wind(Math::UnitRandom(), Math::UnitRandom(), Math::UnitRandom());
// wind.normalise();
// wind *= Math::UnitRandom() * 0.3;
// mImpl.windForce(wind);
// mImpl.timeStep();
// Vector3* pPos = (Vector3*)mPositionBuffer->lock(HardwareBuffer::HBL_NORMAL);
// for (int i = 0; i < mHeight; ++i)
// {
// for (int j = 0; j < mWidth; ++ j)
// {
// *pPos++ = mImpl.getParticle(i,j)->getPos();
// }
// }
// mPositionBuffer->unlock();
//}
//timeStored += delta_time;
}
void Cloth::Spring::ApplyConstraints()
{
assert(a && b);
Vector3 vec = b->Position - a->Position;
float len = vec.length();
Vector3 correctionVec = vec * ( 1 - RestLength / len );
if (! a->Fixed)
a->Position += 0.5 * correctionVec;
if (! b->Fixed)
b->Position -= 0.5 * correctionVec;
}
布料类
最新推荐文章于 2024-08-07 23:49:54 发布