void FixedRenderer::updateSkinning(Mesh * mesh, Armature * armature) { unsigned int s; unsigned int sSize = mesh->getSubMeshsNumber(); for(s=0; s<sSize; s++) { SubMesh * subMesh = &mesh->getSubMeshs()[s]; // data Vector3 * vertices = subMesh->getVertices(); if(! vertices) continue; SkinData * skinData = subMesh->getSkinData(); if(armature && skinData) { unsigned int verticesSize = subMesh->getVerticesSize(); Vector3 * skinVertices = getVertices(verticesSize); computeSkinning(armature, skinData, vertices, NULL, NULL, skinVertices, NULL, NULL); subMesh->getBoundingBox()->initFromPoints(skinVertices, verticesSize); } } mesh->updateBoundingBox(); }
static void createSubMesh(const aiScene * scene, const aiNode * nd, Mesh * mesh, SubMesh * subMeshs, unsigned int * count, const Matrix4x4 & parentMatrix) { aiMatrix4x4 nodeMat = nd->mTransformation; aiTransposeMatrix4(&nodeMat); Matrix4x4 matrix = parentMatrix * Matrix4x4((float*)&nodeMat); unsigned int m; for(m=0; m<nd->mNumMeshes; m++) { unsigned int i; const aiMesh * nodeMesh = scene->mMeshes[nd->mMeshes[m]]; if(nodeMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) continue; // current sub mesh SubMesh * subMesh = &(subMeshs[*count]); // vertices Vector3 * vertices = subMesh->allocVertices(nodeMesh->mNumVertices); for(i=0; i<nodeMesh->mNumVertices; i++) vertices[i] = matrix * Vector3(nodeMesh->mVertices[i].x, nodeMesh->mVertices[i].y, nodeMesh->mVertices[i].z); // normals if(nodeMesh->mNormals) { Vector3 * normals = subMesh->allocNormals(nodeMesh->mNumVertices); for(i=0; i<nodeMesh->mNumVertices; i++) normals[i] = matrix.getRotatedVector3(Vector3(nodeMesh->mNormals[i].x, nodeMesh->mNormals[i].y, nodeMesh->mNormals[i].z)).getNormalized(); } // tangents if(nodeMesh->mTangents) { Vector3 * tangents = subMesh->allocTangents(nodeMesh->mNumVertices); for(i=0; i<nodeMesh->mNumVertices; i++) tangents[i] = matrix.getRotatedVector3(Vector3(nodeMesh->mTangents[i].x, nodeMesh->mTangents[i].y, nodeMesh->mTangents[i].z)).getNormalized(); } // colors if(nodeMesh->mColors[0]) { Color * colors = subMesh->allocColors(nodeMesh->mNumVertices); for(i=0; i<nodeMesh->mNumVertices; i++) colors[i] = Color(nodeMesh->mColors[0][i].r, nodeMesh->mColors[0][i].g, nodeMesh->mColors[0][i].b, nodeMesh->mColors[0][i].a); } // uvcoords { unsigned int t, nb_texLayers = 0; for(t=0; t<AI_MAX_NUMBER_OF_TEXTURECOORDS; t++) { if(nodeMesh->mTextureCoords[t]) nb_texLayers++; } Vector2 * uvCoords = subMesh->allocTexCoords(nodeMesh->mNumVertices*nb_texLayers); nb_texLayers = 0; for(t=0; t<AI_MAX_NUMBER_OF_TEXTURECOORDS; t++) { if(nodeMesh->mTextureCoords[t]) { unsigned int offset = nodeMesh->mNumVertices*nb_texLayers; subMesh->setMapChannelOffset(t, offset); for(i=0; i<nodeMesh->mNumVertices; i++){ uvCoords[offset+i] = Vector2(nodeMesh->mTextureCoords[t][i].x, 1-nodeMesh->mTextureCoords[t][i].y); } nb_texLayers++; } } } // indices { unsigned int f; if(nodeMesh->mNumVertices < 65536) { unsigned short * indices = (unsigned short *)subMesh->allocIndices(nodeMesh->mNumFaces*3, VAR_USHORT); for(f=0; f<nodeMesh->mNumFaces; f++) { aiFace * face = &nodeMesh->mFaces[f]; for(i=0; i<3; i++){ indices[f*3+i] = face->mIndices[i]; } } } else { unsigned int * indices = (unsigned int *)subMesh->allocIndices(nodeMesh->mNumFaces*3, VAR_UINT); for(f=0; f<nodeMesh->mNumFaces; f++) { aiFace * face = &nodeMesh->mFaces[f]; for(i=0; i<3; i++){ indices[f*3+i] = face->mIndices[i]; } } } } // bones initBones(scene, nodeMesh, mesh, subMesh); // display subMesh->allocDisplays(1); MaterialDisplay * display = subMesh->addNewDisplay(PRIMITIVE_TRIANGLES, 0, subMesh->getIndicesSize()); display->setMaterial(mesh->getMaterial(nodeMesh->mMaterialIndex)); // cull mode int twosided = 0; aiMaterial * mtl = scene->mMaterials[nodeMesh->mMaterialIndex]; if(AI_SUCCESS == aiGetMaterialInteger(mtl, AI_MATKEY_TWOSIDED, &twosided)) { if(twosided != 0) display->setCullMode(CULL_NONE); } // bounding box subMesh->getBoundingBox()->initFromPoints(vertices, subMesh->getVerticesSize()); (*count)++; } for(unsigned int n=0; n<nd->mNumChildren; n++) createSubMesh(scene, nd->mChildren[n], mesh, subMeshs, count, matrix); }
void FixedRenderer::drawScene(Scene * scene, OCamera * camera) { struct MEntityLight { Box3d lightBox; OLight * light; }; struct MSubMeshPass { unsigned int subMeshId; unsigned int lightsNumber; Object3d * object; OLight * lights[4]; }; // sub objects #define MAX_TRANSP_SUBOBJ 4096 static int transpList[MAX_TRANSP_SUBOBJ]; static float transpZList[MAX_TRANSP_SUBOBJ]; static MSubMeshPass transpSubObjs[MAX_TRANSP_SUBOBJ]; // lights list #define MAX_ENTITY_LIGHTS 256 static int entityLightsList[MAX_ENTITY_LIGHTS]; static float entityLightsZList[MAX_ENTITY_LIGHTS]; static MEntityLight entityLights[MAX_ENTITY_LIGHTS]; // get render RenderingContext * render = NeoEngine::getInstance()->getRenderingContext(); render->enableLighting(); render->enableBlending(); // make frustum Frustum * frustum = camera->getFrustum(); frustum->makeVolume(camera); // update visibility updateVisibility(scene, camera); // fog enableFog(camera); // camera Vector3 cameraPos = camera->getTransformedPosition(); // transp sub obj number unsigned int transpSubObsNumber = 0; // lights unsigned int l; unsigned int lSize = scene->getLightsNumber(); // entities unsigned int i; unsigned int eSize = scene->getEntitiesNumber(); for(i=0; i<eSize; i++) { // get entity OEntity * entity = scene->getEntityByIndex(i); Mesh * mesh = entity->getMesh(); if(! entity->isActive()) continue; if(! entity->isVisible()) { if(mesh) { Armature * armature = mesh->getArmature(); ArmatureAnim * armatureAnim = mesh->getArmatureAnim(); if(armature) { // animate armature if(mesh->getArmature()) { Armature * armature = mesh->getArmature(); if(mesh->getArmatureAnim()) { animateArmature( mesh->getArmature(), mesh->getArmatureAnim(), entity->getCurrentFrame() ); } else { armature->processBonesLinking(); armature->updateBonesSkinMatrix(); } } // TODO : optimize and add a tag to desactivate it updateSkinning(mesh, armature); (*entity->getBoundingBox()) = (*mesh->getBoundingBox()); } } continue; } // draw mesh if(mesh) { Vector3 scale = entity->getTransformedScale(); Box3d * entityBox = entity->getBoundingBox(); float minScale = scale.x; minScale = MIN(minScale, scale.y); minScale = MIN(minScale, scale.z); minScale = 1.0f / minScale; unsigned int entityLightsNumber = 0; for(l=0; l<lSize; l++) { // get entity OLight * light = scene->getLightByIndex(l); if(! light->isActive()) continue; if(! light->isVisible()) continue; // light box Vector3 lightPos = light->getTransformedPosition(); Vector3 localPos = entity->getInversePosition(lightPos); float localRadius = light->getRadius() * minScale; Box3d lightBox( Vector3(localPos - localRadius), Vector3(localPos + localRadius) ); if(! entityBox->isInCollisionWith(lightBox)) continue; MEntityLight * entityLight = &entityLights[entityLightsNumber]; entityLight->lightBox = lightBox; entityLight->light = light; entityLightsNumber++; if(entityLightsNumber == MAX_ENTITY_LIGHTS) break; } // animate armature if(mesh->getArmature()) { Armature * armature = mesh->getArmature(); if(mesh->getArmatureAnim()) { animateArmature( mesh->getArmature(), mesh->getArmatureAnim(), entity->getCurrentFrame() ); } else { armature->processBonesLinking(); armature->updateBonesSkinMatrix(); } } // animate textures if(mesh->getTexturesAnim()) animateTextures(mesh, mesh->getTexturesAnim(), entity->getCurrentFrame()); // animate materials if(mesh->getMaterialsAnim()) animateMaterials(mesh, mesh->getMaterialsAnim(), entity->getCurrentFrame()); unsigned int s; unsigned int sSize = mesh->getSubMeshsNumber(); for(s=0; s<sSize; s++) { SubMesh * subMesh = &mesh->getSubMeshs()[s]; Box3d * box = subMesh->getBoundingBox(); // check if submesh visible if(sSize > 1) { Vector3 * min = &box->min; Vector3 * max = &box->max; Vector3 points[8] = { entity->getTransformedVector(Vector3(min->x, min->y, min->z)), entity->getTransformedVector(Vector3(min->x, max->y, min->z)), entity->getTransformedVector(Vector3(max->x, max->y, min->z)), entity->getTransformedVector(Vector3(max->x, min->y, min->z)), entity->getTransformedVector(Vector3(min->x, min->y, max->z)), entity->getTransformedVector(Vector3(min->x, max->y, max->z)), entity->getTransformedVector(Vector3(max->x, max->y, max->z)), entity->getTransformedVector(Vector3(max->x, min->y, max->z)) }; if(! frustum->isVolumePointsVisible(points, 8)) continue; } // subMesh center Vector3 center = box->min + (box->max - box->min)*0.5f; center = entity->getTransformedVector(center); // sort entity lights unsigned int lightsNumber = 0; for(l=0; l<entityLightsNumber; l++) { MEntityLight * entityLight = &entityLights[l]; if(! box->isInCollisionWith(entityLight->lightBox)) continue; OLight * light = entityLight->light; float z = (center - light->getTransformedPosition()).getLength(); entityLightsList[lightsNumber] = l; entityLightsZList[l] = (1.0f/z)*light->getRadius(); lightsNumber++; } if(lightsNumber > 1) sortFloatList(entityLightsList, entityLightsZList, 0, (int)lightsNumber-1); // local lights if(lightsNumber > 4) lightsNumber = 4; for(l=0; l<lightsNumber; l++) { MEntityLight * entityLight = &entityLights[entityLightsList[l]]; OLight * light = entityLight->light; // attenuation float quadraticAttenuation = (8.0f / light->getRadius()); quadraticAttenuation = (quadraticAttenuation*quadraticAttenuation)*light->getIntensity(); // color Vector3 color = light->getFinalColor(); // set light render->enableLight(l); render->setLightPosition(l, light->getTransformedPosition()); render->setLightDiffuse(l, Vector4(color)); render->setLightSpecular(l, Vector4(color)); render->setLightAmbient(l, Vector3(0, 0, 0)); render->setLightAttenuation(l, 1, 0, quadraticAttenuation); // spot render->setLightSpotAngle(l, light->getSpotAngle()); if(light->getSpotAngle() < 90){ render->setLightSpotDirection(l, light->getRotatedVector(Vector3(0, 0, -1)).getNormalized()); render->setLightSpotExponent(l, light->getSpotExponent()); } else { render->setLightSpotExponent(l, 0.0f); } } for(l=lightsNumber; l<4; l++){ render->disableLight(l); } render->pushMatrix(); render->multMatrix(entity->getMatrix()); // draw opaques drawOpaques(subMesh, mesh->getArmature()); if(subMesh->hasTransparency()) { if(transpSubObsNumber < MAX_TRANSP_SUBOBJ) { // transparent subMesh pass MSubMeshPass * subMeshPass = &transpSubObjs[transpSubObsNumber]; // lights subMeshPass->lightsNumber = lightsNumber; for(l=0; l<lightsNumber; l++) subMeshPass->lights[l] = entityLights[entityLightsList[l]].light; // z distance to camera float z = getDistanceToCam(camera, center); // set values transpList[transpSubObsNumber] = transpSubObsNumber; transpZList[transpSubObsNumber] = z; subMeshPass->subMeshId = s; subMeshPass->object = entity; transpSubObsNumber++; } } render->popMatrix(); } mesh->updateBoundingBox(); (*entity->getBoundingBox()) = (*mesh->getBoundingBox()); } } // texts unsigned int tSize = scene->getTextsNumber(); for(i=0; i<tSize; i++) { OText * text = scene->getTextByIndex(i); if(text->isActive() && text->isVisible()) { // transparent pass MSubMeshPass * subMeshPass = &transpSubObjs[transpSubObsNumber]; // center Box3d * box = text->getBoundingBox(); Vector3 center = box->min + (box->max - box->min)*0.5f; center = text->getTransformedVector(center); // z distance to camera float z = getDistanceToCam(camera, center); // set values transpList[transpSubObsNumber] = transpSubObsNumber; transpZList[transpSubObsNumber] = z; subMeshPass->object = text; transpSubObsNumber++; } } // sort transparent list if(transpSubObsNumber > 1) sortFloatList(transpList, transpZList, 0, (int)transpSubObsNumber-1); // draw transparents render->setDepthMask(0); for(i=0; i<transpSubObsNumber; i++) { MSubMeshPass * subMeshPass = &transpSubObjs[transpList[i]]; Object3d * object = subMeshPass->object; // objects switch(object->getType()) { case M_OBJECT3D_ENTITY: { OEntity * entity = (OEntity *)object; unsigned int subMeshId = subMeshPass->subMeshId; Mesh * mesh = entity->getMesh(); SubMesh * subMesh = &mesh->getSubMeshs()[subMeshId]; // animate armature if(mesh->getArmature()) { Armature * armature = mesh->getArmature(); if(mesh->getArmatureAnim()) { animateArmature( mesh->getArmature(), mesh->getArmatureAnim(), entity->getCurrentFrame() ); } else { armature->processBonesLinking(); armature->updateBonesSkinMatrix(); } } // animate textures if(mesh->getTexturesAnim()) animateTextures(mesh, mesh->getTexturesAnim(), entity->getCurrentFrame()); // animate materials if(mesh->getMaterialsAnim()) animateMaterials(mesh, mesh->getMaterialsAnim(), entity->getCurrentFrame()); // lights for(l=0; l<subMeshPass->lightsNumber; l++) { OLight * light = subMeshPass->lights[l]; // attenuation float quadraticAttenuation = (8.0f / light->getRadius()); quadraticAttenuation = (quadraticAttenuation*quadraticAttenuation)*light->getIntensity(); // color Vector3 color = light->getFinalColor(); // set light render->enableLight(l); render->setLightPosition(l, light->getTransformedPosition()); render->setLightDiffuse(l, Vector4(color)); render->setLightSpecular(l, Vector4(color)); render->setLightAmbient(l, Vector3(0, 0, 0)); render->setLightAttenuation(l, 1, 0, quadraticAttenuation); // spot render->setLightSpotAngle(l, light->getSpotAngle()); if(light->getSpotAngle() < 90){ render->setLightSpotDirection(l, light->getRotatedVector(Vector3(0, 0, -1)).getNormalized()); render->setLightSpotExponent(l, light->getSpotExponent()); } else { render->setLightSpotExponent(l, 0.0f); } } for(l=subMeshPass->lightsNumber; l<4; l++){ render->disableLight(l); } render->pushMatrix(); render->multMatrix(entity->getMatrix()); drawTransparents(subMesh, mesh->getArmature()); render->popMatrix(); mesh->updateBoundingBox(); (*entity->getBoundingBox()) = (*mesh->getBoundingBox()); } break; case M_OBJECT3D_TEXT: { OText * text = (OText *)object; render->pushMatrix(); render->multMatrix(text->getMatrix()); drawText(text); render->popMatrix(); } break; } } render->setDepthMask(1); render->disableLighting(); render->disableFog(); }