/* Функция инициализации объекта анимации. * АРГУМЕНТЫ: * - указатель на "себя" - сам объект анимации: * vg4UNIT_CTRL *Uni; * - указатель на контекст анимации: * vg4ANIM *Ani; * ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: Нет. */ static VOID VG4_AnimUnitInit( vg4UNIT_CTRL *Uni, vg4ANIM *Ani ) { vg4PRIM pr; Uni->hFnt = CreateFont(30, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, RUSSIAN_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH, "Bookman Old Style"); VG4_RndPrimMatrConvert = MatrMulMatr(MatrMulMatr(MatrScale(0.0024, 0.0024, 0.0024), MatrRotateX(-0)), MatrTranslate(0, 0, 0)); VG4_GeomLoad(&Uni->Helic, "MODELS\\Mi8\\havoc.g3d"); Uni->Helic.ProgId = VG4_ShaderLoad("HELIC"); VG4_RndPrimDefaultColor = ColorSet(1, 0, 0, 1); VG4_PrimCreatePlane(&pr, VecSet(-500, -0.030, 0), VecSet(1000, 0, 0), VecSet(0, 0.059, 0), 2, 2); VG4_GeomAddPrim(&Uni->Axes, &pr); VG4_RndPrimDefaultColor = ColorSet(0, 0, 1, 1); VG4_PrimCreatePlane(&pr, VecSet(0, -0.030, -500), VecSet(0, 0, 1000), VecSet(0, 0.059, 0), 2, 2); VG4_GeomAddPrim(&Uni->Axes, &pr); VG4_RndPrimDefaultColor = ColorSet(0, 1, 0, 1); VG4_PrimCreatePlane(&pr, VecSet(-0.030, -500, 0), VecSet(0, 1000, 0), VecSet(0.059, 0, 0), 2, 2); VG4_GeomAddPrim(&Uni->Axes, &pr); Uni->Axes.ProgId = VG4_ShaderLoad("AXIS"); VG4_RndPrimDefaultColor = ColorSet(0.7, 0.5, 0.3, 1); VG4_PrimCreateSphere(&Uni->Sph, VecSet(0, 0, 0), 1, 8, 15); Uni->Sph.ProgId = Uni->Axes.ProgId; /* начальные параметры вертолета */ Uni->Pos = VecSet(0, 18, 0); Uni->V = 0; Uni->Head = 0; Uni->Omega = 0; Uni->CPos = VecSet(59, 30, 59); } /* End of 'VG4_AnimUnitInit' function */
/* Функция загрузки геометрического объекта. * АРГУМЕНТЫ: * - геометрический объект: * vg4GEOM *G; * - имя файла материалов: * CHAR *FileName; * ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: * (BOOL) TRUE при успехе. */ BOOL VG4_GeomLoad( vg4GEOM *G, CHAR *FileName ) { INT vn = 0, vtn = 0, vnn = 0, fn = 0, pn = 0, size, i, p; FILE *F; /* читаемые данные */ VEC *ReadV, *ReadN; vg4UV *ReadUV; INT (*ReadF)[3]; /* хранение примитивов */ struct { INT First, Last, /* первый и последний номера вершин примитива */ Mtl; /* материал примитива */ } *PrimInfo; memset(G, 0, sizeof(vg4GEOM)); /* разбиваем имя на части и открываем файл */ _splitpath(FileName, ModelDrive, ModelDir, ModelFileName, ModelFileExt); if ((F = fopen(FileName, "rt")) == NULL) return FALSE; /* считаем количества */ while (fgets(Buf, sizeof(Buf), F) != NULL) if (Buf[0] == 'v' && Buf[1] == ' ') vn++; else if (Buf[0] == 'v' && Buf[1] == 't') vtn++; else if (Buf[0] == 'v' && Buf[1] == 'n') vnn++; else if (Buf[0] == 'f' && Buf[1] == ' ') fn += Split() - 3; else if (strncmp(Buf, "usemtl", 6) == 0) pn++; if (pn == 0) pn = 1; /* материалы не использовались */ /* загружаем: * вершины vn * нормали vvn * текстурные координаты vtn * треугольники fn * примитивы pn * дополнительно: * индексы (Vv, Vn, Vt) <- новые номера вершин ? (vn + vt + vnn) * ??? * начальные индексы vn */ /* выделяем память под вспомогательные данные */ size = sizeof(VEC) * vn + /* вершины vn */ sizeof(VEC) * vnn + /* нормали vnn */ sizeof(vg4UV) * vtn + /* текстурные координаты vtn */ sizeof(INT [3]) * fn + /* треугольники fn */ sizeof(PrimInfo[0]) * pn + /* примитивы pn */ sizeof(VertexRefs[0]) * (vn + vtn + vnn) + /* индексы (Vv, Vn, Vt) (vn + vt + vnn) */ sizeof(INT) * vn; /* начальные индексы vn */ if ((ReadV = malloc(size)) == NULL) { fclose(F); return FALSE; } memset(ReadV, 0, size); /* расставляем указатели */ ReadN = ReadV + vn; ReadUV = (vg4UV *)(ReadN + vnn); ReadF = (INT (*)[3])(ReadUV + vtn); VertexRefsStart = (INT *)(ReadF + fn); PrimInfo = (VOID *)(VertexRefsStart + vn); VertexRefs = (VOID *)(PrimInfo + pn); NumOfAllocedVertexRefs = vn + vtn + vnn; NumOfVertexRefs = 0; /* начала списка индексов вершин ==> -1 */ memset(VertexRefsStart, 0xFF, sizeof(INT) * vn); memset(VertexRefs, 0xFF, sizeof(VertexRefs[0]) * NumOfAllocedVertexRefs); /* второй проход - читаем геометрию */ rewind(F); vn = 0; vtn = 0; vnn = 0; fn = 0; pn = 0; PrimInfo[0].First = 0; /* считаем количества */ while (fgets(Buf, sizeof(Buf), F) != NULL) if (Buf[0] == 'v' && Buf[1] == ' ') { FLT x = 0, y = 0, z = 0; sscanf(Buf + 2, "%f%f%f", &x, &y, &z); ReadV[vn++] = VecSet(x, y, z); } else if (Buf[0] == 'v' && Buf[1] == 't') { FLT u = 0, v = 0; sscanf(Buf + 3, "%f%f", &u, &v); ReadUV[vtn++] = VG4_UVSet(u, v); } else if (Buf[0] == 'v' && Buf[1] == 'n') { FLT nx = 0, ny = 0, nz = 0; sscanf(Buf + 3, "%f%f%f", &nx, &ny, &nz); ReadN[vnn++] = VecNormalize(VecSet(nx, ny, nz)); } else if (Buf[0] == 'f' && Buf[1] == ' ') { INT n0[3], n1[3], n[3], r0, r1, r; Split(); SCANF3(Parts[1], n0); r0 = GetVertexNo(n0[0], n0[1], n0[2]); SCANF3(Parts[2], n1); r1 = GetVertexNo(n1[0], n1[1], n1[2]); for (i = 3; i < NumOfParts; i++) { SCANF3(Parts[i], n); r = GetVertexNo(n[0], n[1], n[2]); ReadF[fn][0] = r0; ReadF[fn][1] = r1; ReadF[fn][2] = r; r1 = r; fn++; } } else if (strncmp(Buf, "usemtl", 6) == 0) { Split(); /* запоминаем номер последней грани */ if (pn != 0) PrimInfo[pn - 1].Last = fn - 1; /* ищем материал */ for (i = 0; i < G->NumOfMtls; i++) if (strcmp(Parts[1], G->Mtls[i].Name) == 0) break; if (i == G->NumOfMtls) PrimInfo[pn].Mtl = -1; else PrimInfo[pn].Mtl = i; PrimInfo[pn].First = fn; pn++; } else if (strncmp(Buf, "mtllib ", 7) == 0) { Split(); LoadMaterials(G, Parts[1]); } /* у последнего примитива запоминаем номер последней грани */ if (pn == 0) { PrimInfo[0].Last = fn - 1; PrimInfo[0].Mtl = -1; } else PrimInfo[pn - 1].Last = fn - 1; fclose(F); /* Формируем примитивы из прочитанных данных */ VG4_DefaultColor = ColorSet(1, 1, 1); for (p = 0; p < pn; p++) { INT minv, maxv, j; vg4PRIM prim; minv = maxv = ReadF[PrimInfo[p].First][0]; for (i = PrimInfo[p].First; i <= PrimInfo[p].Last; i++) for (j = 0; j < 3; j++) { if (minv > ReadF[i][j]) minv = ReadF[i][j]; if (maxv < ReadF[i][j]) maxv = ReadF[i][j]; } vn = maxv - minv + 1; fn = PrimInfo[p].Last - PrimInfo[p].First + 1; VG4_PrimCreate(&prim, VG4_PRIM_TRIMESH, vn, fn * 3); /* копируем вершины */ for (i = 0; i < vn; i++) { INT n; prim.V[i].P = ReadV[VertexRefs[minv + i].Nv]; if ((n = VertexRefs[minv + i].Nn) != -1) prim.V[i].N = ReadN[n]; if ((n = VertexRefs[minv + i].Nt) != -1) prim.V[i].T = ReadUV[n]; } /* копируем грани */ for (i = 0; i < fn; i++) for (j = 0; j < 3; j++) prim.I[i * 3 + j] = ReadF[PrimInfo[p].First + i][j] - minv; prim.Mtl = PrimInfo[p].Mtl; VG4_GeomAddPrim(G, &prim); } /* освобождаем память из-под прочитанных данных */ free(ReadV); return TRUE; } /* End of 'VG4_GeomLoad' function */