bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("solid ",6); const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u16 indexCount = buffer->getIndexCount(); switch(buffer->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; } file->write("\n",1); } } file->write("endsolid ",9); file->write(name.c_str(),name.size()); return true; }
void CGWIC_Cell::RandomizeTerrain(float subdelta) { IMesh* pMesh = terrain->getMesh(); s32 Q = static_cast<s32> (subdelta); for (u32 n=0; n<pMesh->getMeshBufferCount(); n++) { IMeshBuffer* pMeshBuffer = pMesh->getMeshBuffer(n); if (pMeshBuffer->getVertexType() != EVT_2TCOORDS) continue; S3DVertex2TCoords* pVertices = (S3DVertex2TCoords*)pMeshBuffer->getVertices(); //1. find the current max & min, since we don't want to escalate landscape float max = 0; float min = 256; u32 i; for (i=0; i<(256*256); i++) { if (pVertices[i].Pos.Y < min) min = pVertices[i].Pos.Y; if (pVertices[i].Pos.Y > max) max = pVertices[i].Pos.Y; } std::cout << "RandTerr: min=" << min << "; max=" << max << std::endl; //2. create temp array & randomize it std::vector<float> tmparr; float cy; for (i=0; i<(256*256); i++) { if (Q) { cy = Random_FLOAT(max-min); cy += min; } else cy = 0; tmparr.push_back(cy); } std::cout << std::endl; //3. interpolate vertices inside big quads s32 A = 0; if (Q) A = 256 / Q + 1; for (int qx=0; qx<A; qx++) for (int qy=0; qy<A; qy++) { //TODO: remove unnecessary vars int x0 = qx * Q; int y0 = qy * Q; int xe = x0 + Q; if (xe > 255) xe = 255; int ye = y0 + Q; if (ye > 255) ye = 255; float hx0 = tmparr[x0*256+y0]; float hy0 = (qx%2)? tmparr[xe*256+ye]:hx0; float hxe = tmparr[xe*256+y0]; float hye = tmparr[x0*256+ye]; float lhy = hye - hy0; float lhx = hxe - hx0; for (int cx=x0; cx<xe; cx++) for (int cy=y0; cy<ye; cy++) { float ch = (((qx%2)?(x0-cx):(cx-x0))/lhx)*lhx+hx0; ch += (((qy%2)?(y0-cy):(cy-y0))/lhy)*lhy+hy0; tmparr[cx*256+cy] = ch / 2; } } //4. get result back for (i=0; i<(256*256); i++) pVertices[i].Pos.Y = tmparr[i]; break; } TerrainChanged(); }
float CGWIC_Cell::GetTerrainHeightUnderPointMetric(irr::core::vector3df pnt) { u32 x = floor(pnt.X); u32 z = floor(pnt.Z); if (x > 255) x = 255; if (z > 255) z = 255; u32 index = x * 256 + z; IMesh* pMesh = terrain->getMesh(); float res = 0.f; // float max = 0; const float scy = terrain->getScale().Y; //FIXME: get the true position in meters for (u32 n=0; n<pMesh->getMeshBufferCount(); n++) { IMeshBuffer* pMeshBuffer = pMesh->getMeshBuffer(n); if (pMeshBuffer->getVertexType() != EVT_2TCOORDS) continue; S3DVertex2TCoords* pVertices = (S3DVertex2TCoords*)pMeshBuffer->getVertices(); res = pVertices[index].Pos.Y / scy; // res = (pVertices[index].Pos.Y + terrain->getPosition().Y) / scy; // res += terrain->getPosition().Y / GWIC_IRRUNITS_PER_METER; // std::cerr << "POSIT " << res << std::endl; // for (u32 k=0; k<(256*256); k++) if (pVertices[k].Pos.Y > max) max = pVertices[k].Pos.Y; // std::cerr << "MAXX " << max << std::endl; break; } return res; }
void CTriangleSelector::updateFromMesh(const IMesh* mesh) const { if (!mesh) return; u32 meshBuffers = mesh->getMeshBufferCount(); u32 triangleCount = 0; for (u32 i = 0; i < meshBuffers; ++i) { IMeshBuffer* buf = mesh->getMeshBuffer(i); u32 idxCnt = buf->getIndexCount(); const u16* indices = buf->getIndices(); switch (buf->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buf->getVertices(); for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df & tri = Triangles[triangleCount++]; tri.pointA = vtx[indices[index + 0]].Pos; tri.pointB = vtx[indices[index + 1]].Pos; tri.pointC = vtx[indices[index + 2]].Pos; } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buf->getVertices(); for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df & tri = Triangles[triangleCount++]; tri.pointA = vtx[indices[index + 0]].Pos; tri.pointB = vtx[indices[index + 1]].Pos; tri.pointC = vtx[indices[index + 2]].Pos; } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buf->getVertices(); for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df & tri = Triangles[triangleCount++]; tri.pointA = vtx[indices[index + 0]].Pos; tri.pointB = vtx[indices[index + 1]].Pos; tri.pointC = vtx[indices[index + 2]].Pos; } } break; } } }
//----------------------------------------------------------------------- // e x t r a c t T r i a n g l e s //----------------------------------------------------------------------- btTriangleMesh* TMeshShape::extractTriangles(IMesh* mesh, bool removeDupVertices) { vector3df p1, p2, p3; // 32 bit indices, 3 component vertices - allows for use in decomposition. btTriangleMesh* triMesh = new btTriangleMesh(true, false); u32 bufCount = mesh->getMeshBufferCount(); for(u32 i=0;i<bufCount;i++) { IMeshBuffer* mbuf = mesh->getMeshBuffer(i); void* vp = mbuf->getVertices(); E_VERTEX_TYPE vtype = mbuf->getVertexType(); S3DVertex *vstd = (S3DVertex*) vp; S3DVertex2TCoords *v2t = (S3DVertex2TCoords*) vp; S3DVertexTangents *vtan = (S3DVertexTangents*)vp; const u16* ip = mbuf->getIndices(); u32 ic = mbuf->getIndexCount(); u32 fi = 0; while(fi < ic) { S3DVertex *v1,*v2,*v3; switch(vtype) { case EVT_2TCOORDS: v1 = &v2t[ip[fi++]]; v2 = &v2t[ip[fi++]]; v3 = &v2t[ip[fi++]]; break; case EVT_TANGENTS: v1 = &vtan[ip[fi++]]; v2 = &vtan[ip[fi++]]; v3 = &vtan[ip[fi++]]; break; default: v1 = &vstd[ip[fi++]]; v2 = &vstd[ip[fi++]]; v3 = &vstd[ip[fi++]]; break; } p1 = v1->Pos; p2 = v2->Pos; p3 = v3->Pos; btVector3 b1(p1.X, p1.Y, p1.Z); btVector3 b2(p2.X, p2.Y, p2.Z); btVector3 b3(p3.X, p3.Y, p3.Z); triMesh->addTriangle(b1,b2,b3,removeDupVertices); } } return triMesh; }
bool CGWIC_Cell::SetTerrainHeightUnderPointMetric(irr::core::vector3df pnt, float height, bool update) { u32 x = floor(pnt.X); u32 z = floor(pnt.Z); if (x > 255) x = 255; if (z > 255) z = 255; u32 index = x * 256 + z; IMesh* pMesh = terrain->getMesh(); const float scy = terrain->getScale().Y; for (u32 n=0; n<pMesh->getMeshBufferCount(); n++) { IMeshBuffer* pMeshBuffer = pMesh->getMeshBuffer(n); if (pMeshBuffer->getVertexType() != EVT_2TCOORDS) continue; S3DVertex2TCoords* pVertices = (S3DVertex2TCoords*)pMeshBuffer->getVertices(); pVertices[index].Pos.Y = height * scy; break; } if (update) TerrainChanged(); return true; }
bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("binary ",7); const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); const s32 sizeleft = 73-name.size(); // 80 byte header if (sizeleft<0) file->write(name.c_str(),73); else { char* buf = new char[80]; memset(buf, 0, 80); file->write(name.c_str(),name.size()); file->write(buf,sizeleft); delete [] buf; } u32 facenum = 0; for (u32 j=0; j<mesh->getMeshBufferCount(); ++j) facenum += mesh->getMeshBuffer(j)->getIndexCount()/3; file->write(&facenum,4); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u16 indexCount = buffer->getIndexCount(); switch(buffer->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; } } } return true; }
//! draws the element and its children void CGUIMeshViewer::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); IVideoDriver* driver = Environment->getVideoDriver(); rect<SINT32> viewPort = AbsoluteRect; viewPort.LowerRightCorner.x -= 1; viewPort.LowerRightCorner.y -= 1; viewPort.UpperLeftCorner.x += 1; viewPort.UpperLeftCorner.y += 1; viewPort.clipAgainst(AbsoluteClippingRect); // draw the frame rect<SINT32> frameRect(AbsoluteRect); frameRect.LowerRightCorner.y = frameRect.UpperLeftCorner.y + 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), frameRect, &AbsoluteClippingRect); frameRect.LowerRightCorner.y = AbsoluteRect.LowerRightCorner.y; frameRect.LowerRightCorner.x = frameRect.UpperLeftCorner.x + 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), frameRect, &AbsoluteClippingRect); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.x = frameRect.LowerRightCorner.x - 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.y = AbsoluteRect.LowerRightCorner.y - 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); // draw the mesh if (Mesh) { //TODO: if outside of screen, dont draw. // - why is the absolute clipping rect not already the screen? rect<SINT32> oldViewPort = driver->getViewPort(); driver->setViewPort(viewPort); Matrix4 mat; //CameraControl->calculateProjectionMatrix(mat); //driver->setTransform(TS_PROJECTION, mat); mat = Matrix4::IDENTITY; mat.setTrans(Vector3(0, 0, 0)); //mat.setTranslation(Vector3(0, 0, 0)); driver->setTransform(ETS_WORLD, mat); //CameraControl->calculateViewMatrix(mat); //driver->setTransform(TS_VIEW, mat); driver->setMaterial(Material); UINT32 frame = 0; if (Mesh->getFrameCount()) frame = (Timer::getTime() / 20) % Mesh->getFrameCount(); const IMesh* const m = Mesh->getMesh(frame); for (UINT32 i = 0; i<m->getMeshBufferCount(); ++i) { IMeshBuffer* mb = m->getMeshBuffer(i); driver->drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getIndexCount() / 3, mb->getVertexType(), EPT_TRIANGLES, mb->getIndexType()); } driver->setViewPort(oldViewPort); } IGUIElement::draw(); }
//! sets the mesh from which the shadow volume should be generated. void CShadowVolumeSceneNode::setMeshToRenderFrom(IMesh* mesh) { ShadowVolumesUsed = 0; s32 oldIndexCount = IndexCount; s32 oldVertexCount = VertexCount; VertexCount = 0; IndexCount = 0; if (!mesh) return; // calculate total amount of vertices and indices u32 i; s32 totalVertices = 0; s32 totalIndices = 0; u32 bufcnt = mesh->getMeshBufferCount(); IMeshBuffer* b; for (i=0; i<bufcnt; ++i) { b = mesh->getMeshBuffer(i); totalIndices += b->getIndexCount(); totalVertices += b->getVertexCount(); } // allocate memory if nececcary if (totalVertices > VertexCountAllocated) { delete [] Vertices; Vertices = new core::vector3df[totalVertices]; VertexCountAllocated = totalVertices; } if (totalIndices > IndexCountAllocated) { delete [] Indices; Indices = new u16[totalIndices]; IndexCountAllocated = totalIndices; if (UseZFailMethod) { delete [] FaceData; FaceData = new bool[totalIndices / 3]; } } // copy mesh for (i=0; i<bufcnt; ++i) { b = mesh->getMeshBuffer(i); s32 idxcnt = b->getIndexCount(); s32 vtxnow = VertexCount; const u16* idxp = b->getIndices(); const u16* idxpend = idxp + idxcnt; for (; idxp!=idxpend; ++idxp) Indices[IndexCount++] = *idxp + vtxnow; s32 vtxcnt = b->getVertexCount(); switch(b->getVertexType()) { case video::EVT_STANDARD: { const video::S3DVertex* vp = (video::S3DVertex*)b->getVertices(); const video::S3DVertex* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; case video::EVT_2TCOORDS: { const video::S3DVertex2TCoords* vp = (video::S3DVertex2TCoords*)b->getVertices(); const video::S3DVertex2TCoords* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; case video::EVT_TANGENTS: { const video::S3DVertexTangents* vp = (video::S3DVertexTangents*)b->getVertices(); const video::S3DVertexTangents* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; } } // recalculate adjacency if neccessarry if (oldVertexCount != VertexCount && oldIndexCount != IndexCount && UseZFailMethod) calculateAdjacency(); // create as much shadow volumes as there are lights but // do not ignore the max light settings. u32 lights = SceneManager->getVideoDriver()->getDynamicLightCount(); core::matrix4 mat = Parent->getAbsoluteTransformation(); core::vector3df parentpos = Parent->getAbsolutePosition(); core::vector3df lpos; mat.makeInverse(); for (i=0; i<lights; ++i) { const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i); lpos = dl.Position; if (dl.CastShadows && fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f)) { mat.transformVect(lpos); createShadowVolume(lpos); } } }