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 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; } } }
f32 TerrainTile::getVerticeHeight(vector3df pos) { f32 radius = 100; f32 returnvalue = 0; f32 smallest = radius; IMeshBuffer* meshBuffer = ((IMeshSceneNode*)node)->getMesh()->getMeshBuffer(0); S3DVertex* mb_vertices = (S3DVertex*) meshBuffer->getVertices(); u16* mb_indices = meshBuffer->getIndices(); //Check all indices in the mesh to find the one that is nearest the position for (unsigned int j = 0; j < meshBuffer->getVertexCount(); j += 1) { vector3df realPos = mb_vertices[j].Pos*(scale/nodescale) + node->getPosition(); pos.Y = realPos.Y; //Put the height at the same height //Check if its the smallest distance if((realPos.getDistanceFrom(pos) < smallest)) { smallest = realPos.getDistanceFrom(pos); returnvalue = realPos.Y; } } return returnvalue; }
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; }
ConvexHull::ConvexHull(ISceneNode *irrobject, double mass) :PhysicalObject(irrobject, mass) { IMeshBuffer* mbuffer = ((IAnimatedMeshSceneNode*)irrobject)->getMesh()->getMeshBuffer(0); int numVertices = mbuffer->getVertexCount(); btVector3 vertexBase[numVertices]; S3DVertex* vertices = (S3DVertex*)(mbuffer->getVertices()); vector3df scale = irrobject->getScale(); btConvexHullShape* chshape = new btConvexHullShape(); for(int i = 0; i < numVertices; i++) { vertexBase[i].setX((float)(vertices[i].Pos.X * scale.X)); vertexBase[i].setY((float)(vertices[i].Pos.Y * scale.Y)); vertexBase[i].setZ((float)(vertices[i].Pos.Z * scale.Z)); chshape->addPoint(vertexBase[i]); } initialize(chshape); }
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(); }
//----------------------------------------------------------------------- // 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; }
void TerrainTile::mergeToTile(TerrainTile* tile) { if(!tile || custom) { #ifdef DEBUG cout << "DEBUG : TERRAIN TILE : MERGE FAILED, TILE IS NULL: " << endl; #endif return; } else { IMeshBuffer* meshBuffer = ((IMeshSceneNode*)node)->getMesh()->getMeshBuffer(0); IMeshBuffer* neighborBuffer = tile->getMeshBuffer(); S3DVertex* mb_vertices = (S3DVertex*) meshBuffer->getVertices(); S3DVertex* n_mb_vertices = (S3DVertex*) neighborBuffer->getVertices(); u16* mb_indices = meshBuffer->getIndices(); u16* n_mb_indices = neighborBuffer->getIndices(); for (unsigned int j = 0; j < meshBuffer->getVertexCount(); j += 1) { for (unsigned int i = 0; i < neighborBuffer->getVertexCount(); i += 1) { vector3df realPos = mb_vertices[j].Pos*(scale/nodescale) + node->getPosition(); vector3df nRealPos = n_mb_vertices[i].Pos*(scale/nodescale) + tile->getNode()->getPosition(); if((realPos.X == nRealPos.X) && (realPos.Z == nRealPos.Z)) { mb_vertices[j].Pos.Y = n_mb_vertices[i].Pos.Y; mb_vertices[j].Normal = n_mb_vertices[i].Normal; //New Copy the normal information needrecalc=true; } } } //smgr->getMeshManipulator()->recalculateNormals(((IMeshSceneNode*)node)->getMesh(),true); ((IMeshSceneNode*)node)->getMesh()->setDirty(); needrecalc = true; } }
void TerrainTile::restoreUndo() { if (undohistory.size()>0) { IMeshBuffer* meshBuffer = ((IMeshSceneNode*)node)->getMesh()->getMeshBuffer(0); S3DVertex* mb_vertices = (S3DVertex*)meshBuffer->getVertices(); u16* mb_indices = meshBuffer->getIndices(); printf("Here is the undo history size: %i\n", undohistory.size()); undobuffer = undohistory.back(); printf("Here is the undo buffer size: %i\n", undobuffer.size()); for (unsigned int j = 0; j < undohistory[undohistory.size()-1].size(); j += 1) { mb_vertices[j].Pos.Y = undohistory[undohistory.size() - 1][j]; } meshBuffer = ((IMeshSceneNode*)ocean)->getMesh()->getMeshBuffer(0); mb_vertices = (S3DVertex*)meshBuffer->getVertices(); mb_indices = meshBuffer->getIndices(); for (unsigned int j = 0; j < undohistory[undohistory.size() - 1].size(); j += 1) { mb_vertices[j].Pos.Y = undohistory[undohistory.size() - 1][j]; } needrecalc = true; recalculate(); undohistory.pop_back(); //Remove the last element of the vector by 1; undobuffer.clear(); //Clear the buffer; } }
void TerrainTile::transformMeshToValue(vector3df clickPos, f32 radius, f32 radius2, f32 strength, f32 value, bool norecalc) { if (custom) return; if(strength<0) strength = -strength; IMeshBuffer* meshBuffer = ((IMeshSceneNode*)node)->getMesh()->getMeshBuffer(0); S3DVertex* mb_vertices = (S3DVertex*) meshBuffer->getVertices(); u16* mb_indices = meshBuffer->getIndices(); for (unsigned int j = 0; j < meshBuffer->getVertexCount(); j += 1) { vector3df realPos = mb_vertices[j].Pos*(scale/nodescale) + node->getPosition(); clickPos.Y = realPos.Y; if(realPos.getDistanceFrom(clickPos) < radius) { needrecalc=true; //f32 ratio = sin(radius - realPos.getDistanceFrom(clickPos)); f32 ratio = radius; if (radius2-realPos.getDistanceFrom(clickPos)<0) ratio = (radius+radius2)-realPos.getDistanceFrom(clickPos); if(mb_vertices[j].Pos.Y > value) { //mb_vertices[j].Pos.Y -= strength * ratio / (scale/nodescale); mb_vertices[j].Pos.Y -= strength * ratio / (scale/nodescale); if(mb_vertices[j].Pos.Y <= value) mb_vertices[j].Pos.Y = value; } if(mb_vertices[j].Pos.Y < value) { //mb_vertices[j].Pos.Y += strength * ratio / (scale / nodescale); mb_vertices[j].Pos.Y += strength *ratio / (scale / nodescale); if(mb_vertices[j].Pos.Y >= value) mb_vertices[j].Pos.Y = value; } } } if (norecalc) { recalculate(true); } else recalculate(); }
void TerrainTile::storeUndo() { IMeshBuffer* meshBuffer = ((IMeshSceneNode*)node)->getMesh()->getMeshBuffer(0); S3DVertex* mb_vertices = (S3DVertex*)meshBuffer->getVertices(); u16* mb_indices = meshBuffer->getIndices(); for (unsigned int j = 0; j < meshBuffer->getVertexCount(); j += 1) { undobuffer.push_back(mb_vertices[j].Pos.Y); } undohistory.push_back(undobuffer); undobuffer.clear(); }
void TerrainTile::transformMesh(vector3df clickPos, f32 radius, f32 radius2, f32 strength, bool norecalc) { if (custom) return; IMeshBuffer* meshBuffer = ((IMeshSceneNode*)node)->getMesh()->getMeshBuffer(0); S3DVertex* mb_vertices = (S3DVertex*) meshBuffer->getVertices(); u16* mb_indices = meshBuffer->getIndices(); for (unsigned int j = 0; j < meshBuffer->getVertexCount(); j += 1) { vector3df realPos = mb_vertices[j].Pos*(scale/nodescale) + node->getPosition(); clickPos.Y = realPos.Y; if(realPos.getDistanceFrom(clickPos) < radius) { needrecalc=true; // This will flag the tile since it's in the radius and will modify the tile vertices. //f32 ratio = sin(radius - realPos.getDistanceFrom(clickPos)); //- (realPos.getDistanceFrom(clickPos)-radius2) f32 ratio = radius; if (radius2-realPos.getDistanceFrom(clickPos)<0) ratio = (radius+radius2)-realPos.getDistanceFrom(clickPos); mb_vertices[j].Pos.Y += (strength * (ratio)/(scale/nodescale)); //printf("found something here: vertice %i, vertice Y: %f\n",j, mb_vertices[j].Pos.Y); } //if(mb_vertices[j].Pos.Y > nodescale/4) mb_vertices[j].Pos.Y = nodescale/4; // Fix up/down limits if(mb_vertices[j].Pos.Y > nodescale*0.75f) mb_vertices[j].Pos.Y = nodescale*0.75f; if(mb_vertices[j].Pos.Y < -(nodescale*0.25f)) mb_vertices[j].Pos.Y = -(nodescale*0.25f); } if (norecalc) { recalculate(true); } else recalculate(); }
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; }
// Test the tile if it was being modified bool TerrainTile::checkModified() { bool modified = false; IMeshBuffer* meshBuffer = ((IMeshSceneNode*)node)->getMesh()->getMeshBuffer(0); S3DVertex* mb_vertices = (S3DVertex*) meshBuffer->getVertices(); for (unsigned int j = 0; j < meshBuffer->getVertexCount(); j += 1) { vector3df realPos = mb_vertices[j].Pos*(scale/nodescale) + node->getPosition(); if(realPos.Y != 0.0f ) { modified = true; j=meshBuffer->getVertexCount(); break; } } return modified; }
void CPlanarShadow::buildMesh(IMesh*mesh) { s32 i; s32 totalVertices = 0; s32 totalIndices = 0; s32 bufcnt = mesh->getMeshBufferCount(); IMeshBuffer* b; int vtxNow = 0; for (i=0; i<bufcnt; ++i) { IMeshBuffer* b; b = mesh->getMeshBuffer(i); video::S3DVertex* vtxbuff = (video::S3DVertex*)b->getVertices(); for(int o = 0; o < b->getVertexCount(); o++) Vertices[vtxNow++] = vtxbuff[o].Pos; } }
//! 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); } } }
//! 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(); }
//! creates the tree bool COctTreeSceneNode::createTree(IMesh* mesh) { if (!mesh) return false; MeshName = SceneManager->getMeshCache()->getMeshFilename( mesh ); deleteTree(); u32 beginTime = os::Timer::getRealTime(); u32 nodeCount = 0; u32 polyCount = 0; Box = mesh->getBoundingBox(); if (mesh->getMeshBufferCount()) { vertexType = mesh->getMeshBuffer(0)->getVertexType(); switch(vertexType) { case video::EVT_STANDARD: { for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); StdMeshes.push_back(OctTree<video::S3DVertex>::SMeshChunk()); OctTree<video::S3DVertex>::SMeshChunk &nchunk = StdMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); for (v=0; v<b->getVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; v<b->getIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } StdOctTree = new OctTree<video::S3DVertex>(StdMeshes, MinimalPolysPerNode); nodeCount = StdOctTree->getNodeCount(); } break; case video::EVT_2TCOORDS: { for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); LightMapMeshes.push_back(OctTree<video::S3DVertex2TCoords>::SMeshChunk()); OctTree<video::S3DVertex2TCoords>::SMeshChunk& nchunk = LightMapMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); for (v=0; v<b->getVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; v<b->getIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } LightMapOctTree = new OctTree<video::S3DVertex2TCoords>(LightMapMeshes, MinimalPolysPerNode); nodeCount = LightMapOctTree->getNodeCount(); } break; case video::EVT_TANGENTS: { for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); TangentsMeshes.push_back(OctTree<video::S3DVertexTangents>::SMeshChunk()); OctTree<video::S3DVertexTangents>::SMeshChunk& nchunk = TangentsMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); for (v=0; v<b->getVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; v<b->getIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } TangentsOctTree = new OctTree<video::S3DVertexTangents>(TangentsMeshes, MinimalPolysPerNode); nodeCount = TangentsOctTree->getNodeCount(); } break; } } u32 endTime = os::Timer::getRealTime(); c8 tmp[255]; sprintf(tmp, "Needed %ums to create OctTree SceneNode.(%u nodes, %u polys)", endTime - beginTime, nodeCount, polyCount/3); os::Printer::log(tmp, ELL_INFORMATION); 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; }
Vegetation* TerrainTile::paintVegetation(vector3df clickPos, bool erase) { //Do a prior check to see if there is a least one tree active in the list of active objects vector<bool> enabled=VegetationSeed::getInstance()->getEnabled(); vector<int> newlist; for(int i = 0; i<(int)enabled.size(); i++) { if (enabled[i]==true) newlist.push_back(i); //New list will contain the list of the enabled items } if (newlist.size()==0) return NULL; IMeshBuffer* meshBuffer = ((IMeshSceneNode*)node)->getMesh()->getMeshBuffer(0); S3DVertex* mb_vertices = (S3DVertex*) meshBuffer->getVertices(); u16* mb_indices = meshBuffer->getIndices(); Vegetation* returnvalue = NULL; for (unsigned int j = 0; j < meshBuffer->getVertexCount(); j += 1) { if(erase) { vector3df realPos = vector3df (0.0f,0.0f,0.0f); //Should be able to place a tree anywhere on a custom model if (!custom) realPos = mb_vertices[j].Pos*(scale/nodescale) + node->getPosition(); else realPos = clickPos; clickPos.Y = realPos.Y; if(realPos.getDistanceFrom(clickPos) < vegetationRange/2 && getVegetationAt(vector3df(realPos.X,realPos.Y,realPos.Z))) { Vegetation* toRemove = getVegetationAt(vector3df(realPos.X,realPos.Y,realPos.Z)); returnvalue = toRemove; return returnvalue; // Done outside the function (caller will do the removal) } } else { vector3df realPos = vector3df (0.0f,0.0f,0.0f); //Should be able to place a tree anywhere on a custom model if (!custom) realPos = mb_vertices[j].Pos*(scale/nodescale) + node->getPosition(); else realPos = clickPos; clickPos.Y = realPos.Y; if(realPos.getDistanceFrom(clickPos) < (vegetationRange/2) && !getVegetationAt(vector3df(realPos.X,realPos.Y,realPos.Z))) { Vegetation* v = new Vegetation(); //v->setPosition(vector3df(realPos.X + (rand()%5)*0.1f - 0.25f,realPos.Y/(scale/nodescale),realPos.Z + (rand()%5)*0.1f - 0.25f)); //v->setPosition(vector3df(realPos.X + (rand()%5)*scale/100,realPos.Y,realPos.Z + (rand()%5)*scale/100)); v->setPosition(vector3df(realPos.X,realPos.Y,realPos.Z)); f32 treesize = (f32)(rand() % 50 + 25); f32 treerot = (f32)(rand() % 1 + 359); v->setScale(vector3df(treesize,treesize,treesize)); v->setRotation(vector3df(0,treerot,0)); #ifdef DEBUG printf("Attempting to place a tree with this size: %f\n",treesize); #endif vegetationVector.push_back(v); returnvalue = v; return returnvalue; #ifdef APP_DEBUG cout << "DEBUG : TERRAIN TILE : VEGETATION CREATED: " << realPos.X << "," << realPos.Y << "," << realPos.Z << " TOTAL:" << vegetationVector.size() << endl; #endif } } } return returnvalue; }
// ISoftBody::createShape() is taken from code found on the Irrlicht forum void ISoftBody::createShape(IMesh* const collMesh) { int cMeshBuffer, j; IMeshBuffer *mb; video::S3DVertex* mb_vertices; u16* mb_indices; std::map<int, int> index_map; std::map<int, int> bullet_map; std::map<int, S3DVertex> vertex_map; int count = 0; indexCount = 0; vertexCount = 0; for(cMeshBuffer=0; cMeshBuffer < 1; cMeshBuffer++) { //printf("Loading new mesh buffer for softbody.\n"); mb = collMesh->getMeshBuffer(cMeshBuffer); mb_vertices = (irr::video::S3DVertex*)mb->getVertices(); mb_indices = mb->getIndices(); indexCount += mb->getIndexCount(); vertexCount += mb->getVertexCount(); for(u32 i=0; i<mb->getIndexCount(); i++) { int iIndex = mb_indices[i]; vector3df iVertex = mb_vertices[iIndex].Pos; bool isFirst = true; for(u32 j=0; j<i; j++) { int jIndex = mb_indices[j]; vector3df jVertex = mb_vertices[jIndex].Pos; if (iVertex == jVertex) { index_map.insert(std::make_pair(i, j)); isFirst = false; break; } } // ???????Bullet??Index?????? if(isFirst) { // Irrlicht?Index??????Index index_map.insert(std::make_pair(i, i)); // ?????Index????Index bullet_map.insert(std::make_pair(i, count)); // ??Index????????? vertex_map.insert(std::make_pair(count, mb_vertices[iIndex])); count++; } } } indices = new int[indexCount]; vertexCount = vertex_map.size(); vertices = new btScalar[vertexCount*3]; for(j=0; j<indexCount; j++) { int index1 = index_map.find(j)->second; int index2 = bullet_map.find(index1)->second; indices[j] = index2; } for(j=0; j<vertexCount; j++) { vertices[3*j] = vertex_map[j].Pos.X; vertices[3*j+1] = vertex_map[j].Pos.Y; vertices[3*j+2] = -vertex_map[j].Pos.Z; } //std::cout << "create softbody" << std::endl; object = btSoftBodyHelpers::CreateFromTriMesh( dynamicsWorld->getSoftBodyWorldInfo(), vertices,indices, indexCount/3); //std::cout << "create map" << std::endl; for(int i=0; i<getPointer()->m_faces.size(); i++) { btSoftBody::Face face = getPointer()->m_faces[i]; for(int j=0; j<3; j++) { if(node_map.find(face.m_n[j]) == node_map.end()) { node_map.insert(std::make_pair(face.m_n[j], node_map.size())); } } for(int j=0; j<3; j++) { m_indices.push_back(node_map.find(face.m_n[j])->second); } } // Reverse node->index to index->node (should be unique on both sides) std::map<btSoftBody::Node*, int>::const_iterator node_iter; for(node_iter = node_map.begin(); node_iter != node_map.end(); ++node_iter) { m_vertices.insert(std::make_pair(node_iter->second, node_iter->first)); } //std::cout << "update Irrlicht vertices" << std::endl; std::map<int, btSoftBody::Node*>::const_iterator it; for(u32 i=0; i<mb->getVertexCount(); i++) { for(it=m_vertices.begin(); it != m_vertices.end(); ++it) { int v_index = it->first; btSoftBody::Node* node = it->second; if(node->m_x.x() == mb_vertices[i].Pos.X && node->m_x.y() == mb_vertices[i].Pos.Y && node->m_x.z() == mb_vertices[i].Pos.Z) { MeshMap.insert(std::make_pair(i, v_index)); break; } } } }