Commit 0760b479 authored by hybrid's avatar hybrid

Fixed the texture mapping of the sphere scene node. It is now wrapped by one...

Fixed the texture mapping of the sphere scene node. It is now wrapped by one texture without artifacts. Also made x and y subdivison separately adjustable when calling the constructor manually.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@669 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 5180ee88
...@@ -330,7 +330,7 @@ ISceneNode* CSceneManager::addSphereSceneNode(f32 radius, s32 polyCount, ISceneN ...@@ -330,7 +330,7 @@ ISceneNode* CSceneManager::addSphereSceneNode(f32 radius, s32 polyCount, ISceneN
if (!parent) if (!parent)
parent = this; parent = this;
ISceneNode* node = new CSphereSceneNode(radius, polyCount, parent, this, id, position, rotation, scale); ISceneNode* node = new CSphereSceneNode(radius, polyCount, polyCount, parent, this, id, position, rotation, scale);
node->drop(); node->drop();
return node; return node;
......
...@@ -54,7 +54,7 @@ namespace scene ...@@ -54,7 +54,7 @@ namespace scene
virtual ISceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, virtual ISceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1,
const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
//! Adds a sphere scene node for test purposes to the scene. //! Adds a sphere scene node to the scene.
virtual ISceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1, virtual ISceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1,
const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0),
......
...@@ -14,10 +14,10 @@ namespace scene ...@@ -14,10 +14,10 @@ namespace scene
{ {
//! constructor //! constructor
CSphereSceneNode::CSphereSceneNode(f32 Radius, s32 polyCount, ISceneNode* parent, ISceneManager* mgr, s32 id, CSphereSceneNode::CSphereSceneNode(f32 Radius, u32 polyCountX, u32 polyCountY, ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale)
: ISceneNode(parent, mgr, id, position, rotation, scale), Radius(Radius), : ISceneNode(parent, mgr, id, position, rotation, scale), Radius(Radius),
PolyCount(polyCount) PolyCountX(polyCountX), PolyCountY(polyCountY)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CSphereSceneNode"); setDebugName("CSphereSceneNode");
...@@ -41,57 +41,58 @@ void CSphereSceneNode::setSizeAndPolys() ...@@ -41,57 +41,58 @@ void CSphereSceneNode::setSizeAndPolys()
// we are creating the sphere mesh here. // we are creating the sphere mesh here.
if (PolyCount < 2) if (PolyCountX < 2)
PolyCount = 2; PolyCountX = 2;
else if (PolyCountY < 2)
if (PolyCount > 181) // prevent u16 overflow PolyCountY = 2;
PolyCount = 181; if (PolyCountX * PolyCountY > 32767) // prevent u16 overflow
if (PolyCountX > PolyCountY) // prevent u16 overflow
PolyCountX = 32767/PolyCountY-1;
else
PolyCountY = 32767/(PolyCountX+1);
Buffer.Vertices.set_used((PolyCount * PolyCount) + 2); u32 PolyCountXPitch = PolyCountX+1; // get to same vertex on next level
Buffer.Indices.set_used((PolyCount * PolyCount) * 6); Buffer.Vertices.set_used((PolyCountXPitch * PolyCountY) + 2);
Buffer.Indices.set_used((PolyCountX * PolyCountY) * 6);
video::SColor clr(100, 255,255,255); video::SColor clr(100, 255,255,255);
int i=0; u32 i=0;
int level = 0; u32 level = 0;
for (int p1=0; p1<PolyCount-1; ++p1) for (u32 p1 = 0; p1 < PolyCountY-1; ++p1)
{ {
level = p1 * PolyCount; //main quads, top to bottom
int p2; for (u32 p2 = 0; p2 < PolyCountX - 1; ++p2)
for (p2 = 0; p2 < PolyCount - 1; ++p2)
{ {
Buffer.Indices[i] = level + p2 + PolyCount; const u32 curr = level + p2;
Buffer.Indices[++i] = level + p2; Buffer.Indices[i] = curr + PolyCountXPitch;
Buffer.Indices[++i] = level + p2 + 1; Buffer.Indices[++i] = curr;
Buffer.Indices[++i] = curr + 1;
Buffer.Indices[++i] = curr + PolyCountXPitch;
Buffer.Indices[++i] = curr+1;
Buffer.Indices[++i] = curr + 1 + PolyCountXPitch;
++i; ++i;
} }
Buffer.Indices[i] = level + PolyCount - 1 + PolyCount; // the connectors from front to end
Buffer.Indices[++i] = level + PolyCount - 1; Buffer.Indices[i] = level + PolyCountX - 1 + PolyCountXPitch;
Buffer.Indices[++i] = level; Buffer.Indices[++i] = level + PolyCountX - 1;
Buffer.Indices[++i] = level + PolyCountX;
++i; ++i;
Buffer.Indices[i] = level + PolyCount - 1 + PolyCount; Buffer.Indices[i] = level + PolyCountX - 1 + PolyCountXPitch;
Buffer.Indices[++i] = level; Buffer.Indices[++i] = level + PolyCountX;
Buffer.Indices[++i] = level + PolyCount; Buffer.Indices[++i] = level + PolyCountX + PolyCountXPitch;
++i; ++i;
level += PolyCountXPitch;
for (p2 = 1; p2 <= PolyCount - 1; ++p2)
{
Buffer.Indices[i] = level + p2 - 1 + PolyCount;
Buffer.Indices[++i] = level + p2;
Buffer.Indices[++i] = level + p2 + PolyCount;
++i;
}
} }
int PolyCountSq = PolyCount * PolyCount; const u32 PolyCountSq = PolyCountXPitch * PolyCountY; // top point
int PolyCountSq1 = PolyCountSq + 1; const u32 PolyCountSq1 = PolyCountSq + 1; // bottom point
int PolyCountSqM1 = (PolyCount - 1) * PolyCount; const u32 PolyCountSqM1 = (PolyCountY - 1) * PolyCountXPitch; // last row's first vertex
for (int p2 = 0; p2 < PolyCount - 1; ++p2) for (u32 p2 = 0; p2 < PolyCountX - 1; ++p2)
{ {
// create triangles which are at the top of the sphere // create triangles which are at the top of the sphere
...@@ -108,57 +109,71 @@ void CSphereSceneNode::setSizeAndPolys() ...@@ -108,57 +109,71 @@ void CSphereSceneNode::setSizeAndPolys()
++i; ++i;
} }
// create a triangle which is at the top of the sphere // create final triangle which is at the top of the sphere
Buffer.Indices[i] = PolyCountSq; Buffer.Indices[i] = PolyCountSq;
Buffer.Indices[++i] = 0; Buffer.Indices[++i] = PolyCountX;
Buffer.Indices[++i] = PolyCount - 1; Buffer.Indices[++i] = PolyCountX-1;
++i; ++i;
// create a triangle which is at the bottom of the sphere // create final triangle which is at the bottom of the sphere
Buffer.Indices[i] = PolyCountSqM1 + PolyCount - 1; Buffer.Indices[i] = PolyCountSqM1 + PolyCountX - 1;
Buffer.Indices[++i] = PolyCountSqM1; Buffer.Indices[++i] = PolyCountSqM1;
Buffer.Indices[++i] = PolyCountSq1; Buffer.Indices[++i] = PolyCountSq1;
// calculate the angle which separates all points in a circle // calculate the angle which separates all points in a circle
const f64 Angle = 2 * core::PI / PolyCount; const f64 AngleX = 2 * core::PI / PolyCountX;
const f64 AngleY = core::PI / PolyCountY;
i = 0; i = 0;
f64 axz; f64 axz;
// we don't start at 0. // we don't start at 0.
f64 ay = -Angle / 4; f64 ay = 0;//AngleY / 2;
for (int y = 0; y < PolyCount; ++y) for (u32 y = 0; y < PolyCountY; ++y)
{ {
ay += Angle / 2; ay += AngleY;
const f64 sinay = sin(ay);
axz = 0; axz = 0;
for (int xz = 0;xz < PolyCount; ++xz) // calculate the necessary vertices without the doubled one
for (u32 xz = 0;xz < PolyCountX; ++xz)
{ {
// calculate points position // calculate points position
axz += Angle;
const f64 sinay = sin(ay);
const core::vector3df pos(Radius * cos(axz) * sinay, const core::vector3df pos(Radius * cos(axz) * sinay,
Radius * cos(ay), Radius * cos(ay),
Radius * sin(axz) * sinay); Radius * sin(axz) * sinay);
// for spheres the normal is the position
core::vector3df normal(pos); core::vector3df normal(pos);
normal.normalize(); normal.normalize();
// calculate texture coordinates via sphere mapping
// tu is the same on each level, so only calculate once
f32 tu = 0.5f; f32 tu = 0.5f;
if (normal.Y != -1.0f && normal.Y != 1.0f) if (y==0)
tu = (f32)(acos(core::clamp(normal.X/sinay, -1.0, 1.0)) * 0.5 *core::RECIPROCAL_PI64); {
if (normal.Y != -1.0f && normal.Y != 1.0f)
tu = (f32)(acos(core::clamp(normal.X/sinay, -1.0, 1.0)) * 0.5 *core::RECIPROCAL_PI64);
if (normal.Z < 0.0f)
tu=1-tu;
}
else
tu = Buffer.Vertices[i-PolyCountXPitch].TCoords.X;
Buffer.Vertices[i] = video::S3DVertex(pos.X, pos.Y, pos.Z, Buffer.Vertices[i] = video::S3DVertex(pos.X, pos.Y, pos.Z,
normal.X, normal.Y, normal.Z, normal.X, normal.Y, normal.Z,
clr, clr, tu,
(normal.Z > 0.0f)?tu:1-tu,
(f32)(ay*core::RECIPROCAL_PI64)); (f32)(ay*core::RECIPROCAL_PI64));
++i; ++i;
axz += AngleX;
} }
// This is the doubled vertex on the initial position
Buffer.Vertices[i] = video::S3DVertex(Buffer.Vertices[i-PolyCountX]);
Buffer.Vertices[i].TCoords.X=1.0f;
++i;
} }
// the vertex at the top of the sphere // the vertex at the top of the sphere
...@@ -242,7 +257,8 @@ void CSphereSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeR ...@@ -242,7 +257,8 @@ void CSphereSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeR
ISceneNode::serializeAttributes(out, options); ISceneNode::serializeAttributes(out, options);
out->addFloat("Radius", Radius); out->addFloat("Radius", Radius);
out->addInt("PolyCount", PolyCount); out->addInt("PolyCountX", PolyCountX);
out->addInt("PolyCountY", PolyCountY);
} }
...@@ -250,14 +266,20 @@ void CSphereSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeR ...@@ -250,14 +266,20 @@ void CSphereSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeR
void CSphereSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) void CSphereSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{ {
f32 oldRadius = Radius; f32 oldRadius = Radius;
s32 oldPolyCount = PolyCount; u32 oldPolyCountX = PolyCountX;
u32 oldPolyCountY = PolyCountY;
Radius = in->getAttributeAsFloat("Radius"); Radius = in->getAttributeAsFloat("Radius");
PolyCount = in->getAttributeAsInt("PolyCount"); PolyCountX = in->getAttributeAsInt("PolyCountX");
PolyCountY = in->getAttributeAsInt("PolyCountY");
// legacy values read for compatibility with older versions
u32 polyCount = in->getAttributeAsInt("PolyCount");
if (PolyCountX ==0 && PolyCountY == 0)
PolyCountX = PolyCountY = polyCount;
Radius = irr::core::max_(Radius, 0.0001f); Radius = irr::core::max_(Radius, 0.0001f);
if ( !core::equals(Radius, oldRadius) || PolyCount != oldPolyCount) if ( !core::equals(Radius, oldRadius) || PolyCountX != oldPolyCountX || PolyCountY != oldPolyCountY)
setSizeAndPolys(); setSizeAndPolys();
ISceneNode::deserializeAttributes(in, options); ISceneNode::deserializeAttributes(in, options);
...@@ -269,7 +291,7 @@ ISceneNode* CSphereSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan ...@@ -269,7 +291,7 @@ ISceneNode* CSphereSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan
if (!newParent) newParent = Parent; if (!newParent) newParent = Parent;
if (!newManager) newManager = SceneManager; if (!newManager) newManager = SceneManager;
CSphereSceneNode* nb = new CSphereSceneNode(Radius, PolyCount, newParent, CSphereSceneNode* nb = new CSphereSceneNode(Radius, PolyCountX, PolyCountY, newParent,
newManager, ID, RelativeTranslation); newManager, ID, RelativeTranslation);
nb->cloneMembers(this, newManager); nb->cloneMembers(this, newManager);
......
...@@ -17,7 +17,7 @@ namespace scene ...@@ -17,7 +17,7 @@ namespace scene
public: public:
//! constructor //! constructor
CSphereSceneNode(f32 size, s32 polyCount, ISceneNode* parent, ISceneManager* mgr, s32 id, CSphereSceneNode(f32 size, u32 polyCountX, u32 polyCountY, ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
...@@ -61,7 +61,8 @@ namespace scene ...@@ -61,7 +61,8 @@ namespace scene
SMeshBuffer Buffer; SMeshBuffer Buffer;
f32 Radius; f32 Radius;
s32 PolyCount; u32 PolyCountX;
u32 PolyCountY;
}; };
} // end namespace scene } // end namespace scene
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment