/* ================= R_LoadPSK ================= */ qboolean R_LoadPSK(model_t * mod, byte *buffer, int bufferSize, const char *modName) { int i, j, k; memStream_t *stream; axChunkHeader_t chunkHeader; int numPoints; axPoint_t *point; axPoint_t *points; int numVertexes; axVertex_t *vertex; axVertex_t *vertexes; //int numSmoothGroups; int numTriangles; axTriangle_t *triangle; axTriangle_t *triangles; int numMaterials; axMaterial_t *material; axMaterial_t *materials; int numReferenceBones; axReferenceBone_t *refBone; axReferenceBone_t *refBones; int numWeights; axBoneWeight_t *axWeight; axBoneWeight_t *axWeights; md5Model_t *md5; md5Bone_t *md5Bone; md5Weight_t *weight; vec3_t boneOrigin; quat_t boneQuat; //matrix_t boneMat; int materialIndex, oldMaterialIndex; int numRemaining; growList_t sortedTriangles; growList_t vboVertexes; growList_t vboTriangles; growList_t vboSurfaces; int numBoneReferences; int boneReferences[MAX_BONES]; matrix_t unrealToQuake; //MatrixSetupScale(unrealToQuake, 1, -1, 1); MatrixFromAngles(unrealToQuake, 0, 90, 0); stream = AllocMemStream(buffer, bufferSize); GetChunkHeader(stream, &chunkHeader); // check indent again if(Q_stricmpn(chunkHeader.ident, "ACTRHEAD", 8)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk indent ('%s' should be '%s')\n", modName, chunkHeader.ident, "ACTRHEAD"); FreeMemStream(stream); return qfalse; } PrintChunkHeader(&chunkHeader); mod->type = MOD_MD5; mod->dataSize += sizeof(md5Model_t); md5 = mod->md5 = (md5Model_t*)ri.Hunk_Alloc(sizeof(md5Model_t), h_low); // read points GetChunkHeader(stream, &chunkHeader); if(Q_stricmpn(chunkHeader.ident, "PNTS0000", 8)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk indent ('%s' should be '%s')\n", modName, chunkHeader.ident, "PNTS0000"); FreeMemStream(stream); return qfalse; } if(chunkHeader.dataSize != sizeof(axPoint_t)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", modName, chunkHeader.dataSize, sizeof(axPoint_t)); FreeMemStream(stream); return qfalse; } PrintChunkHeader(&chunkHeader); numPoints = chunkHeader.numData; points = (axPoint_t*)Com_Allocate(numPoints * sizeof(axPoint_t)); for(i = 0, point = points; i < numPoints; i++, point++) { point->point[0] = MemStreamGetFloat(stream); point->point[1] = MemStreamGetFloat(stream); point->point[2] = MemStreamGetFloat(stream); #if 0 // Tr3B: HACK convert from Unreal coordinate system to the Quake one MatrixTransformPoint2(unrealToQuake, point->point); #endif } // read vertices GetChunkHeader(stream, &chunkHeader); if(Q_stricmpn(chunkHeader.ident, "VTXW0000", 8)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk indent ('%s' should be '%s')\n", modName, chunkHeader.ident, "VTXW0000"); FreeMemStream(stream); Com_Dealloc(points); return qfalse; } if(chunkHeader.dataSize != sizeof(axVertex_t)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", modName, chunkHeader.dataSize, sizeof(axVertex_t)); FreeMemStream(stream); Com_Dealloc(points); return qfalse; } PrintChunkHeader(&chunkHeader); numVertexes = chunkHeader.numData; vertexes = (axVertex_t*)Com_Allocate(numVertexes * sizeof(axVertex_t)); for(i = 0, vertex = vertexes; i < numVertexes; i++, vertex++) { vertex->pointIndex = MemStreamGetShort(stream); if(vertex->pointIndex < 0 || vertex->pointIndex >= numPoints) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has vertex with point index out of range (%i while max %i)\n", modName, vertex->pointIndex, numPoints); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); return qfalse; } vertex->unknownA = MemStreamGetShort(stream); vertex->st[0] = MemStreamGetFloat(stream); vertex->st[1] = MemStreamGetFloat(stream); vertex->materialIndex = MemStreamGetC(stream); vertex->reserved = MemStreamGetC(stream); vertex->unknownB = MemStreamGetShort(stream); #if 0 ri.Printf(PRINT_ALL, "R_LoadPSK: axVertex_t(%i):\n" "axVertex:pointIndex: %i\n" "axVertex:unknownA: %i\n" "axVertex::st: %f %f\n" "axVertex:materialIndex: %i\n" "axVertex:reserved: %d\n" "axVertex:unknownB: %d\n", i, vertex->pointIndex, vertex->unknownA, vertex->st[0], vertex->st[1], vertex->materialIndex, vertex->reserved, vertex->unknownB); #endif } // read triangles GetChunkHeader(stream, &chunkHeader); if(Q_stricmpn(chunkHeader.ident, "FACE0000", 8)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk indent ('%s' should be '%s')\n", modName, chunkHeader.ident, "FACE0000"); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); return qfalse; } if(chunkHeader.dataSize != sizeof(axTriangle_t)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", modName, chunkHeader.dataSize, sizeof(axTriangle_t)); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); return qfalse; } PrintChunkHeader(&chunkHeader); numTriangles = chunkHeader.numData; triangles = (axTriangle_t*)Com_Allocate(numTriangles * sizeof(axTriangle_t)); for(i = 0, triangle = triangles; i < numTriangles; i++, triangle++) { for(j = 0; j < 3; j++) //for(j = 2; j >= 0; j--) { triangle->indexes[j] = MemStreamGetShort(stream); if(triangle->indexes[j] < 0 || triangle->indexes[j] >= numVertexes) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has triangle with vertex index out of range (%i while max %i)\n", modName, triangle->indexes[j], numVertexes); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); return qfalse; } } triangle->materialIndex = MemStreamGetC(stream); triangle->materialIndex2 = MemStreamGetC(stream); triangle->smoothingGroups = MemStreamGetLong(stream); } // read materials GetChunkHeader(stream, &chunkHeader); if(Q_stricmpn(chunkHeader.ident, "MATT0000", 8)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk indent ('%s' should be '%s')\n", modName, chunkHeader.ident, "MATT0000"); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); return qfalse; } if(chunkHeader.dataSize != sizeof(axMaterial_t)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", modName, chunkHeader.dataSize, sizeof(axMaterial_t)); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); return qfalse; } PrintChunkHeader(&chunkHeader); numMaterials = chunkHeader.numData; materials = (axMaterial_t*)Com_Allocate(numMaterials * sizeof(axMaterial_t)); for(i = 0, material = materials; i < numMaterials; i++, material++) { MemStreamRead(stream, material->name, sizeof(material->name)); ri.Printf(PRINT_ALL, "R_LoadPSK: material name: '%s'\n", material->name); material->shaderIndex = MemStreamGetLong(stream); material->polyFlags = MemStreamGetLong(stream); material->auxMaterial = MemStreamGetLong(stream); material->auxFlags = MemStreamGetLong(stream); material->lodBias = MemStreamGetLong(stream); material->lodStyle = MemStreamGetLong(stream); } for(i = 0, vertex = vertexes; i < numVertexes; i++, vertex++) { if(vertex->materialIndex < 0 || vertex->materialIndex >= numMaterials) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has vertex with material index out of range (%i while max %i)\n", modName, vertex->materialIndex, numMaterials); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); return qfalse; } } for(i = 0, triangle = triangles; i < numTriangles; i++, triangle++) { if(triangle->materialIndex < 0 || triangle->materialIndex >= numMaterials) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has triangle with material index out of range (%i while max %i)\n", modName, triangle->materialIndex, numMaterials); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); return qfalse; } } // read reference bones GetChunkHeader(stream, &chunkHeader); if(Q_stricmpn(chunkHeader.ident, "REFSKELT", 8)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk indent ('%s' should be '%s')\n", modName, chunkHeader.ident, "REFSKELT"); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); return qfalse; } if(chunkHeader.dataSize != sizeof(axReferenceBone_t)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", modName, chunkHeader.dataSize, sizeof(axReferenceBone_t)); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); return qfalse; } PrintChunkHeader(&chunkHeader); numReferenceBones = chunkHeader.numData; refBones = (axReferenceBone_t*)Com_Allocate(numReferenceBones * sizeof(axReferenceBone_t)); for(i = 0, refBone = refBones; i < numReferenceBones; i++, refBone++) { MemStreamRead(stream, refBone->name, sizeof(refBone->name)); //ri.Printf(PRINT_ALL, "R_LoadPSK: reference bone name: '%s'\n", refBone->name); refBone->flags = MemStreamGetLong(stream); refBone->numChildren = MemStreamGetLong(stream); refBone->parentIndex = MemStreamGetLong(stream); GetBone(stream, &refBone->bone); #if 0 ri.Printf(PRINT_ALL, "R_LoadPSK: axReferenceBone_t(%i):\n" "axReferenceBone_t::name: '%s'\n" "axReferenceBone_t::flags: %i\n" "axReferenceBone_t::numChildren %i\n" "axReferenceBone_t::parentIndex: %i\n" "axReferenceBone_t::quat: %f %f %f %f\n" "axReferenceBone_t::position: %f %f %f\n" "axReferenceBone_t::length: %f\n" "axReferenceBone_t::xSize: %f\n" "axReferenceBone_t::ySize: %f\n" "axReferenceBone_t::zSize: %f\n", i, refBone->name, refBone->flags, refBone->numChildren, refBone->parentIndex, refBone->bone.quat[0], refBone->bone.quat[1], refBone->bone.quat[2], refBone->bone.quat[3], refBone->bone.position[0], refBone->bone.position[1], refBone->bone.position[2], refBone->bone.length, refBone->bone.xSize, refBone->bone.ySize, refBone->bone.zSize); #endif } // read bone weights GetChunkHeader(stream, &chunkHeader); if(Q_stricmpn(chunkHeader.ident, "RAWWEIGHTS", 10)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk indent ('%s' should be '%s')\n", modName, chunkHeader.ident, "RAWWEIGHTS"); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); Com_Dealloc(refBones); return qfalse; } if(chunkHeader.dataSize != sizeof(axBoneWeight_t)) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", modName, chunkHeader.dataSize, sizeof(axBoneWeight_t)); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); Com_Dealloc(refBones); return qfalse; } PrintChunkHeader(&chunkHeader); numWeights = chunkHeader.numData; axWeights = (axBoneWeight_t*)Com_Allocate(numWeights * sizeof(axBoneWeight_t)); for(i = 0, axWeight = axWeights; i < numWeights; i++, axWeight++) { axWeight->weight = MemStreamGetFloat(stream); axWeight->pointIndex = MemStreamGetLong(stream); axWeight->boneIndex = MemStreamGetLong(stream); #if 0 ri.Printf(PRINT_ALL, "R_LoadPSK: axBoneWeight_t(%i):\n" "axBoneWeight_t::weight: %f\n" "axBoneWeight_t::pointIndex %i\n" "axBoneWeight_t::boneIndex: %i\n", i, axWeight->weight, axWeight->pointIndex, axWeight->boneIndex); #endif } // // convert the model to an internal MD5 representation // md5->numBones = numReferenceBones; // calc numMeshes <number> /* numSmoothGroups = 0; for(i = 0, triangle = triangles; i < numTriangles; i++, triangle++) { if(triangle->smoothingGroups) { } } */ if(md5->numBones < 1) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has no bones\n", modName); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); Com_Dealloc(refBones); Com_Dealloc(axWeights); return qfalse; } if(md5->numBones > MAX_BONES) { ri.Printf(PRINT_WARNING, "R_LoadPSK: '%s' has more than %i bones (%i)\n", modName, MAX_BONES, md5->numBones); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); Com_Dealloc(refBones); Com_Dealloc(axWeights); return qfalse; } //ri.Printf(PRINT_ALL, "R_LoadPSK: '%s' has %i bones\n", modName, md5->numBones); // copy all reference bones md5->bones = (md5Bone_t*)ri.Hunk_Alloc(sizeof(*md5Bone) * md5->numBones, h_low); for(i = 0, md5Bone = md5->bones, refBone = refBones; i < md5->numBones; i++, md5Bone++, refBone++) { Q_strncpyz(md5Bone->name, refBone->name, sizeof(md5Bone->name)); if(i == 0) { md5Bone->parentIndex = refBone->parentIndex -1; } else { md5Bone->parentIndex = refBone->parentIndex; } //ri.Printf(PRINT_ALL, "R_LoadPSK: '%s' has bone '%s' with parent index %i\n", modName, md5Bone->name, md5Bone->parentIndex); if(md5Bone->parentIndex >= md5->numBones) { ri.Error(ERR_DROP, "R_LoadPSK: '%s' has bone '%s' with bad parent index %i while numBones is %i\n", modName, md5Bone->name, md5Bone->parentIndex, md5->numBones); } for(j = 0; j < 3; j++) { boneOrigin[j] = refBone->bone.position[j]; } // Tr3B: I have really no idea why the .psk format stores the first quaternion with inverted quats. // Furthermore only the X and Z components of the first quat are inverted ?!?! if(i == 0) { boneQuat[0] = refBone->bone.quat[0]; boneQuat[1] = -refBone->bone.quat[1]; boneQuat[2] = refBone->bone.quat[2]; boneQuat[3] = refBone->bone.quat[3]; } else { boneQuat[0] = -refBone->bone.quat[0]; boneQuat[1] = -refBone->bone.quat[1]; boneQuat[2] = -refBone->bone.quat[2]; boneQuat[3] = refBone->bone.quat[3]; } VectorCopy(boneOrigin, md5Bone->origin); //MatrixTransformPoint(unrealToQuake, boneOrigin, md5Bone->origin); QuatCopy(boneQuat, md5Bone->rotation); //QuatClear(md5Bone->rotation); #if 0 ri.Printf(PRINT_ALL, "R_LoadPSK: md5Bone_t(%i):\n" "md5Bone_t::name: '%s'\n" "md5Bone_t::parentIndex: %i\n" "md5Bone_t::quat: %f %f %f %f\n" "md5bone_t::position: %f %f %f\n", i, md5Bone->name, md5Bone->parentIndex, md5Bone->rotation[0], md5Bone->rotation[1], md5Bone->rotation[2], md5Bone->rotation[3], md5Bone->origin[0], md5Bone->origin[1], md5Bone->origin[2]); #endif if(md5Bone->parentIndex >= 0) { vec3_t rotated; quat_t quat; md5Bone_t *parent; parent = &md5->bones[md5Bone->parentIndex]; QuatTransformVector(parent->rotation, md5Bone->origin, rotated); //QuatTransformVector(md5Bone->rotation, md5Bone->origin, rotated); VectorAdd(parent->origin, rotated, md5Bone->origin); QuatMultiply1(parent->rotation, md5Bone->rotation, quat); QuatCopy(quat, md5Bone->rotation); } MatrixSetupTransformFromQuat(md5Bone->inverseTransform, md5Bone->rotation, md5Bone->origin); MatrixInverse(md5Bone->inverseTransform); #if 0 ri.Printf(PRINT_ALL, "R_LoadPSK: md5Bone_t(%i):\n" "md5Bone_t::name: '%s'\n" "md5Bone_t::parentIndex: %i\n" "md5Bone_t::quat: %f %f %f %f\n" "md5bone_t::position: %f %f %f\n", i, md5Bone->name, md5Bone->parentIndex, md5Bone->rotation[0], md5Bone->rotation[1], md5Bone->rotation[2], md5Bone->rotation[3], md5Bone->origin[0], md5Bone->origin[1], md5Bone->origin[2]); #endif } Com_InitGrowList(&vboVertexes, 10000); for(i = 0, vertex = vertexes; i < numVertexes; i++, vertex++) { md5Vertex_t *vboVert = (md5Vertex_t*)Com_Allocate(sizeof(*vboVert)); for(j = 0; j < 3; j++) { vboVert->position[j] = points[vertex->pointIndex].point[j]; } vboVert->texCoords[0] = vertex->st[0]; vboVert->texCoords[1] = vertex->st[1]; // find number of associated weights vboVert->numWeights = 0; for(j = 0, axWeight = axWeights; j < numWeights; j++, axWeight++) { if(axWeight->pointIndex == vertex->pointIndex && axWeight->weight > 0.0f) { vboVert->numWeights++; } } if(vboVert->numWeights > MAX_WEIGHTS) { ri.Error(ERR_DROP, "R_LoadPSK: vertex %i requires more weights %i than the maximum of %i in model '%s'", i, vboVert->numWeights, MAX_WEIGHTS, modName); //ri.Printf(PRINT_WARNING, "R_LoadPSK: vertex %i requires more weights %i than the maximum of %i in model '%s'\n", i, vboVert->numWeights, MAX_WEIGHTS, modName); } vboVert->weights = (md5Weight_t**)ri.Hunk_Alloc(sizeof(*vboVert->weights) * vboVert->numWeights, h_low); for(j = 0, axWeight = axWeights, k = 0; j < numWeights; j++, axWeight++) { if(axWeight->pointIndex == vertex->pointIndex && axWeight->weight > 0.0f) { weight = (md5Weight_t*)ri.Hunk_Alloc(sizeof(*weight), h_low); weight->boneIndex = axWeight->boneIndex; weight->boneWeight = axWeight->weight; // FIXME? weight->offset[0] = refBones[axWeight->boneIndex].bone.xSize; weight->offset[1] = refBones[axWeight->boneIndex].bone.ySize; weight->offset[2] = refBones[axWeight->boneIndex].bone.zSize; vboVert->weights[k++] = weight; } } Com_AddToGrowList(&vboVertexes, vboVert); } ClearBounds(md5->bounds[0], md5->bounds[1]); for(i = 0, vertex = vertexes; i < numVertexes; i++, vertex++) { AddPointToBounds(points[vertex->pointIndex].point, md5->bounds[0], md5->bounds[1]); } #if 0 ri.Printf(PRINT_ALL, "R_LoadPSK: AABB (%i %i %i) (%i %i %i)\n", (int)md5->bounds[0][0], (int)md5->bounds[0][1], (int)md5->bounds[0][2], (int)md5->bounds[1][0], (int)md5->bounds[1][1], (int)md5->bounds[1][2]); #endif // sort triangles qsort(triangles, numTriangles, sizeof(axTriangle_t), CompareTrianglesByMaterialIndex); Com_InitGrowList(&sortedTriangles, 1000); for(i = 0, triangle = triangles; i < numTriangles; i++, triangle++) { skelTriangle_t *sortTri = (skelTriangle_t*)Com_Allocate(sizeof(*sortTri)); for(j = 0; j < 3; j++) { sortTri->indexes[j] = triangle->indexes[j]; sortTri->vertexes[j] = (md5Vertex_t*)Com_GrowListElement(&vboVertexes, triangle->indexes[j]); } sortTri->referenced = qfalse; Com_AddToGrowList(&sortedTriangles, sortTri); } // calc tangent spaces #if 1 { md5Vertex_t *v0, *v1, *v2; const float *p0, *p1, *p2; const float *t0, *t1, *t2; vec3_t tangent; vec3_t binormal; vec3_t normal; for(j = 0; j < vboVertexes.currentElements; j++) { v0 = (md5Vertex_t*)Com_GrowListElement(&vboVertexes, j); VectorClear(v0->tangent); VectorClear(v0->binormal); VectorClear(v0->normal); } for(j = 0; j < sortedTriangles.currentElements; j++) { skelTriangle_t *tri = (skelTriangle_t*)Com_GrowListElement(&sortedTriangles, j); v0 = (md5Vertex_t*)Com_GrowListElement(&vboVertexes, tri->indexes[0]); v1 = (md5Vertex_t*)Com_GrowListElement(&vboVertexes, tri->indexes[1]); v2 = (md5Vertex_t*)Com_GrowListElement(&vboVertexes, tri->indexes[2]); p0 = v0->position; p1 = v1->position; p2 = v2->position; t0 = v0->texCoords; t1 = v1->texCoords; t2 = v2->texCoords; #if 1 R_CalcTangentSpace(tangent, binormal, normal, p0, p1, p2, t0, t1, t2); #else R_CalcNormalForTriangle(normal, p0, p1, p2); R_CalcTangentsForTriangle(tangent, binormal, p0, p1, p2, t0, t1, t2); #endif for(k = 0; k < 3; k++) { float *v; v0 = (md5Vertex_t*)Com_GrowListElement(&vboVertexes, tri->indexes[k]); v = v0->tangent; VectorAdd(v, tangent, v); v = v0->binormal; VectorAdd(v, binormal, v); v = v0->normal; VectorAdd(v, normal, v); } } for(j = 0; j < vboVertexes.currentElements; j++) { v0 = (md5Vertex_t*)Com_GrowListElement(&vboVertexes, j); VectorNormalize(v0->tangent); VectorNormalize(v0->binormal); VectorNormalize(v0->normal); } } #else { float bb, s, t; vec3_t bary; vec3_t faceNormal; md5Vertex_t *dv[3]; for(j = 0; j < sortedTriangles.currentElements; j++) { skelTriangle_t *tri = Com_GrowListElement(&sortedTriangles, j); dv[0] = Com_GrowListElement(&vboVertexes, tri->indexes[0]); dv[1] = Com_GrowListElement(&vboVertexes, tri->indexes[1]); dv[2] = Com_GrowListElement(&vboVertexes, tri->indexes[2]); R_CalcNormalForTriangle(faceNormal, dv[0]->position, dv[1]->position, dv[2]->position); // calculate barycentric basis for the triangle bb = (dv[1]->texCoords[0] - dv[0]->texCoords[0]) * (dv[2]->texCoords[1] - dv[0]->texCoords[1]) - (dv[2]->texCoords[0] - dv[0]->texCoords[0]) * (dv[1]->texCoords[1] - dv[0]->texCoords[1]); if(fabs(bb) < 0.00000001f) continue; // do each vertex for(k = 0; k < 3; k++) { // calculate s tangent vector s = dv[k]->texCoords[0] + 10.0f; t = dv[k]->texCoords[1]; bary[0] = ((dv[1]->texCoords[0] - s) * (dv[2]->texCoords[1] - t) - (dv[2]->texCoords[0] - s) * (dv[1]->texCoords[1] - t)) / bb; bary[1] = ((dv[2]->texCoords[0] - s) * (dv[0]->texCoords[1] - t) - (dv[0]->texCoords[0] - s) * (dv[2]->texCoords[1] - t)) / bb; bary[2] = ((dv[0]->texCoords[0] - s) * (dv[1]->texCoords[1] - t) - (dv[1]->texCoords[0] - s) * (dv[0]->texCoords[1] - t)) / bb; dv[k]->tangent[0] = bary[0] * dv[0]->position[0] + bary[1] * dv[1]->position[0] + bary[2] * dv[2]->position[0]; dv[k]->tangent[1] = bary[0] * dv[0]->position[1] + bary[1] * dv[1]->position[1] + bary[2] * dv[2]->position[1]; dv[k]->tangent[2] = bary[0] * dv[0]->position[2] + bary[1] * dv[1]->position[2] + bary[2] * dv[2]->position[2]; VectorSubtract(dv[k]->tangent, dv[k]->position, dv[k]->tangent); VectorNormalize(dv[k]->tangent); // calculate t tangent vector (binormal) s = dv[k]->texCoords[0]; t = dv[k]->texCoords[1] + 10.0f; bary[0] = ((dv[1]->texCoords[0] - s) * (dv[2]->texCoords[1] - t) - (dv[2]->texCoords[0] - s) * (dv[1]->texCoords[1] - t)) / bb; bary[1] = ((dv[2]->texCoords[0] - s) * (dv[0]->texCoords[1] - t) - (dv[0]->texCoords[0] - s) * (dv[2]->texCoords[1] - t)) / bb; bary[2] = ((dv[0]->texCoords[0] - s) * (dv[1]->texCoords[1] - t) - (dv[1]->texCoords[0] - s) * (dv[0]->texCoords[1] - t)) / bb; dv[k]->binormal[0] = bary[0] * dv[0]->position[0] + bary[1] * dv[1]->position[0] + bary[2] * dv[2]->position[0]; dv[k]->binormal[1] = bary[0] * dv[0]->position[1] + bary[1] * dv[1]->position[1] + bary[2] * dv[2]->position[1]; dv[k]->binormal[2] = bary[0] * dv[0]->position[2] + bary[1] * dv[1]->position[2] + bary[2] * dv[2]->position[2]; VectorSubtract(dv[k]->binormal, dv[k]->position, dv[k]->binormal); VectorNormalize(dv[k]->binormal); // calculate the normal as cross product N=TxB #if 0 CrossProduct(dv[k]->tangent, dv[k]->binormal, dv[k]->normal); VectorNormalize(dv[k]->normal); // Gram-Schmidt orthogonalization process for B // compute the cross product B=NxT to obtain // an orthogonal basis CrossProduct(dv[k]->normal, dv[k]->tangent, dv[k]->binormal); if(DotProduct(dv[k]->normal, faceNormal) < 0) { VectorInverse(dv[k]->normal); //VectorInverse(dv[k]->tangent); //VectorInverse(dv[k]->binormal); } #else VectorAdd(dv[k]->normal, faceNormal, dv[k]->normal); #endif } } #if 1 for(j = 0; j < vboVertexes.currentElements; j++) { dv[0] = Com_GrowListElement(&vboVertexes, j); //VectorNormalize(dv[0]->tangent); //VectorNormalize(dv[0]->binormal); VectorNormalize(dv[0]->normal); } #endif } #endif #if 0 { md5Vertex_t *v0, *v1; // do another extra smoothing for normals to avoid flat shading for(j = 0; j < vboVertexes.currentElements; j++) { v0 = Com_GrowListElement(&vboVertexes, j); for(k = 0; k < vboVertexes.currentElements; k++) { if(j == k) continue; v1 = Com_GrowListElement(&vboVertexes, k); if(VectorCompare(v0->position, v1->position)) { VectorAdd(v0->position, v1->normal, v0->normal); } } VectorNormalize(v0->normal); } } #endif // split the surfaces into VBO surfaces by the maximum number of GPU vertex skinning bones Com_InitGrowList(&vboSurfaces, 10); materialIndex = oldMaterialIndex = -1; for(i = 0; i < numTriangles; i++) { triangle = &triangles[i]; materialIndex = triangle->materialIndex; if(materialIndex != oldMaterialIndex) { oldMaterialIndex = materialIndex; numRemaining = sortedTriangles.currentElements - i; while(numRemaining) { numBoneReferences = 0; Com_Memset(boneReferences, 0, sizeof(boneReferences)); Com_InitGrowList(&vboTriangles, 1000); for(j = i; j < sortedTriangles.currentElements; j++) { skelTriangle_t *sortTri; triangle = &triangles[j]; materialIndex = triangle->materialIndex; if(materialIndex != oldMaterialIndex) continue; sortTri = (skelTriangle_t*)Com_GrowListElement(&sortedTriangles, j); if(sortTri->referenced) continue; if(AddTriangleToVBOTriangleList(&vboTriangles, sortTri, &numBoneReferences, boneReferences)) { sortTri->referenced = qtrue; } } for(j = 0; j < MAX_BONES; j++) { if(boneReferences[j] > 0) { ri.Printf(PRINT_ALL, "R_LoadPSK: referenced bone: '%s'\n", (j < numReferenceBones) ? refBones[j].name : NULL); } } if(!vboTriangles.currentElements) { ri.Printf(PRINT_WARNING, "R_LoadPSK: could not add triangles to a remaining VBO surface for model '%s'\n", modName); break; } // FIXME skinIndex AddSurfaceToVBOSurfacesList2(&vboSurfaces, &vboTriangles, &vboVertexes, md5, vboSurfaces.currentElements, materials[oldMaterialIndex].name, numBoneReferences, boneReferences); numRemaining -= vboTriangles.currentElements; Com_DestroyGrowList(&vboTriangles); } } } for(j = 0; j < sortedTriangles.currentElements; j++) { skelTriangle_t *sortTri = (skelTriangle_t*)Com_GrowListElement(&sortedTriangles, j); Com_Dealloc(sortTri); } Com_DestroyGrowList(&sortedTriangles); for(j = 0; j < vboVertexes.currentElements; j++) { md5Vertex_t *v = (md5Vertex_t*)Com_GrowListElement(&vboVertexes, j); Com_Dealloc(v); } Com_DestroyGrowList(&vboVertexes); // move VBO surfaces list to hunk md5->numVBOSurfaces = vboSurfaces.currentElements; md5->vboSurfaces = (srfVBOMD5Mesh_t**)ri.Hunk_Alloc(md5->numVBOSurfaces * sizeof(*md5->vboSurfaces), h_low); for(i = 0; i < md5->numVBOSurfaces; i++) { md5->vboSurfaces[i] = (srfVBOMD5Mesh_t *) Com_GrowListElement(&vboSurfaces, i); } Com_DestroyGrowList(&vboSurfaces); FreeMemStream(stream); Com_Dealloc(points); Com_Dealloc(vertexes); Com_Dealloc(triangles); Com_Dealloc(materials); Com_Dealloc(refBones); Com_Dealloc(axWeights); ri.Printf(PRINT_ALL, "%i VBO surfaces created for PSK model '%s'\n", md5->numVBOSurfaces, modName); return qtrue; }
/*---------------------------------------------------------------*/ int main(int argc, char **argv) { char *srcsubj; float betplaneres, inplaneres, intensity; MATRIX *R, *Xsrc, *invXsrc, *Xtarg, *Rtarg; int float2int, err; Progname = argv[0] ; argc --; argv++; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; if (argc == 0) usage_exit(); parse_commandline(argc, argv); check_options(); dump_options(stdout); /* Load the registration matrix, fix if necessary */ err = regio_read_register(srcregpath, &srcsubj, &inplaneres, &betplaneres, &intensity, &R, &float2int); if (err) exit(1); printf("---- Input registration matrix --------\n"); MatrixPrint(stdout,R); if (float2int == FLT2INT_TKREG && fixtkreg) { if (fvolid == NULL) { printf("ERROR: the input registration file requires that you " "supply an example functional volume with --fvol\n"); exit(1); } FuncMRI = MRIreadHeader(fvolid,MRI_VOLUME_TYPE_UNKNOWN); if (FuncMRI==NULL) exit(1); printf("INFO: making tkreg matrix compatible with round\n"); R = MRIfixTkReg(FuncMRI,R); printf("---- Fixed input registration matrix --------\n"); MatrixPrint(stdout,R); } float2int = FLT2INT_ROUND; /* Load the source subject xfm */ Xsrc = DevolveXFM(srcsubj,NULL,xfmrname); if (Xsrc == NULL) exit(1); invXsrc = MatrixInverse(Xsrc,NULL); /* Load the target subject xfm */ Xtarg = DevolveXFM(targsubj,NULL,xfmrname); if (Xtarg == NULL) exit(1); /* Rtarg = R*inv(Xsrc)*Xtarg */ Rtarg = MatrixMultiply(R,invXsrc,NULL); Rtarg = MatrixMultiply(Rtarg,Xtarg,Rtarg); printf("---- New registration matrix --------\n"); MatrixPrint(stdout,Rtarg); err = regio_write_register(targregpath, targsubj, inplaneres, betplaneres, intensity, Rtarg, float2int); if (err) { printf("ERROR: could not write to %s\n",targregpath); exit(1); } return(0); exit(0); }
float computePairCNR(float *LDAmean1, float *LDAmean2, MATRIX *SW1, MATRIX *SW2, float classSize1, float classSize2, int nvolumes_total, float *weights, int flag) { /* if flag == 1, output the optimal weights to weights */ float cnr; int m1, m2; MATRIX *SW, *SB, *InvSW; float *weight; double value1, value2; if (classSize1 < 0.5 || classSize2 < 0.5) { printf("One of the two classes is empty\n"); return 0; } SW = (MATRIX *)MatrixAlloc(nvolumes_total, nvolumes_total, MATRIX_REAL); SB = (MATRIX *)MatrixAlloc(nvolumes_total, nvolumes_total, MATRIX_REAL); weight = (float *)malloc(nvolumes_total*sizeof(float)); /* initialize all */ for (m1=1; m1 <= nvolumes_total; m1++) { for (m2=1; m2 <= nvolumes_total; m2++) { SW->rptr[m1][m2] = 0.5*(SW1->rptr[m1][m2] + SW2->rptr[m1][m2]); /* index starts from 1 for matrix */ SB->rptr[m1][m2] = 0.0; /* index starts from 1 for matrix */ } /* weight[m1-1] = 0.0; */ /*initialize later */ } for (m1=1; m1 <= nvolumes_total; m1++) { value1 = LDAmean1[m1-1] - LDAmean2[m1-1]; for (m2=m1; m2 <= nvolumes_total; m2++) { value2 = LDAmean1[m2-1] - LDAmean2[m2-1]; SB->rptr[m1][m2] += value1*value2; SB->rptr[m2][m1] = SB->rptr[m1][m2]; } } InvSW = MatrixInverse(SW, NULL); /* compute the optimal weight that will give largest CNR for the two * classes! Note that the weight differs depending on which formula * to use to evaluate final CNR * Here, the weight is consistent with the following definition: * CNR = |\mu_1 - \mu_2|\sqrt((\sigma_1^2 + \sigma_2^2)*0.5) */ for (m1=1; m1 <= nvolumes_total; m1++) { weight[m1-1]= 0.0; for (m2=1; m2 <= nvolumes_total; m2++) { weight[m1-1] += InvSW->rptr[m1][m2] *(LDAmean1[m2-1] - LDAmean2[m2-1]); } } /* compute CNR */ cnr = 0 ; value1 = 0.0; value2 = 0.0; /* borrowed */ for (m1=0; m1 < nvolumes_total; m1++) { cnr += weight[m1]*(LDAmean1[m1] - LDAmean2[m1]); if (flag) { value1 += weight[m1]; value2 += weight[m1]*weight[m1]; } } if (flag && weights != NULL) { value2 = sqrt(value2); for (m1=0; m1 < nvolumes_total; m1++) { if (value1 > 0) weights[m1] = weight[m1]/(value2 + 1e-15); else weights[m1] = -weight[m1]/(value2 + 1e-15); } } cnr = sqrt(cnr); MatrixFree(&SW); MatrixFree(&InvSW); MatrixFree(&SB); free(weight); return cnr; }
/* ================= R_LoadMD5 ================= */ qboolean R_LoadMD5( model_t *mod, void *buffer, int bufferSize, const char *modName ) { int i, j, k; md5Model_t *md5; md5Bone_t *bone; md5Surface_t *surf; md5Triangle_t *tri; md5Vertex_t *v; md5Weight_t *weight; int version; shader_t *sh; char *buf_p; char *token; vec3_t boneOrigin; quat_t boneQuat; matrix_t boneMat; buf_p = ( char * ) buffer; // skip MD5Version indent string COM_ParseExt2( &buf_p, qfalse ); // check version token = COM_ParseExt2( &buf_p, qfalse ); version = atoi( token ); if ( version != MD5_VERSION ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: %s has wrong version (%i should be %i)\n", modName, version, MD5_VERSION ); return qfalse; } mod->type = MOD_MD5; mod->dataSize += sizeof( md5Model_t ); md5 = mod->model.md5 = ri.Hunk_Alloc( sizeof( md5Model_t ), h_low ); // skip commandline <arguments string> token = COM_ParseExt2( &buf_p, qtrue ); token = COM_ParseExt2( &buf_p, qtrue ); // ri.Printf(PRINT_ALL, "%s\n", token); // parse numJoints <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "numJoints" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'numJoints' found '%s' in model '%s'\n", token, modName ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); md5->numBones = atoi( token ); // parse numMeshes <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "numMeshes" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'numMeshes' found '%s' in model '%s'\n", token, modName ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); md5->numSurfaces = atoi( token ); //ri.Printf(PRINT_ALL, "R_LoadMD5: '%s' has %i surfaces\n", modName, md5->numSurfaces); if ( md5->numBones < 1 ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: '%s' has no bones\n", modName ); return qfalse; } if ( md5->numBones > MAX_BONES ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: '%s' has more than %i bones (%i)\n", modName, MAX_BONES, md5->numBones ); return qfalse; } //ri.Printf(PRINT_ALL, "R_LoadMD5: '%s' has %i bones\n", modName, md5->numBones); // parse all the bones md5->bones = ri.Hunk_Alloc( sizeof( *bone ) * md5->numBones, h_low ); // parse joints { token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "joints" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'joints' found '%s' in model '%s'\n", token, modName ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "{" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '{' found '%s' in model '%s'\n", token, modName ); return qfalse; } for ( i = 0, bone = md5->bones; i < md5->numBones; i++, bone++ ) { token = COM_ParseExt2( &buf_p, qtrue ); Q_strncpyz( bone->name, token, sizeof( bone->name ) ); //ri.Printf(PRINT_ALL, "R_LoadMD5: '%s' has bone '%s'\n", modName, bone->name); token = COM_ParseExt2( &buf_p, qfalse ); bone->parentIndex = atoi( token ); //ri.Printf(PRINT_ALL, "R_LoadMD5: '%s' has bone '%s' with parent index %i\n", modName, bone->name, bone->parentIndex); if ( bone->parentIndex >= md5->numBones ) { ri.Error( ERR_DROP, "R_LoadMD5: '%s' has bone '%s' with bad parent index %i while numBones is %i\n", modName, bone->name, bone->parentIndex, md5->numBones ); } // skip ( token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "(" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '(' found '%s' in model '%s'\n", token, modName ); return qfalse; } for ( j = 0; j < 3; j++ ) { token = COM_ParseExt2( &buf_p, qfalse ); boneOrigin[ j ] = atof( token ); } // skip ) token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, ")" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected ')' found '%s' in model '%s'\n", token, modName ); return qfalse; } // skip ( token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "(" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '(' found '%s' in model '%s'\n", token, modName ); return qfalse; } for ( j = 0; j < 3; j++ ) { token = COM_ParseExt2( &buf_p, qfalse ); boneQuat[ j ] = atof( token ); } QuatCalcW( boneQuat ); MatrixFromQuat( boneMat, boneQuat ); VectorCopy( boneOrigin, bone->origin ); QuatCopy( boneQuat, bone->rotation ); MatrixSetupTransformFromQuat( bone->inverseTransform, boneQuat, boneOrigin ); MatrixInverse( bone->inverseTransform ); // skip ) token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, ")" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '(' found '%s' in model '%s'\n", token, modName ); return qfalse; } } // parse } token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "}" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '}' found '%s' in model '%s'\n", token, modName ); return qfalse; } // parse all the surfaces if ( md5->numSurfaces < 1 ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: '%s' has no surfaces\n", modName ); return qfalse; } //ri.Printf(PRINT_ALL, "R_LoadMD5: '%s' has %i surfaces\n", modName, md5->numSurfaces); md5->surfaces = ri.Hunk_Alloc( sizeof( *surf ) * md5->numSurfaces, h_low ); for ( i = 0, surf = md5->surfaces; i < md5->numSurfaces; i++, surf++ ) { // parse mesh { token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "mesh" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'mesh' found '%s' in model '%s'\n", token, modName ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "{" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '{' found '%s' in model '%s'\n", token, modName ); return qfalse; } // change to surface identifier surf->surfaceType = SF_MD5; // give pointer to model for Tess_SurfaceMD5 surf->model = md5; // parse shader <name> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "shader" ) ) { Q_strncpyz( surf->shader, "<default>", sizeof( surf->shader ) ); surf->shaderIndex = 0; } else { token = COM_ParseExt2( &buf_p, qfalse ); Q_strncpyz( surf->shader, token, sizeof( surf->shader ) ); //ri.Printf(PRINT_ALL, "R_LoadMD5: '%s' uses shader '%s'\n", modName, surf->shader); // FIXME .md5mesh meshes don't have surface names // lowercase the surface name so skin compares are faster //Q_strlwr(surf->name); //ri.Printf(PRINT_ALL, "R_LoadMD5: '%s' has surface '%s'\n", modName, surf->name); // register the shaders sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue ); if ( sh->defaultShader ) { surf->shaderIndex = 0; } else { surf->shaderIndex = sh->index; } token = COM_ParseExt2( &buf_p, qtrue ); } // parse numVerts <number> if ( Q_stricmp( token, "numVerts" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'numVerts' found '%s' in model '%s'\n", token, modName ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); surf->numVerts = atoi( token ); if ( surf->numVerts > SHADER_MAX_VERTEXES ) { ri.Error( ERR_DROP, "R_LoadMD5: '%s' has more than %i verts on a surface (%i)", modName, SHADER_MAX_VERTEXES, surf->numVerts ); } surf->verts = ri.Hunk_Alloc( sizeof( *v ) * surf->numVerts, h_low ); for ( j = 0, v = surf->verts; j < surf->numVerts; j++, v++ ) { // skip vert <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "vert" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'vert' found '%s' in model '%s'\n", token, modName ); return qfalse; } COM_ParseExt2( &buf_p, qfalse ); // skip ( token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "(" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '(' found '%s' in model '%s'\n", token, modName ); return qfalse; } for ( k = 0; k < 2; k++ ) { token = COM_ParseExt2( &buf_p, qfalse ); v->texCoords[ k ] = atof( token ); } // skip ) token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, ")" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected ')' found '%s' in model '%s'\n", token, modName ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); v->firstWeight = atoi( token ); token = COM_ParseExt2( &buf_p, qfalse ); v->numWeights = atoi( token ); if ( v->numWeights > MAX_WEIGHTS ) { ri.Error( ERR_DROP, "R_LoadMD5: vertex %i requires more than %i weights on surface (%i) in model '%s'", j, MAX_WEIGHTS, i, modName ); } } // parse numTris <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "numTris" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'numTris' found '%s' in model '%s'\n", token, modName ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); surf->numTriangles = atoi( token ); if ( surf->numTriangles > SHADER_MAX_TRIANGLES ) { ri.Error( ERR_DROP, "R_LoadMD5: '%s' has more than %i triangles on a surface (%i)", modName, SHADER_MAX_TRIANGLES, surf->numTriangles ); } surf->triangles = ri.Hunk_Alloc( sizeof( *tri ) * surf->numTriangles, h_low ); for ( j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++ ) { // skip tri <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "tri" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'tri' found '%s' in model '%s'\n", token, modName ); return qfalse; } COM_ParseExt2( &buf_p, qfalse ); for ( k = 0; k < 3; k++ ) { token = COM_ParseExt2( &buf_p, qfalse ); tri->indexes[ k ] = atoi( token ); } } // parse numWeights <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "numWeights" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'numWeights' found '%s' in model '%s'\n", token, modName ); return qfalse; } token = COM_ParseExt2( &buf_p, qfalse ); surf->numWeights = atoi( token ); surf->weights = ri.Hunk_Alloc( sizeof( *weight ) * surf->numWeights, h_low ); for ( j = 0, weight = surf->weights; j < surf->numWeights; j++, weight++ ) { // skip weight <number> token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "weight" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected 'weight' found '%s' in model '%s'\n", token, modName ); return qfalse; } COM_ParseExt2( &buf_p, qfalse ); token = COM_ParseExt2( &buf_p, qfalse ); weight->boneIndex = atoi( token ); token = COM_ParseExt2( &buf_p, qfalse ); weight->boneWeight = atof( token ); // skip ( token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, "(" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '(' found '%s' in model '%s'\n", token, modName ); return qfalse; } for ( k = 0; k < 3; k++ ) { token = COM_ParseExt2( &buf_p, qfalse ); weight->offset[ k ] = atof( token ); } // skip ) token = COM_ParseExt2( &buf_p, qfalse ); if ( Q_stricmp( token, ")" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected ')' found '%s' in model '%s'\n", token, modName ); return qfalse; } } // parse } token = COM_ParseExt2( &buf_p, qtrue ); if ( Q_stricmp( token, "}" ) ) { ri.Printf( PRINT_WARNING, "R_LoadMD5: expected '}' found '%s' in model '%s'\n", token, modName ); return qfalse; } // loop trough all vertices and set up the vertex weights for ( j = 0, v = surf->verts; j < surf->numVerts; j++, v++ ) { v->weights = ri.Hunk_Alloc( sizeof( *v->weights ) * v->numWeights, h_low ); for ( k = 0; k < v->numWeights; k++ ) { v->weights[ k ] = surf->weights + ( v->firstWeight + k ); } } } // loading is done now calculate the bounding box and tangent spaces ClearBounds( md5->bounds[ 0 ], md5->bounds[ 1 ] ); for ( i = 0, surf = md5->surfaces; i < md5->numSurfaces; i++, surf++ ) { for ( j = 0, v = surf->verts; j < surf->numVerts; j++, v++ ) { vec3_t tmpVert; md5Weight_t *w; VectorClear( tmpVert ); for ( k = 0, w = v->weights[ 0 ]; k < v->numWeights; k++, w++ ) { vec3_t offsetVec; bone = &md5->bones[ w->boneIndex ]; QuatTransformVector( bone->rotation, w->offset, offsetVec ); VectorAdd( bone->origin, offsetVec, offsetVec ); VectorMA( tmpVert, w->boneWeight, offsetVec, tmpVert ); } VectorCopy( tmpVert, v->position ); AddPointToBounds( tmpVert, md5->bounds[ 0 ], md5->bounds[ 1 ] ); } // calc normals { const float *v0, *v1, *v2; const float *t0, *t1, *t2; vec3_t normal; for ( j = 0, v = surf->verts; j < surf->numVerts; j++, v++ ) { VectorClear( v->tangent ); VectorClear( v->binormal ); VectorClear( v->normal ); } for ( j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++ ) { v0 = surf->verts[ tri->indexes[ 0 ] ].position; v1 = surf->verts[ tri->indexes[ 1 ] ].position; v2 = surf->verts[ tri->indexes[ 2 ] ].position; t0 = surf->verts[ tri->indexes[ 0 ] ].texCoords; t1 = surf->verts[ tri->indexes[ 1 ] ].texCoords; t2 = surf->verts[ tri->indexes[ 2 ] ].texCoords; R_CalcNormalForTriangle( normal, v0, v1, v2 ); for ( k = 0; k < 3; k++ ) { float *v; v = surf->verts[ tri->indexes[ k ] ].normal; VectorAdd( v, normal, v ); } } for ( j = 0, v = surf->verts; j < surf->numVerts; j++, v++ ) { VectorNormalize( v->normal ); } } #if 0 // do another extra smoothing for normals to avoid flat shading for ( j = 0; j < surf->numVerts; j++ ) { for ( k = 0; k < surf->numVerts; k++ ) { if ( j == k ) { continue; } if ( VectorCompare( surf->verts[ j ].position, surf->verts[ k ].position ) ) { VectorAdd( surf->verts[ j ].normal, surf->verts[ k ].normal, surf->verts[ j ].normal ); } } VectorNormalize( surf->verts[ j ].normal ); } #endif } return qtrue; }
int main(int argc, char *argv[]) { char **av, *ltafn1, *ltafn2, *ltafn_total; LTA *lta1, *lta2, *lta_total; FILE *fo; MATRIX *r_to_i_1, *i_to_r_1, *i_to_r_2, *r_to_i_2; MATRIX *RAS_1_to_1, *RAS_2_to_2, *m_tmp; int nargs, ac; int type = 0; Progname = argv[0]; nargs = handle_version_option (argc, argv, "$Id: mri_concatenate_lta.c,v 1.5 2011/03/02 00:04:55 nicks Exp $", "$Name: $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc != 4) usage(1); ltafn1 = argv[1]; ltafn2 = argv[2]; ltafn_total = argv[3]; printf("Read individual LTAs\n"); lta1 = ltaReadFileEx(ltafn1); if (!lta1) ErrorExit(ERROR_BADFILE, "%s: can't read file %s",Progname, ltafn1); if (invert1) { VOL_GEOM vgtmp; LT *lt; MATRIX *m_tmp = lta1->xforms[0].m_L ; lta1->xforms[0].m_L = MatrixInverse(lta1->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a1->xforms[0]; if (lt->dst.valid == 0 || lt->src.valid == 0) { fprintf(stderr, "WARNING:***************************************************************\n"); fprintf(stderr, "WARNING:dst volume infor is invalid. Most likely produce wrong inverse.\n"); fprintf(stderr, "WARNING:***************************************************************\n"); } copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); } type = TransformFileNameType(ltafn2); if (type == MNI_TRANSFORM_TYPE) { if (invert2 != 0) ErrorExit(ERROR_BADFILE, "%s: LTA2 is talairach.xfm, and shouldn't be inverted ",Progname); lta2 = ltaMNIreadEx(ltafn2) ; //the talairach xform is supposed to be linear_RAS_TO_RAS, right? Yes lta2->type = LINEAR_RAS_TO_RAS; if (tal_src_file == 0 && lta2->xforms[0].src.valid == 0) ErrorExit(ERROR_BADFILE, "%s: pls use -tal option to give talairach src and template filenames",Progname); if (tal_dst_file == 0 && lta2->xforms[0].dst.valid == 0) ErrorExit(ERROR_BADFILE, "%s: pls use -tal option to give talairach src and template filenames",Progname); if (tal_src_file != 0) LTAmodifySrcDstGeom(lta2, tal_src, NULL); // add src and dst information if (tal_dst_file != 0) LTAmodifySrcDstGeom(lta2, NULL, tal_dst); // add src and dst information } else lta2 = ltaReadFileEx(ltafn2); if (!lta2) ErrorExit(ERROR_BADFILE, "%s: can't read file %s",Progname, ltafn2); if (invert2) { VOL_GEOM vgtmp; LT *lt; MATRIX *m_tmp = lta2->xforms[0].m_L ; lta2->xforms[0].m_L = MatrixInverse(lta2->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a2->xforms[0]; if (lt->dst.valid == 0 || lt->src.valid == 0) { fprintf(stderr, "WARNING:***************************************************************\n"); fprintf(stderr, "WARNING:dst volume infor is invalid. Most likely produce wrong inverse.\n"); fprintf(stderr, "WARNING:***************************************************************\n"); } copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); } if (vg_isEqual(<a1->xforms[0].dst, <a2->xforms[0].src) == 0) { /* ErrorExit(ERROR_BADFILE, "%s: dst volume of lta1 doesn't match src volume of lta2",Progname);*/ printf("Warning: dst volume of lta1 doesn't match src volume of lta2\n"); printf("Volume geometry for lta1-dst:\n"); vg_print(<a1->xforms[0].dst); printf("Volume geometry for lta2-src:\n"); vg_print(<a2->xforms[0].src); } printf("Combine the two LTAs to get a RAS-to-RAS from src of LTA1 to dst of LTA2\n"); if (lta1->type == LINEAR_RAS_TO_RAS) { RAS_1_to_1 = MatrixCopy(lta1->xforms[0].m_L, NULL); } else if (lta1->type == LINEAR_VOX_TO_VOX) { r_to_i_1 = vg_r_to_i(<a1->xforms[0].src); i_to_r_1 = vg_i_to_r(<a1->xforms[0].dst); if (!r_to_i_1 || !i_to_r_1) ErrorExit(ERROR_BADFILE, "%s: failed to convert LTA1 to RAS_to_RAS",Progname); m_tmp = MatrixMultiply(lta1->xforms[0].m_L, r_to_i_1, NULL); RAS_1_to_1 = MatrixMultiply(i_to_r_1, m_tmp, NULL); MatrixFree(&m_tmp); } else { ErrorExit(ERROR_BADFILE, "%s: unknown transform type for LTA1",Progname); } if (lta2->type == LINEAR_RAS_TO_RAS) { RAS_2_to_2 = MatrixCopy(lta2->xforms[0].m_L, NULL); } else if (lta2->type == LINEAR_VOX_TO_VOX) { r_to_i_2 = vg_r_to_i(<a2->xforms[0].src); i_to_r_2 = vg_i_to_r(<a2->xforms[0].dst); if (!r_to_i_2 || !i_to_r_2) ErrorExit(ERROR_BADFILE, "%s: failed to convert LTA1 to RAS_to_RAS",Progname); m_tmp = MatrixMultiply(lta2->xforms[0].m_L, r_to_i_2, NULL); RAS_2_to_2 = MatrixMultiply(i_to_r_2, m_tmp, NULL); MatrixFree(&m_tmp); } else { ErrorExit(ERROR_BADFILE, "%s: unknown transform type for LTA1",Progname); } lta_total = LTAalloc(1, NULL); lta_total->type = LINEAR_RAS_TO_RAS; MatrixMultiply(RAS_2_to_2, RAS_1_to_1, lta_total->xforms[0].m_L); lta_total->xforms[0].src = lta1->xforms[0].src; lta_total->xforms[0].dst = lta2->xforms[0].dst; lta_total->xforms[0].x0 = 0; lta_total->xforms[0].y0 = 0; lta_total->xforms[0].z0 = 0; lta_total->xforms[0].sigma = 1.0f; type = TransformFileNameType(ltafn_total); if (type == MNI_TRANSFORM_TYPE) { ltaMNIwrite(lta_total, ltafn_total); } else { //change type to VOXEL_VOXEL if (lta_total->type != out_type) LTAchangeType(lta_total, out_type); printf("Write combined LTA to file %s\n", ltafn_total); fo = fopen(ltafn_total,"w"); if (fo==NULL) ErrorExit(ERROR_BADFILE, "%s: can't create file %s",Progname, ltafn_total); LTAprint(fo, lta_total); fclose(fo); } LTAfree(<a1); LTAfree(<a2); LTAfree(<a_total); MatrixFree(&RAS_1_to_1); MatrixFree(&RAS_2_to_2); if (tal_src) MRIfree(&tal_src); if (tal_dst) MRIfree(&tal_dst); return(0); } /* end main() */
void display(void) { float mview[16],imview[16]; char buffer[128]; shadowmap(); glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45,4.0 / 3.0,1,2048); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(camerapos[0],camerapos[1],camerapos[2], cameradir[0],cameradir[1],cameradir[2], 0,0,1); glLightfv(GL_LIGHT0,GL_POSITION,lightpos); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); glEnable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); // draw model glBindTexture(GL_TEXTURE_2D,texturemodel); glPushMatrix(); glTranslatef(objpos[0],objpos[1],objpos[2]); glRotatef(modelangle,0,0,1); glCallList(modellist); glPopMatrix(); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_LIGHTING); glBindTexture(GL_TEXTURE_2D,textureground); // draw ground glCallList(groundlist); glDisable(GL_TEXTURE_2D); glPushMatrix(); // light sources glTranslatef(lightpos[0],lightpos[1],lightpos[2]); glColor4f(0,1,0,1); glCallList(lightlist); glColor4f(1,1,1,1); glPopMatrix(); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glEnable(GL_TEXTURE_GEN_Q); glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexGeni(GL_Q,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glGetFloatv(GL_MODELVIEW_MATRIX,mview); MatrixInverse(mview,imview); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glTranslatef(0.5,0.5,0); glScalef(0.5,0.5,1.0); glOrtho(-modelsize,modelsize,-modelsize,modelsize,-1,1); gluLookAt(lightpos[0],lightpos[1],lightpos[2], objpos[0],objpos[1],objpos[2], 0,1,0); glMultMatrixf(imview); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); // shadow glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR); glBindTexture(GL_TEXTURE_2D,textureshadow); glCallList(groundlist); glDisable(GL_BLEND); glMatrixMode(GL_MODELVIEW); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); glDisable(GL_TEXTURE_GEN_Q); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1,1,-1,1,-1,1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor4f(1,1,1,1); glDisable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); sprintf(buffer,"fps: %.2f",getfps()); drawstring(-0.95,0.95,buffer); glEnable(GL_DEPTH_TEST); glutSwapBuffers(); }
int MRIcomputePartialVolumeFractions(MRI *mri_src, MATRIX *m_vox2vox, MRI *mri_seg, MRI *mri_wm, MRI *mri_subcort_gm, MRI *mri_cortex, MRI *mri_csf, int wm_val, int subcort_gm_val, int cortex_val, int csf_val) { int x, y, z, xs, ys, zs, label ; VECTOR *v1, *v2 ; MRI *mri_counts ; float val, count ; MATRIX *m_inv ; m_inv = MatrixInverse(m_vox2vox, NULL) ; if (m_inv == NULL) { MatrixPrint(stdout, m_vox2vox) ; ErrorExit(ERROR_BADPARM, "MRIcomputePartialVolumeFractions: non-invertible vox2vox matrix"); } mri_counts = MRIcloneDifferentType(mri_src, MRI_INT) ; v1 = VectorAlloc(4, MATRIX_REAL) ; v2 = VectorAlloc(4, MATRIX_REAL) ; VECTOR_ELT(v1, 4) = 1.0 ; VECTOR_ELT(v2, 4) = 1.0 ; for (x = 0 ; x < mri_seg->width ; x++) { V3_X(v1) = x ; for (y = 0 ; y < mri_seg->height ; y++) { V3_Y(v1) = y ; for (z = 0 ; z < mri_seg->depth ; z++) { if (x == Gx && y == Gy && z == Gz) DiagBreak() ; V3_Z(v1) = z ; MatrixMultiply(m_vox2vox, v1, v2) ; xs = nint(V3_X(v2)) ; ys = nint(V3_Y(v2)) ; zs = nint(V3_Z(v2)) ; if (xs >= 0 && ys >= 0 && zs >= 0 && xs < mri_src->width && ys < mri_src->height && zs < mri_src->depth) { val = MRIgetVoxVal(mri_counts, xs, ys, zs, 0) ; MRIsetVoxVal(mri_counts, xs, ys, zs, 0, val+1) ; label = MRIgetVoxVal(mri_seg, x, y, z, 0) ; if (label == csf_val) { val = MRIgetVoxVal(mri_csf, xs, ys, zs, 0) ; MRIsetVoxVal(mri_csf, xs, ys, zs, 0, val+1) ; } else if (label == wm_val) { val = MRIgetVoxVal(mri_wm, xs, ys, zs, 0) ; MRIsetVoxVal(mri_wm, xs, ys, zs, 0, val+1) ; } else if (label == subcort_gm_val) { val = MRIgetVoxVal(mri_subcort_gm, xs, ys, zs, 0) ; MRIsetVoxVal(mri_subcort_gm, xs, ys, zs, 0, val+1) ; } else if (label == cortex_val) { val = MRIgetVoxVal(mri_cortex, xs, ys, zs, 0) ; MRIsetVoxVal(mri_cortex, xs, ys, zs, 0, val+1) ; } else DiagBreak() ; } } } } for (x = 0 ; x < mri_src->width ; x++) for (y = 0 ; y < mri_src->height ; y++) for (z = 0 ; z < mri_src->depth ; z++) { count = MRIgetVoxVal(mri_counts, x, y, z, 0) ; if (count >= 1) { if (x == Gx && y == Gy && z == Gz) DiagBreak() ; val = MRIgetVoxVal(mri_wm, x, y, z, 0) ; MRIsetVoxVal(mri_wm, x, y, z, 0, val/count) ; val = MRIgetVoxVal(mri_subcort_gm, x, y, z, 0) ; MRIsetVoxVal(mri_subcort_gm, x, y, z, 0, val/count) ; val = MRIgetVoxVal(mri_cortex, x, y, z, 0) ; MRIsetVoxVal(mri_cortex, x, y, z, 0, val/count) ; val = MRIgetVoxVal(mri_csf, x, y, z, 0) ; MRIsetVoxVal(mri_csf, x, y, z, 0, val/count) ; } else // sample in other direction { V3_X(v1) = x ; V3_Y(v1) = y ; V3_Z(v1) = z ; MatrixMultiply(m_inv, v1, v2) ; MatrixMultiply(m_inv, v1, v2) ; xs = nint(V3_X(v2)) ; ys = nint(V3_Y(v2)) ; zs = nint(V3_Z(v2)) ; if (xs >= 0 && ys >= 0 && zs >= 0 && xs < mri_seg->width && ys < mri_seg->height && zs < mri_seg->depth) { label = MRIgetVoxVal(mri_seg, xs, ys, zs, 0) ; if (label == csf_val) MRIsetVoxVal(mri_csf, x, y, z, 0, 1) ; else if (label == wm_val) MRIsetVoxVal(mri_wm, x, y, z, 0, 1) ; else if (label == subcort_gm_val) MRIsetVoxVal(mri_subcort_gm, x, y, z, 0, 1) ; else if (cortex_val) MRIsetVoxVal(mri_cortex, x, y, z, 0, 1) ; else DiagBreak() ; } } } VectorFree(&v1) ; VectorFree(&v2) ; MatrixFree(&m_inv) ; MRIfree(&mri_counts) ; return(NO_ERROR) ; }
//====== // 更新 //====== void cPMDIK::update( void ) { Vector3 vec3OrgTargetPos; vec3OrgTargetPos.x = m_pTargetBone->m_matLocal[3][0]; vec3OrgTargetPos.y = m_pTargetBone->m_matLocal[3][1]; vec3OrgTargetPos.z = m_pTargetBone->m_matLocal[3][2]; Vector3 vec3EffPos; Vector3 vec3TargetPos; for( short i = m_cbNumLink - 1 ; i >= 0 ; i-- ){ m_ppBoneList[i]->updateMatrix(); } m_pEffBone->updateMatrix(); for( unsigned short it = 0 ; it < m_unCount ; it++ ) { for( unsigned char cbLinkIdx = 0 ; cbLinkIdx < m_cbNumLink ; cbLinkIdx++ ) { // エフェクタの位置の取得 vec3EffPos.x = m_pEffBone->m_matLocal[3][0]; vec3EffPos.y = m_pEffBone->m_matLocal[3][1]; vec3EffPos.z = m_pEffBone->m_matLocal[3][2]; // ワールド座標系から注目ノードの局所(ローカル)座標系への変換 Matrix matInvBone; MatrixInverse( matInvBone, m_ppBoneList[cbLinkIdx]->m_matLocal ); // エフェクタ,到達目標のローカル位置 Vector3Transform( &vec3EffPos, &vec3EffPos, matInvBone ); Vector3Transform( &vec3TargetPos, &vec3OrgTargetPos, matInvBone ); // 十分近ければ終了 Vector3 vec3Diff; Vector3Sub( &vec3Diff, &vec3EffPos, &vec3TargetPos ); if( Vector3DotProduct( &vec3Diff, &vec3Diff ) < 0.0000001f ) return; // (1) 基準関節→エフェクタ位置への方向ベクトル Vector3Normalize( &vec3EffPos, &vec3EffPos ); // (2) 基準関節→目標位置への方向ベクトル Vector3Normalize( &vec3TargetPos, &vec3TargetPos ); // ベクトル (1) を (2) に一致させるための最短回転量(Axis-Angle) // // 回転角 float fRotAngle = acosf( Vector3DotProduct( &vec3EffPos, &vec3TargetPos ) ); if( 0.00000001f < fabsf( fRotAngle ) ) { if( fRotAngle < -m_fFact ) fRotAngle = -m_fFact; else if( m_fFact < fRotAngle ) fRotAngle = m_fFact; // 回転軸 Vector3 vec3RotAxis; Vector3CrossProduct( &vec3RotAxis, &vec3EffPos, &vec3TargetPos ); if( Vector3DotProduct( &vec3RotAxis, &vec3RotAxis ) < 0.0000001f ) continue; Vector3Normalize( &vec3RotAxis, &vec3RotAxis ); // 関節回転量の補正 Vector4 vec4RotQuat; QuaternionCreateAxis( &vec4RotQuat, &vec3RotAxis, fRotAngle ); if( m_ppBoneList[cbLinkIdx]->m_bIKLimitAngle ) limitAngle( &vec4RotQuat, &vec4RotQuat ); QuaternionNormalize( &vec4RotQuat, &vec4RotQuat ); QuaternionMultiply( &m_ppBoneList[cbLinkIdx]->m_vec4Rotation, &m_ppBoneList[cbLinkIdx]->m_vec4Rotation, &vec4RotQuat ); QuaternionNormalize( &m_ppBoneList[cbLinkIdx]->m_vec4Rotation, &m_ppBoneList[cbLinkIdx]->m_vec4Rotation ); for( short i = cbLinkIdx ; i >= 0 ; i-- ){ m_ppBoneList[i]->updateMatrix(); } m_pEffBone->updateMatrix(); } } } }
int main(int argc, char *argv[]) { char **av; char *fslfn, *ltafn; MRI *mri_src, *mri_tgt; int ac, nargs; LTA *mylta = 0; FILE *fo; VOL_GEOM srcG, dstG; MATRIX *invTgt, *Dsrc, *V_to_V; Progname = argv[0]; nargs = handle_version_option (argc, argv, "$Id: mri_fslmat_to_lta.c,v 1.3 2011/03/02 00:04:15 nicks Exp $", "$Name: $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc != 5) usage(1); printf("Read source volume file %s\n", argv[1]); mri_src = MRIread(argv[1]) ; if (!mri_src) ErrorExit(ERROR_BADPARM, "%s: could not read source volume %s", Progname, argv[1]) ; printf("Read destination volume file %s\n", argv[2]); mri_tgt = MRIread(argv[2]) ; if (!mri_tgt) ErrorExit(ERROR_BADPARM, "%s: could not read label volume %s", Progname, argv[2]) ; fslfn = argv[3]; ltafn = argv[4]; printf("Read fsl transformation from file %s\n", fslfn); mylta = ltaFSLread(fslfn); getVolGeom(mri_src, &srcG); getVolGeom(mri_tgt, &dstG); if (invert_flag) { mylta->xforms[0].src = dstG; mylta->xforms[0].dst = srcG; } else { mylta->xforms[0].src = srcG; mylta->xforms[0].dst = dstG; } invTgt = MatrixAlloc(4,4,MATRIX_REAL); invTgt->rptr[1][1] = 1.0/dstG.xsize; invTgt->rptr[2][2] = 1.0/dstG.ysize; invTgt->rptr[3][3] = 1.0/dstG.zsize; invTgt->rptr[4][4] = 1.0; Dsrc = MatrixAlloc(4,4,MATRIX_REAL); Dsrc->rptr[1][1] = srcG.xsize; Dsrc->rptr[2][2] = srcG.ysize; Dsrc->rptr[3][3] = srcG.zsize; Dsrc->rptr[4][4] = 1.0; V_to_V = MatrixMultiply(invTgt, mylta->xforms[0].m_L, NULL); V_to_V = MatrixMultiply(V_to_V, Dsrc, V_to_V); if (invert_flag) { mylta->xforms[0].m_L = MatrixInverse(V_to_V, mylta->xforms[0].m_L); } else { mylta->xforms[0].m_L = MatrixCopy(V_to_V, mylta->xforms[0].m_L); } if (!mylta) { MRIfree(&mri_src); MRIfree(&mri_tgt); ErrorExit(ERROR_BADFILE, "%s: can't read in transformation",Progname); } printf("Write transformation to lta file %s\n", ltafn); fo = fopen(ltafn,"w"); if (fo==NULL) ErrorExit(ERROR_BADFILE, "%s: can't create file %s",Progname, ltafn); LTAprint(fo, mylta); fclose(fo); MRIfree(&mri_src); MRIfree(&mri_tgt); LTAfree(&mylta); MatrixFree(&invTgt); MatrixFree(&Dsrc); MatrixFree(&V_to_V); return(0); } /* end main() */
void CEditRenderPipeline::SetRenderStyle( const STATIC_RS& RenderStyle ) { //m_pipeline->SetRenderStyle(RenderStyle); //return ; m_GraphicRenderStyle.m_Material = RenderStyle.m_Material; CRenderPipeline::GetInst()->SetShader(RenderStyle.m_ShaderType); _SetMaterial( m_GraphicRenderStyle.m_Material ); _SetRenderStyle ( RS_ALPHAREF, RenderStyle.m_Alpharef ); if (m_GraphicRenderStyle.m_Texturefactor!=RenderStyle.m_Texturefactor || bReFreshTexFactor) { m_GraphicRenderStyle.m_Texturefactor = RenderStyle.m_Texturefactor; _SetRenderStyle ( RS_TEXTUREFACTOR, m_GraphicRenderStyle.m_Texturefactor ); CColor4 factor = m_GraphicRenderStyle.m_Texturefactor; SetFragmentShaderF(ACT_TEXTURE_FACTOR, factor.r, factor.g, factor.b, factor.a); bReFreshTexFactor = false; } float Params[4]; Params[0] = (float)RenderStyle.m_Alpharef; Params[1] = (float)RenderStyle.m_Material.Diffuse.a; Params[2] = (float)RenderStyle.m_Material.Specular.a; SetVertexShaderF(ACT_TEXTURE_FACTOR,Params,1); CColor4 tSpecular(0.0f,0.0f,0.0f,0.0f); if (RenderStyle.m_SpecularEnable) { tSpecular = m_GraphicRenderStyle.m_Material.Specular; tSpecular.a = m_GraphicRenderStyle.m_Material.Power; } SetVertexShaderF(ACT_MAT_DIFFUSE_COLOR , (float*)&m_GraphicRenderStyle.m_Material.Diffuse, 1); SetVertexShaderF(ACT_MAT_AMBIENT_COLOR , (float*)&m_GraphicRenderStyle.m_Material.Ambient, 1); SetVertexShaderF(ACT_MAT_SPECULAR_COLOR , (float*)&tSpecular, 1); SetVertexShaderF(ACT_MAT_EMISSIVE_COLOR , (float*)&m_GraphicRenderStyle.m_Material.Emissive, 1); SetVertexShaderF(ACT_REFRACT_SCALAR , RenderStyle.m_fRefractIndex); SetVertexShaderF(ACT_UV_INDEX , float(RenderStyle.m_Uv_S0) , float(RenderStyle.m_Uv_S1) , float(RenderStyle.m_Uv_S2) ); //_SetRenderStyle ( RS_SLOPESCALEDEPTHBIAS, *(DWORD*)&(RenderStyle.m_fSlopeScaleZBias)); _SetRenderStyle ( RS_DEPTHBIAS, *(DWORD*)&(RenderStyle.m_fZBias)); _SetRenderStyle ( RS_ALPHABLENDENABLE, RenderStyle.m_AlphaBlendEnable ); _SetRenderStyle ( RS_SRCBLEND, RenderStyle.m_SrcBlend ); _SetRenderStyle ( RS_DESTBLEND, RenderStyle.m_DestBlend ); _SetRenderStyle ( RS_ALPHATESTENABLE, RenderStyle.m_AlphaTestEnable ); _SetRenderStyle ( RS_ALPHAFUNC, RenderStyle.m_AlphaTestFun ); _SetRenderStyle ( RS_LIGHTING, RenderStyle.m_LightEnable ); _SetRenderStyle ( RS_SPECULARENABLE, RenderStyle.m_SpecularEnable ); _SetRenderStyle ( RS_ZENABLE, RenderStyle.m_ZTestEnable ); _SetRenderStyle ( RS_ZFUNC, RenderStyle.m_ZTestFun ); _SetRenderStyle ( RS_ZWRITEENABLE, RenderStyle.m_ZWrite ); _SetRenderStyle ( RS_CULLMODE, RenderStyle.m_Cull ); _SetRenderStyle ( RS_FILLMODE, RenderStyle.m_FillMode ); bool isClipPlaneValid = RenderStyle.m_ClipPlane.IsValid(); if (isClipPlaneValid) { CPlane plane = RenderStyle.m_ClipPlane; if (RenderStyle.m_ShaderType.GetVSShaderID()) { // transform to clipping space CMatrix transform = m_CurViewProj; MatrixInverse(transform); transform.Transpose(); plane.Transform(transform); } _SetClipPlane(0, plane); } _SetRenderStyle( RS_CLIPPLANEENABLE, DWORD(isClipPlaneValid ? CLIPPLANE0 : 0) ); SetTextureEx(RenderStyle); }
int main(int argc, char *argv[]) { char **av; MRI *mri_src, *mri_mask, *mri_dst ; int nargs, ac, nmask; int x, y, z; float value; MRI_REGION *region; LTA *lta = 0; int transform_type; MRI *mri_tmp; nargs = handle_version_option ( argc, argv, "$Id: mri_mask.c,v 1.18 2012/12/07 22:45:50 greve Exp $", "$Name: $" ); if (nargs && argc - nargs == 1) { exit (0); } argc -= nargs ; Progname = argv[0]; ErrorInit(NULL, NULL, NULL) ; DiagInit(NULL, NULL, NULL) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc != 4) { printf("Incorrect number of arguments, argc = %d\n", argc); usage(1); } mri_src = MRIread(argv[1]) ; if (!mri_src) ErrorExit(ERROR_BADPARM, "%s: could not read source volume %s", Progname, argv[1]) ; mri_mask = MRIread(argv[2]) ; if (!mri_mask) ErrorExit(ERROR_BADPARM, "%s: could not read mask volume %s", Progname, argv[2]) ; if(mri_src->width != mri_mask->width) { printf("ERROR: dimension mismatch between source and mask\n"); exit(1); } printf("DoAbs = %d\n",DoAbs); /* Read LTA transform and apply it to mri_mask */ if (xform_fname != NULL) { printf("Apply the given LTA xfrom to the mask volume\n"); // read transform transform_type = TransformFileNameType(xform_fname); if (transform_type == MNI_TRANSFORM_TYPE || transform_type == TRANSFORM_ARRAY_TYPE || transform_type == REGISTER_DAT || transform_type == FSLREG_TYPE ) { printf("Reading transform ...\n"); lta = LTAreadEx(xform_fname) ; if (!lta) ErrorExit(ERROR_NOFILE, "%s: could not read transform file %s", Progname, xform_fname) ; if (transform_type == FSLREG_TYPE) { if (lta_src == 0 || lta_dst == 0) { fprintf(stderr, "ERROR: fslmat does not have information on " "the src and dst volumes\n"); fprintf(stderr, "ERROR: you must give options '-lta_src' " "and '-lta_dst' to specify the src and dst volume infos\n"); } LTAmodifySrcDstGeom(lta, lta_src, lta_dst); // add src and dst information LTAchangeType(lta, LINEAR_VOX_TO_VOX); } if (lta->xforms[0].src.valid == 0) { if (lta_src == 0) { fprintf(stderr, "The transform does not have the valid src volume info.\n"); fprintf(stderr, "Either you give src volume info by option -lta_src or\n"); fprintf(stderr, "make the transform to have the valid src info.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, lta_src, NULL); // add src information // getVolGeom(lta_src, <->src); } } if (lta->xforms[0].dst.valid == 0) { if (lta_dst == 0) { fprintf(stderr, "The transform does not have the valid dst volume info.\n"); fprintf(stderr, "Either you give src volume info by option -lta_dst or\n"); fprintf(stderr, "make the transform to have the valid dst info.\n"); fprintf(stderr, "If the dst was average_305, then you can set\n"); fprintf(stderr, "environmental variable USE_AVERAGE305 true\n"); fprintf(stderr, "without giving the dst volume for RAS-to-RAS transform.\n"); ErrorExit(ERROR_BAD_PARM, "Bailing out...\n"); } else { LTAmodifySrcDstGeom(lta, NULL, lta_dst); // add dst information } } } else { ErrorExit(ERROR_BADPARM, "transform is not of MNI, nor Register.dat, nor FSLMAT type"); } if (invert) { VOL_GEOM vgtmp; LT *lt; MATRIX *m_tmp = lta->xforms[0].m_L ; lta->xforms[0].m_L = MatrixInverse(lta->xforms[0].m_L, NULL) ; MatrixFree(&m_tmp) ; lt = <a->xforms[0]; if (lt->dst.valid == 0 || lt->src.valid == 0) { fprintf(stderr, "WARNING:**************************************" "*************************\n"); fprintf(stderr, "WARNING:dst volume information is invalid. " "Most likely produced wrong inverse.\n"); fprintf(stderr, "WARNING:**************************************" "*************************\n"); } copyVolGeom(<->dst, &vgtmp); copyVolGeom(<->src, <->dst); copyVolGeom(&vgtmp, <->src); } // LTAchangeType(lta, LINEAR_VOX_TO_VOX); mri_tmp = MRIalloc(mri_src->width, mri_src->height, mri_src->depth, mri_mask->type) ; MRIcopyHeader(mri_src, mri_tmp) ; mri_tmp = LTAtransformInterp(mri_mask, mri_tmp, lta, InterpMethod); // mri_tmp = //MRIlinearTransformInterp // ( // mri_mask, mri_tmp, lta->xforms[0].m_L, InterpMethod // ); MRIfree(&mri_mask); mri_mask = mri_tmp; if (lta_src) { MRIfree(<a_src); } if (lta_dst) { MRIfree(<a_dst); } if (lta) { LTAfree(<a); } } /* if (xform_fname != NULL) */ // Threshold mask nmask = 0; for (z = 0 ; z <mri_mask->depth ; z++) { for (y = 0 ; y < mri_mask->height ; y++) { for (x = 0 ; x < mri_mask->width ; x++) { value = MRIgetVoxVal(mri_mask, x, y, z, 0); if(DoAbs) { value = fabs(value); } if(value <= threshold) { MRIsetVoxVal(mri_mask,x,y,z,0,0); } else { nmask ++; } } } } printf("Found %d voxels in mask (pct=%6.2f)\n",nmask, 100.0*nmask/(mri_mask->width*mri_mask->height*mri_mask->depth)); if(DoBB){ printf("Computing bounding box, npad = %d\n",nPadBB); region = REGIONgetBoundingBox(mri_mask,nPadBB); REGIONprint(stdout, region); mri_tmp = MRIextractRegion(mri_mask, NULL, region); if(mri_tmp == NULL) exit(1); MRIfree(&mri_mask); mri_mask = mri_tmp; mri_tmp = MRIextractRegion(mri_src, NULL, region); if(mri_tmp == NULL) exit(1); MRIfree(&mri_src); mri_src = mri_tmp; } int mask=0; float out_val=0; if (do_transfer) { mask = (int)transfer_val; out_val = transfer_val; } mri_dst = MRImask(mri_src, mri_mask, NULL, mask, out_val) ; if (!mri_dst) { ErrorExit(Gerror, "%s: stripping failed", Progname) ; } if (keep_mask_deletion_edits) { mri_dst = MRImask(mri_dst, mri_mask, NULL, 1, 1) ; // keep voxels = 1 if (!mri_dst) ErrorExit(Gerror, "%s: stripping failed on keep_mask_deletion_edits", Progname) ; } printf("Writing masked volume to %s...", argv[3]) ; MRIwrite(mri_dst, argv[3]); printf("done.\n") ; MRIfree(&mri_src); MRIfree(&mri_mask); MRIfree(&mri_dst); exit(0); } /* end main() */
int main(int argc, char *argv[]) { char *ref_fname, *in_fname, *out_fname, fname[STRLEN], **av ; MRI *mri_ref, *mri_in, *mri_orig, *mri_in_red, *mri_ref_red, *mri_in_tmp, *mri_ref_tmp, *mri_ref_orig, *mri_in_orig ; int ac, nargs, i, msec, minutes, seconds ; struct timeb start ; MATRIX *m_L ; /* rkt: check for and handle version tag */ nargs = handle_version_option (argc, argv, "$Id: mri_linear_register.c,v 1.13 2011/03/02 00:04:22 nicks Exp $", "$Name: stable5 $"); if (nargs && argc - nargs == 1) exit (0); argc -= nargs; parms.mri_crop = NULL ; parms.l_intensity = 1.0f ; parms.niterations = 100 ; parms.levels = -1 ; /* use default */ parms.dt = 1e-6 ; /* was 5e-6 */ parms.tol = INTEGRATION_TOL*5 ; parms.dt = 5e-6 ; /* was 5e-6 */ parms.tol = 1e-3 ; parms.momentum = 0.8 ; parms.max_levels = MAX_LEVELS ; parms.factor = 1.0 ; parms.niterations = 25 ; Progname = argv[0] ; DiagInit(NULL, NULL, NULL) ; ErrorInit(NULL, NULL, NULL) ; ac = argc ; av = argv ; for ( ; argc > 1 && ISOPTION(*argv[1]) ; argc--, argv++) { nargs = get_option(argc, argv) ; argc -= nargs ; argv += nargs ; } if (argc < 4) ErrorExit(ERROR_BADPARM, "usage: %s <in brain> <template> <output file name>\n", Progname) ; in_fname = argv[1] ; ref_fname = argv[2] ; if (xform_mean_fname) { int sno, nsubjects ; FILE *fp ; parms.m_xform_mean = MatrixAsciiRead(xform_mean_fname, NULL) ; if (!parms.m_xform_mean) ErrorExit(Gerror, "%s: could not read parameter means from %s", Progname, xform_mean_fname) ; fp = fopen(xform_covariance_fname, "r") ; if (!fp) ErrorExit(ERROR_NOFILE, "%s: could not read covariances from %s", Progname, xform_covariance_fname) ; fscanf(fp, "nsubjects=%d", &nsubjects) ; printf("reading %d transforms...\n", nsubjects) ; parms.m_xforms = (MATRIX **)calloc(nsubjects, sizeof(MATRIX *)) ; if (!parms.m_xforms) ErrorExit(ERROR_NOMEMORY, "%s: could not allocate array of %d xforms", Progname, nsubjects) ; for (sno = 0 ; sno < nsubjects ; sno++) { parms.m_xforms[sno] = MatrixAsciiReadFrom(fp, NULL) ; if (!parms.m_xforms[sno]) ErrorExit(ERROR_NOMEMORY, "%s: could not allocate %dth xform", Progname, sno) ; } parms.m_xform_covariance = MatrixAsciiReadFrom(fp, NULL) ; if (!parms.m_xform_covariance) ErrorExit(Gerror, "%s: could not read parameter covariance from %s", Progname, xform_covariance_fname) ; fclose(fp) ; parms.l_priors = l_priors ; parms.nxforms = nsubjects ; } out_fname = argv[3] ; FileNameOnly(out_fname, fname) ; FileNameRemoveExtension(fname, fname) ; strcpy(parms.base_name, fname) ; fprintf(stderr, "logging results to %s.log\n", parms.base_name) ; TimerStart(&start) ; fprintf(stderr, "reading '%s'...\n", ref_fname) ; fflush(stderr) ; mri_ref = MRIread(ref_fname) ; if (!mri_ref) ErrorExit(ERROR_NOFILE, "%s: could not open reference volume %s.\n", Progname, ref_fname) ; if (mri_ref->type != MRI_UCHAR) { MRI *mri_tmp ; mri_tmp = MRIchangeType(mri_ref, MRI_UCHAR, 0.0, 0.999, FALSE) ; MRIfree(&mri_ref) ; mri_ref = mri_tmp ; } if (var_fname) /* read in a volume of standard deviations */ { MRI *mri_var, *mri_tmp ; fprintf(stderr, "reading '%s'...\n", var_fname) ; mri_var = MRIread(var_fname) ; if (!mri_var) ErrorExit(ERROR_NOFILE, "%s: could not open variance volume %s.\n", Progname, var_fname) ; mri_tmp = MRIconcatenateFrames(mri_ref, mri_var, NULL) ; MRIfree(&mri_var) ; MRIfree(&mri_ref) ; mri_ref = mri_tmp ; } fprintf(stderr, "reading '%s'...\n", in_fname) ; fflush(stderr) ; mri_orig = mri_in = MRIread(in_fname) ; if (!mri_in) ErrorExit(ERROR_NOFILE, "%s: could not open input volume %s.\n", Progname, in_fname) ; if (mri_in->type != MRI_UCHAR) { MRI *mri_tmp ; mri_orig = mri_tmp = MRIchangeType(mri_in, MRI_UCHAR, 0.0, 0.999, FALSE) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } /* make sure they are the same size */ if (mri_in->width != mri_ref->width || mri_in->height != mri_ref->height || mri_in->depth != mri_ref->depth) { int width, height, depth ; MRI *mri_tmp ; width = MAX(mri_in->width, mri_ref->width) ; height = MAX(mri_in->height, mri_ref->height) ; depth = MAX(mri_in->depth, mri_ref->depth) ; mri_tmp = MRIalloc(width, height, depth, MRI_UCHAR) ; MRIextractInto(mri_in, mri_tmp, 0, 0, 0, mri_in->width, mri_in->height, mri_in->depth, 0, 0, 0) ; #if 0 MRIfree(&mri_in) ; #else parms.mri_in = mri_in ; #endif mri_in = mri_orig = mri_tmp ; mri_tmp = MRIallocSequence(width, height,depth,MRI_UCHAR,mri_ref->nframes); MRIextractInto(mri_ref, mri_tmp, 0, 0, 0, mri_ref->width, mri_ref->height, mri_ref->depth, 0, 0, 0) ; #if 0 MRIfree(&mri_ref) ; #else parms.mri_in = mri_in ; #endif mri_ref = mri_tmp ; } if (!FZERO(tx) || !FZERO(ty) || !FZERO(tz)) { MRI *mri_tmp ; fprintf(stderr, "translating second volume by (%2.1f, %2.1f, %2.1f)\n", tx, ty, tz) ; mri_tmp = MRItranslate(mri_in, NULL, tx, ty, tz) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } if (!FZERO(rzrot)) { MRI *mri_tmp ; fprintf(stderr, "rotating second volume by %2.1f degrees around Z axis\n", (float)DEGREES(rzrot)) ; mri_tmp = MRIrotateZ_I(mri_in, NULL, rzrot) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } if (!FZERO(rxrot)) { MRI *mri_tmp ; fprintf(stderr, "rotating second volume by %2.1f degrees around X axis\n", (float)DEGREES(rxrot)) ; mri_tmp = MRIrotateX_I(mri_in, NULL, rxrot) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } if (!FZERO(ryrot)) { MRI *mri_tmp ; fprintf(stderr, "rotating second volume by %2.1f degrees around Y axis\n", (float)DEGREES(ryrot)) ; mri_tmp = MRIrotateY_I(mri_in, NULL, ryrot) ; MRIfree(&mri_in) ; mri_in = mri_tmp ; } if (!transform_loaded) /* wasn't preloaded */ parms.lta = LTAalloc(1, mri_in) ; if (!FZERO(blur_sigma)) { MRI *mri_kernel, *mri_tmp ; mri_kernel = MRIgaussian1d(blur_sigma, 100) ; mri_tmp = MRIconvolveGaussian(mri_in, NULL, mri_kernel) ; mri_in = mri_tmp ; MRIfree(&mri_kernel) ; } MRIscaleMeanIntensities(mri_in, mri_ref, mri_in); mri_ref_orig = mri_ref ; mri_in_orig = mri_in ; if (nreductions > 0) { mri_in_red = mri_in_tmp = MRIcopy(mri_in, NULL) ; mri_ref_red = mri_ref_tmp = MRIcopy(mri_ref, NULL) ; for (i = 0 ; i < nreductions ; i++) { mri_in_red = MRIreduceByte(mri_in_tmp, NULL) ; mri_ref_red = MRIreduceMeanAndStdByte(mri_ref_tmp,NULL); MRIfree(&mri_in_tmp); MRIfree(&mri_ref_tmp) ; mri_in_tmp = mri_in_red ; mri_ref_tmp = mri_ref_red ; } mri_in = mri_in_red ; mri_ref = mri_ref_red ; } /* for diagnostics */ if (full_res) { parms.mri_ref = mri_ref ; parms.mri_in = mri_in ; } else { parms.mri_ref = mri_ref_orig ; parms.mri_in = mri_in_orig ; } m_L = initialize_transform(mri_in, mri_ref, &parms) ; if (use_gradient) { MRI *mri_in_mag, *mri_ref_mag, *mri_grad, *mri_mag ; printf("computing gradient magnitude of input image...\n") ; mri_mag = MRIalloc(mri_in->width, mri_in->height, mri_in->depth,MRI_FLOAT); MRIcopyHeader(mri_in, mri_mag) ; mri_grad = MRIsobel(mri_in, NULL, mri_mag) ; MRIfree(&mri_grad) ; /* convert it to ubytes */ MRIvalScale(mri_mag, mri_mag, 0.0f, 255.0f) ; mri_in_mag = MRIclone(mri_in, NULL) ; MRIcopy(mri_mag, mri_in_mag) ; MRIfree(&mri_mag) ; /* now compute gradient of ref image */ printf("computing gradient magnitude of reference image...\n") ; mri_mag = MRIalloc(mri_ref->width, mri_ref->height, mri_ref->depth,MRI_FLOAT); MRIcopyHeader(mri_ref, mri_mag) ; mri_grad = MRIsobel(mri_ref, NULL, mri_mag) ; MRIfree(&mri_grad) ; /* convert it to ubytes */ MRIvalScale(mri_mag, mri_mag, 0.0f, 255.0f) ; mri_ref_mag = MRIclone(mri_ref, NULL) ; MRIcopy(mri_mag, mri_ref_mag) ; MRIfree(&mri_mag) ; register_mri(mri_in_mag, mri_ref_mag, &parms, m_L) ; MRIfree(&mri_in_mag) ; MRIfree(&mri_ref_mag) ; } register_mri(mri_in, mri_ref, &parms, m_L) ; if (check_crop_flag) /* not working yet! */ { printf("searching for cropped regions in the input image...\n") ; parms.mri_crop = find_cropping(mri_orig, mri_ref, &parms) ; MRIwrite(parms.mri_crop, "crop.mgh") ; register_mri(mri_in, mri_ref, &parms, m_L) ; } if (voxel_coords) { printf("transforming xform to voxel coordinates...\n") ; MRIrasXformToVoxelXform(mri_in_orig, mri_ref_orig, parms.lta->xforms[0].m_L, parms.lta->xforms[0].m_L); if (Gdiag & DIAG_WRITE) { MRI *mri_tmp ; mri_tmp = MRIlinearTransform(mri_in_orig, NULL,parms.lta->xforms[0].m_L); MRIwriteImageViews(mri_tmp, "morphed", IMAGE_SIZE) ; MRIfree(&mri_tmp) ; } } // save src and target info in lta getVolGeom(mri_in_orig, &parms.lta->xforms[0].src); getVolGeom(mri_ref_orig, &parms.lta->xforms[0].dst); fprintf(stderr, "writing output transformation to %s...\n", out_fname) ; if (invert_flag) { MATRIX *m_tmp ; m_tmp = MatrixInverse(parms.lta->xforms[0].m_L, NULL) ; MatrixFree(&parms.lta->xforms[0].m_L) ; // change src and dst getVolGeom(mri_in_orig, &parms.lta->xforms[0].dst); getVolGeom(mri_ref_orig, &parms.lta->xforms[0].src); parms.lta->xforms[0].m_L = m_tmp ; } // LTAwriteEx(parms.lta, out_fname) ; // if (mri_ref) MRIfree(&mri_ref) ; if (mri_in) MRIfree(&mri_in) ; msec = TimerStop(&start) ; seconds = nint((float)msec/1000.0f) ; minutes = seconds / 60 ; seconds = seconds % 60 ; fprintf(stderr, "registration took %d minutes and %d seconds.\n", minutes, seconds) ; exit(0) ; return(0) ; }