void CCullingSystem::initializeOccluders() { static core::array<SOccluderEntry> occluders_tmp; occluders_tmp.set_used(0); m_Occluders.sort(); for (u32 i=0; i<m_Occluders.size(); i++) { bool occluded = false; for (u32 j=i+1; j<m_Occluders.size(); j++) { if (m_Occluders[j].isOccludeByPlanes(m_Occluders[i].tbbox)) { occluded = true; break; } } if (!occluded) { occluders_tmp.push_back(m_Occluders[i]); } } m_Occluders.set_used(0); m_Occluders = occluders_tmp; }
void CCal3DSceneNode::render() { //----------------------------------------------------------// if ( calModel == 0 ) return; // Make sure there is a model to render //----------------------------------------------------------// video::IVideoDriver* driver = SceneManager->getVideoDriver(); // Get the video driver CalRenderer* renderer = calModel->getRenderer(); // Get the CalRenderer //----------------------------------------------------------// // All we're doing here is form a bridge between the CalRenderer and the IVideoDriver // The CalRenderer gives us data (doesn't draw anything) and IVideoDriver needs that data // Only problem is that we need to convert it to Irrlicht Compatible data // To explain what's going on, this simple diagram should help: // CalRenderer >--GET--> Data >--CONVERT--> Irrlicht Format >--SEND--> IVideoDriver >--DRAW--> .. //----------------------------------------------------------// calModel->getSkeleton()->calculateBoundingBoxes(); // Calculate the bounding box of the skeleton //----------------------------------------------------------// if ( renderer == 0 ) return; // Bail out if no renderer was received if ( !renderer->beginRendering() ) return; // Bail out if renderer encountered an error //----------------------------------------------------------// Move to our position (and rotate/scale) driver->setTransform( video::ETS_WORLD, AbsoluteTransformation ); //----------------------------------------------------------// s32 numMeshes = renderer->getMeshCount(); // Get the number of meshes we need to draw for ( s32 meshId = 0; meshId < numMeshes; meshId++ ) // Loop for every mesh { //--------------------------------------------------------// s32 numSubMeshes = renderer->getSubmeshCount(meshId); // Get the number of submeshes for ( s32 subId = 0; subId < numSubMeshes; subId++ ) // Loop for every submesh { if ( !renderer->selectMeshSubmesh(meshId, subId) ) // Select the current mesh and submesh { continue; // Skip this submesh if it failed } //------------------------------------------------------// if ( !OverrideMaterial ) // Should we use Cal3D's material? { u8 meshColor [4]; // Color stored in RGBA format // Irrlicht wants it in ARGB format renderer->getAmbientColor( meshColor ); // Get the ambient color Material.AmbientColor.setRed( meshColor[0] ); // Set the red component Material.AmbientColor.setGreen( meshColor[1] ); // Set the green component Material.AmbientColor.setBlue( meshColor[2] ); // Set the blue component Material.AmbientColor.setAlpha( meshColor[3] ); // Set the alpha component renderer->getDiffuseColor( meshColor ); // Get the diffuse color Material.DiffuseColor.setRed( meshColor[0] ); // Set the red component Material.DiffuseColor.setGreen( meshColor[1] ); // Set the green component Material.DiffuseColor.setBlue( meshColor[2] ); // Set the blue component Material.DiffuseColor.setAlpha( meshColor[3] ); // Set the alpha component renderer->getSpecularColor( meshColor ); // Get the specular color Material.SpecularColor.setRed( meshColor[0] ); // Set the red component Material.SpecularColor.setGreen( meshColor[1] ); // Set the green component Material.SpecularColor.setBlue( meshColor[2] ); // Set the blue component Material.SpecularColor.setAlpha( meshColor[3] ); // Set the alpha component Material.Shininess = renderer->getShininess(); // Set the shininess factor if ( renderer->getMapCount() >= 1 ) { // Get the irrlicht texture from user data Material.setTexture(0, (video::ITexture*)renderer->getMapUserData(0)); } } //------------------------------------------------------// s32 vertexCount = renderer->getVertexCount(); // Get the number of vertices if (vertexCount == 0) continue; // Skip if the mesh is empty static core::array<core::vector3df> vertexBuffer; // Use a core::array to support msvc vertexBuffer.set_used( vertexCount ); // Make room for the vertex coordinates renderer->getVertices( &vertexBuffer[0].X ); // Copy the vertices into the buffer //------------------------------------------------------// static core::array<core::vector3df> normalBuffer; normalBuffer.set_used( vertexCount ); // Buffer for the vertex normals renderer->getNormals( &normalBuffer[0].X ); // Copy the normals to the buffer //------------------------------------------------------// static core::array<core::vector2df> texCoordBuffer; texCoordBuffer.set_used( vertexCount ); // Buffer for the vertex texture coordinates renderer->getTextureCoordinates( 0, &texCoordBuffer[0].X );// Copy the texture coordinates to the buffer //------------------------------------------------------// s32 faceCount = renderer->getFaceCount(); // Get the number of faces static CalIndex cal_indices[30000000]; renderer->getFaces( cal_indices ); // Copy the face indices to the buffer static core::array<u16> faceBuffer; faceBuffer.set_used( faceCount * 3 ); // Buffer for the face v1,v2,v3 indices for(int i = 0; i < faceCount * 3; ++i) { faceBuffer[i] = cal_indices[i]; } //------------------------------------------------------// static core::array<video::S3DVertex> irrVertexBuffer; irrVertexBuffer.set_used( vertexCount ); // Buffer for the irrlicht vertices for (s32 vert=0; vert<vertexCount; vert++) // Convert all vertices to irrlicht format { // Irrlicht and Cal3D uses different coordinates. Irrlicht's Y points up, where Cal3D's Z points up irrVertexBuffer[vert].Pos.X = vertexBuffer[vert].X; // Set the X coordinate irrVertexBuffer[vert].Pos.Y = vertexBuffer[vert].Y; // Set the Y coordinate (Cal3D's Z coord) irrVertexBuffer[vert].Pos.Z = vertexBuffer[vert].Z; // Set the Z coordinate (Cal3D's Y coord) irrVertexBuffer[vert].Color.set(255,128,128,128); // Vertex colors aren't supported by Cal3D irrVertexBuffer[vert].Normal.X = normalBuffer[vert].X;// Set the X coordinate irrVertexBuffer[vert].Normal.Y = normalBuffer[vert].Y;// Set the Y coordinate (Cal3D's Z coord) irrVertexBuffer[vert].Normal.Z = normalBuffer[vert].Z;// Set the Z coordinate (Cal3D's Y coord) irrVertexBuffer[vert].TCoords.X = texCoordBuffer[vert].X;// Set the X texture coordinate (U) irrVertexBuffer[vert].TCoords.Y = texCoordBuffer[vert].Y;// Set the Y texture coordinate (V) } //------------------------------------------------------// Invert triangle direction for (s32 face=0; face<faceCount; face++) // Irrlicht wants indices in the opposite order { u16 faceA = faceBuffer[face*3]; // Swap first and last vertex index faceBuffer[face*3] = faceBuffer[face*3+2]; // Set the first to the last faceBuffer[face*3+2] = faceA; // And the last to the first } //------------------------------------------------------// Finally! Time to draw everthing Material.BackfaceCulling = false; float k; if(draw_mode != DM_DEFAULT) { video::SMaterial debug_material; debug_material.Wireframe = true; debug_material.BackfaceCulling = false; debug_material.Lighting = false; driver->setMaterial(debug_material); /* so that debug looks good for all sizes of models*/ k = EXTENT_K * BoundingBox.getExtent().getLength(); } else { driver->setMaterial( Material ); } if(draw_mode == DM_DEFAULT) { driver->drawIndexedTriangleList(irrVertexBuffer.const_pointer(), vertexCount, faceBuffer.const_pointer(), faceCount); } else if(draw_mode == DM_WIREFRAME || draw_mode == DM_WIREFRAME_AND_SKELETON) { /* draw faces */ for (s32 face=0; face<faceCount; ++face) { u16 i1, i2, i3; i1 = faceBuffer[face*3+0]; i2 = faceBuffer[face*3+1]; i3 = faceBuffer[face*3+2]; driver->draw3DLine(core::vector3df(vertexBuffer[i1].X, vertexBuffer[i1].Y, vertexBuffer[i1].Z), core::vector3df(vertexBuffer[i2].X, vertexBuffer[i2].Y, vertexBuffer[i2].Z), video::SColor(255,0,0,255)); driver->draw3DLine(core::vector3df(vertexBuffer[i2].X, vertexBuffer[i2].Y, vertexBuffer[i2].Z), core::vector3df(vertexBuffer[i3].X, vertexBuffer[i3].Y, vertexBuffer[i3].Z), video::SColor(255,0,0,255)); driver->draw3DLine(core::vector3df(vertexBuffer[i3].X, vertexBuffer[i3].Y, vertexBuffer[i3].Z), core::vector3df(vertexBuffer[i1].X, vertexBuffer[i1].Y, vertexBuffer[i1].Z), video::SColor(255,0,0,255)); } } if(draw_mode == DM_SKELETON || draw_mode == DM_WIREFRAME_AND_SKELETON) { float lines[1024][2][3]; int num_lines; num_lines = calModel->getSkeleton()->getBoneLines(&lines[0][0][0]); video::S3DVertex vertex; for(int line = 0; line < num_lines; ++line) { driver->draw3DLine(core::vector3df(lines[line][0][0], lines[line][0][1], lines[line][0][2]), core::vector3df(lines[line][1][0], lines[line][1][1], lines[line][1][2]), video::SColor(255,255,0,0)); core::aabbox3df box1(lines[line][0][0]-SKELETON_K*k, lines[line][0][1]-SKELETON_K*k, lines[line][0][2]-SKELETON_K*k, lines[line][0][0]+SKELETON_K*k, lines[line][0][1]+SKELETON_K*k, lines[line][0][2]+SKELETON_K*k); core::aabbox3df box2(lines[line][1][0]-SKELETON_K*k, lines[line][1][1]-SKELETON_K*k, lines[line][1][2]-SKELETON_K*k, lines[line][1][0]+SKELETON_K*k, lines[line][1][1]+SKELETON_K*k, lines[line][1][2]+SKELETON_K*k); driver->draw3DBox(box1, video::SColor(255,0,255,0)); driver->draw3DBox(box2, video::SColor(255,0,255,0)); } } if(draw_bbox) { video::SMaterial debug_material; debug_material.Wireframe = true; debug_material.BackfaceCulling = false; debug_material.Lighting = false; driver->setMaterial(debug_material); driver->draw3DBox(BoundingBox, video::SColor(255,255,0,255)); } if(draw_normals) { k = EXTENT_K * BoundingBox.getExtent().getLength(); video::SMaterial debug_material; debug_material.Wireframe = true; debug_material.BackfaceCulling = false; debug_material.Lighting = false; driver->setMaterial(debug_material); /* draw normals */ for (s32 vert=0; vert<vertexCount; ++vert) { driver->draw3DLine(core::vector3df(vertexBuffer[vert].X, vertexBuffer[vert].Y, vertexBuffer[vert].Z), core::vector3df(vertexBuffer[vert].X + NORMAL_K*k*normalBuffer[vert].X, vertexBuffer[vert].Y + NORMAL_K*k*normalBuffer[vert].Y, vertexBuffer[vert].Z + NORMAL_K*k*normalBuffer[vert].Z), video::SColor(255,0,255,0)); } } } // for subId } // for meshId //----------------------------------------------------------// renderer->endRendering(); // Tell the renderer we are finished now }
HeightMap(u16 _w, u16 _h) : Width(_w), Height(_h), s(0.f), data(0) { s = sqrtf((f32)(Width * Width + Height * Height)); data.set_used(Width * Height); }
core::vector3df collideWithWorld(s32 recursionDepth, SCollisionData &colData, core::vector3df pos, core::vector3df vel) { f32 veryCloseDistance = colData.slidingSpeed; if (recursionDepth > 5) return pos; colData.velocity = vel; colData.normalizedVelocity = vel; colData.normalizedVelocity.normalize(); colData.basePoint = pos; colData.foundCollision = false; colData.nearestDistance = FLT_MAX; double uhel_cos = 90 - acos(colData.normalizedVelocity.dotProduct(vector3df(0, -1, 0).normalize())) * 180.0 / PI; if (recursionDepth > 0 && vel.getLength() > 0 && vel.Y < 0) { if (abs(uhel_cos) < 50) return pos; } //------------------ collide with world // get all triangles with which we might collide core::aabbox3d<f32> box(colData.R3Position); box.addInternalPoint(colData.R3Position + colData.R3Velocity); box.MinEdge -= colData.eRadius; box.MaxEdge += colData.eRadius; s32 totalTriangleCnt = colData.selector->getTriangleCount(); Triangles.set_used(totalTriangleCnt); core::matrix4 scaleMatrix; scaleMatrix.setScale( core::vector3df(1.0f / colData.eRadius.X, 1.0f / colData.eRadius.Y, 1.0f / colData.eRadius.Z)); s32 triangleCnt = 0; colData.selector->getTriangles(Triangles.pointer(), totalTriangleCnt, triangleCnt, box, &scaleMatrix); for (s32 i=0; i<triangleCnt; ++i) if(testTriangleIntersection(&colData, Triangles[i])) colData.triangleIndex = i; //---------------- end collide with world if (!colData.foundCollision) return pos + vel; // original destination point const core::vector3df destinationPoint = pos + vel; core::vector3df newBasePoint = pos; if (colData.nearestDistance >= veryCloseDistance) { core::vector3df v = vel; v.setLength( colData.nearestDistance - veryCloseDistance ); newBasePoint = colData.basePoint + v; v.normalize(); colData.intersectionPoint -= (v * veryCloseDistance); } // calculate sliding plane const core::vector3df slidePlaneOrigin = colData.intersectionPoint; const core::vector3df slidePlaneNormal = (newBasePoint - colData.intersectionPoint).normalize(); core::plane3d<f32> slidingPlane(slidePlaneOrigin, slidePlaneNormal); core::vector3df newDestinationPoint = destinationPoint - (slidePlaneNormal * slidingPlane.getDistanceTo(destinationPoint)); // generate slide vector const core::vector3df newVelocityVector = newDestinationPoint - colData.intersectionPoint; if (newVelocityVector.getLength() < veryCloseDistance) return newBasePoint; //printf("Puvodni delka: %f | nova delka: %f\n", colData.velocity.getLength(), newVelocityVector.getLength()); return collideWithWorld(recursionDepth+1, colData, newBasePoint, newVelocityVector); }