// Merges data into a single vertex and index buffer referenced by primitive groups (submeshes). // ERet CompileMesh( const TcMeshData& src, const VertexDescription& vertex, RawMeshData &dst ) { UINT totalVertexCount = 0; UINT totalIndexCount = 0; CalculateTotalVertexIndexCount( src, totalVertexCount, totalIndexCount ); const bool use32indices = (totalVertexCount >= MAX_UINT16); const UINT indexStride = use32indices ? 4 : 2; VertexStream streamStorage[8]; TArray< VertexStream > streams; streams.SetExternalStorage( streamStorage, mxCOUNT_OF(streamStorage) ); GatherStreams(vertex, streams); const UINT numStreams = streams.Num(); // reserve space in vertex data RawVertexData& dstVD = dst.vertexData; dstVD.streams.SetNum(numStreams); dstVD.count = totalVertexCount; dstVD.type = VertexType::Generic; for( UINT streamIndex = 0; streamIndex < numStreams; streamIndex++ ) { const UINT32 stride = vertex.streamStrides[ streamIndex ]; // stride of the vertex buffer RawVertexStream &dstVB = dstVD.streams[ streamIndex ]; dstVB.data.SetNum( stride * totalVertexCount ); } // reserve space in index data RawIndexData& dstID = dst.indexData; dstID.data.SetNum(indexStride * totalIndexCount); dstID.stride = indexStride; dst.topology = Topology::TriangleList; dst.bounds = src.bounds; // iterate over all submeshes (primitive groups) and merge vertex/index data const UINT numMeshes = src.sets.Num(); dst.parts.SetNum(numMeshes); UINT32 currentVertexIndex = 0; UINT32 currentIndexNumber = 0; for( UINT meshIndex = 0; meshIndex < numMeshes; meshIndex++ ) { const TcTriMesh& submesh = src.sets[ meshIndex ]; const UINT32 numVertices = submesh.NumVertices(); // number of vertices in this submesh const UINT32 numIndices = submesh.NumIndices(); // number of indices in this submesh RawMeshPart &meshPart = dst.parts[ meshIndex ]; meshPart.baseVertex = currentVertexIndex; meshPart.startIndex = currentIndexNumber; meshPart.indexCount = numIndices; meshPart.vertexCount = numVertices; const int maxBoneInfluences = numVertices * MAX_INFLUENCES; ScopedStackAlloc stackAlloc(gCore.frameAlloc); int * boneIndices = stackAlloc.AllocMany< int >( maxBoneInfluences ); float * boneWeights = stackAlloc.AllocMany< float >( maxBoneInfluences ); memset(boneIndices, 0, maxBoneInfluences * sizeof(boneIndices[0])); memset(boneWeights, 0, maxBoneInfluences * sizeof(boneWeights[0])); if( submesh.weights.NonEmpty() ) { mxASSERT(submesh.weights.Num() == numVertices); for( UINT32 vertexIndex = 0; vertexIndex < numVertices; vertexIndex++ ) { const TcWeights& weights = submesh.weights[ vertexIndex ]; const int numWeights = smallest(weights.Num(), MAX_INFLUENCES); for( int weightIndex = 0; weightIndex < numWeights; weightIndex++ ) { const int offset = vertexIndex * MAX_INFLUENCES + weightIndex; boneIndices[ offset ] = weights[ weightIndex ].boneIndex; boneWeights[ offset ] = weights[ weightIndex ].boneWeight; } }//for each vertex } // process each vertex stream for( UINT streamIndex = 0; streamIndex < numStreams; streamIndex++ ) { const UINT32 streamStride = vertex.streamStrides[ streamIndex ]; // stride of the vertex buffer const VertexStream& stream = streams[ streamIndex ]; RawVertexStream &dstVB = dstVD.streams[ streamIndex ]; dstVB.data.SetNum( streamStride * totalVertexCount ); const UINT32 currentVertexDataOffset = currentVertexIndex * streamStride; // first fill the vertex data with zeros void* dstStreamData = mxAddByteOffset( dstVB.data.ToPtr(), currentVertexDataOffset ); memset(dstStreamData, 0, streamStride * numVertices); // process each vertex stream component for( UINT elementIndex = 0; elementIndex < stream.components.Num(); elementIndex++ ) { const UINT32 attribIndex = stream.components[ elementIndex ]; const VertexElement& attrib = vertex.attribsArray[ attribIndex ]; const UINT32 attribOffset = vertex.attribOffsets[ attribIndex ]; // offset within stream const AttributeType::Enum attribType = (AttributeType::Enum) attrib.type; const VertexAttribute::Enum semantic = (VertexAttribute::Enum) attrib.semantic; const UINT attribDimension = attrib.dimension + 1; // process each vertex const void* srcPtr = NULL; UINT srcDimension = 0; // vector dimension: [1,2,3,4] bool srcDataIsFloat = true; bool srcIsPositive = false; bool normalize = attrib.normalized; int srcStride = 4; // sizeof(float) == sizeof(int) switch( semantic ) { case VertexAttribute::Position : srcPtr = (float*) submesh.positions.SafeGetFirstItemPtr(); srcDimension = 3; break; case VertexAttribute::Color0 : srcPtr = (float*) submesh.colors.SafeGetFirstItemPtr(); srcDimension = 4; srcIsPositive = true; // RGBA colors are in range [0..1] break; case VertexAttribute::Color1 : ptERROR("Vertex colors > 1 are not supported!\n"); break; case VertexAttribute::Normal : srcPtr = (float*) submesh.normals.SafeGetFirstItemPtr(); srcDimension = 3; normalize = true; // we pack normals and tangents into Ubyte4 break; case VertexAttribute::Tangent : srcPtr = (float*) submesh.tangents.SafeGetFirstItemPtr(); srcDimension = 3; normalize = true; // we pack normals and tangents into Ubyte4 break; case VertexAttribute::TexCoord0 : srcPtr = (float*) submesh.texCoords.SafeGetFirstItemPtr(); srcDimension = 2; break; case VertexAttribute::TexCoord1 : case VertexAttribute::TexCoord2 : case VertexAttribute::TexCoord3 : case VertexAttribute::TexCoord4 : case VertexAttribute::TexCoord5 : case VertexAttribute::TexCoord6 : case VertexAttribute::TexCoord7 : ptWARN("TexCoord > 1 are not supported!\n"); break; case VertexAttribute::BoneIndices : srcPtr = boneIndices; srcDimension = 4; srcDataIsFloat = false; srcIsPositive = true; break; case VertexAttribute::BoneWeights : srcPtr = boneWeights; srcDimension = 4; srcIsPositive = true; // bone weights are always in range [0..1] break; default: ptERROR("Unknown vertex attrib semantic: %d\n", semantic); } if( srcPtr && srcDimension > 0 ) { for( UINT32 vertexIndex = 0; vertexIndex < numVertices; vertexIndex++ ) { UINT vertexOffset = currentVertexDataOffset + vertexIndex*streamStride + attribOffset; void* dstPtr = mxAddByteOffset( dstVB.data.ToPtr(), vertexOffset ); if( srcDataIsFloat ) { PackVertexAttribF( (float*)srcPtr, srcDimension, dstPtr, attribType, attribDimension, normalize, srcIsPositive ); } else { mxASSERT2( !attrib.normalized, "Integer data cannot be normalized!" ); PackVertexAttribI( (int*)srcPtr, srcDimension, dstPtr, attribType, attribDimension ); } srcPtr = mxAddByteOffset( srcPtr, srcDimension * srcStride ); }//for each vertex } }//for each component }//for each stream void* indices = mxAddByteOffset(dstID.data.ToPtr(), currentIndexNumber * indexStride); for( UINT32 i = 0; i < numIndices; i++ ) { const UINT32 index = submesh.indices[i]; if( use32indices ) { UINT32* indices32 = (UINT32*) indices; indices32[i] = currentVertexIndex + index; } else { UINT16* indices16 = (UINT16*) indices; indices16[i] = currentVertexIndex + index; } } currentVertexIndex += submesh.NumVertices(); currentIndexNumber += submesh.NumIndices(); } const UINT numBones = src.skeleton.bones.Num(); Skeleton& skeleton = dst.skeleton; skeleton.bones.SetNum(numBones); skeleton.boneNames.SetNum(numBones); skeleton.invBindPoses.SetNum(numBones); for( UINT boneIndex = 0; boneIndex < numBones; boneIndex++ ) { const TcBone& bone = src.skeleton.bones[boneIndex]; Bone& joint = skeleton.bones[boneIndex]; joint.orientation = bone.rotation; joint.position = bone.translation; joint.parent = bone.parent; #if 0 if( bone.parent >= 0 ) { const Joint& parent = skeleton.joints[bone.parent]; UNDONE; //ConcatenateJointTransforms(parent.position, parent.orientation, joint.position, joint.orientation); //Float4x4 parentMatrix = CalculateJointMatrix( parent.position, parent.orientation ); //Float4x4 boneMatrix = CalculateJointMatrix( bone.translation, bone.rotation ); //Float4x4 localMatrix = boneMatrix * glm::inverse(parentMatrix); //glm::vec3 localT(localMatrix[3]); //glm::quat localQ(localMatrix); //joint.orientation = localQ; //joint.position = localT; //Float4x4 parentMatrix = CalculateJointMatrix( parent.position, parent.orientation ); //Float4x4 boneTransform = CalculateJointMatrix( bone.translation, bone.rotation ); //Float4x4 globalMatrix = parentMatrix * boneTransform; //joint.orientation = glm::quat(globalMatrix); //joint.position = glm::vec3(globalMatrix[3]); } //joint.orientation = glm::quat(bone.absolute); //joint.position = glm::vec3(bone.absolute[3]); joint.orientation = glm::normalize(joint.orientation); //ptPRINT("Joint[%u]: '%s', parent = %d (P = %.3f, %.3f, %.3f, Q = %.3f, %.3f, %.3f, %.3f)\n", // boneIndex, bone.name.ToPtr(), bone.parent, // joint.position.iX, joint.position.iY, joint.position.iZ, // joint.orientation.iX, joint.orientation.iY, joint.orientation.iZ, joint.orientation.w); skeleton.jointNames[boneIndex] = bone.name; Float4x4 jointMatrix = CalculateJointMatrix( joint.position, joint.orientation ); skeleton.invBindPoses[boneIndex] = glm::inverse(jointMatrix); //ptPRINT("Bone[%u]: '%s', absolute = %s,\ncomputed = %s\n", // boneIndex, bone.name.ToPtr(), // MatrixToString(bone.absolute).ToPtr(), // MatrixToString(jointMatrix).ToPtr()); //ptPRINT("Bone[%u]: '%s', parent = %d (P = %.3f, %.3f, %.3f, Q = %.3f, %.3f, %.3f, %.3f)\n", // boneIndex, bone.name.ToPtr(), // bone.parent, bone.translation.iX, bone.translation.iY, bone.translation.iZ, // bone.rotation.iX, bone.rotation.iY, bone.rotation.iZ, bone.rotation.w); #endif } return ALL_OK; }
int main() { Object* objects[liveObjects]; time_t start; memset(objects, 0, sizeof(objects)); start = time(NULL); for (size_t i = 0; i < totalObjects; i++) { delete objects[i % liveObjects]; objects[i % liveObjects] = new Object(); } for (size_t i = 0; i < liveObjects; i++) { delete objects[i]; } printf("Elapsed time for standard new/delete: %ld\n", time(NULL) - start); { FixedAllocator<Object> fixedAlloc; memset(objects, 0, sizeof(objects)); start = time(NULL); for (size_t i = 0; i < totalObjects; i++) { fixedAlloc.free(objects[i % liveObjects]); objects[i % liveObjects] = fixedAlloc.allocate(); } } printf("Elapsed time for fixed size allocator: %ld\n", time(NULL) - start); { StackAllocator stackAlloc(64*1024); GC::ThreadContext<StackAllocator> ctx; ctx.set(&stackAlloc); memset(objects, 0, sizeof(objects)); start = time(NULL); for (size_t i = 0; i < totalObjects; i++) { if (i % liveObjects == 0) { ctx.get()->reset(); } objects[i % liveObjects] = ctx.get()->allocate<Object>(); } } printf("Elapsed time for stack allocator: %ld\n", time(NULL) - start); { boost::shared_ptr<Object> objectRefs[liveObjects]; start = time(NULL); for (size_t i = 0; i < totalObjects; i++) { objectRefs[i % liveObjects] = boost::shared_ptr<Object>(new Object()); } } printf("Elapsed time boost::shared_ptr: %ld\n", time(NULL) - start); { std::shared_ptr<Object> objectRefs[liveObjects]; start = time(NULL); for (size_t i = 0; i < totalObjects; i++) { objectRefs[i % liveObjects] = std::shared_ptr<Object>(new Object()); } } printf("Elapsed time std::shared_ptr: %ld\n", time(NULL) - start); { GC::MemoryAllocator mem(1*Mb, 1*Mb); GC::ArrayVar<GCObject,liveObjects> objectRefs; start = time(NULL); for (size_t i = 0; i < totalObjects; i++) { objectRefs[i % liveObjects] = new GCObject(); } } printf("Elapsed time for mark&sweep: %ld\n", time(NULL) - start); return 0; }