void CMeshSlantBrickDialog::onApply(void) { //Delete old object m_pGLPreviewWin->releaseObject(); //Create a new brick object const int nx = this->m_nx; const int ny = this->m_ny; const int nz = this->m_nz; Vector3d* pVertex; Vector4i* pQuad; Vector8i* pHex; int nVertexCount, nPolygonCount, nHexCount; //doMeshBrick(lowleft, upright, nx, ny, nz, pVertex, pQuad, pHex, nVertexCount, nPolygonCount, nHexCount); meshSlantBrickVertices(m_vVertex, nx+1, ny+1, nz+1, pVertex, nVertexCount); getBrickElements(nx, ny, nz, pHex, nHexCount); getBrickBounday(nx, ny, nz, pQuad, nPolygonCount); CHexObj *p = new CHexObj(pVertex, nVertexCount, pHex, nHexCount, pQuad, nPolygonCount); if (p==NULL) return; Vector3d lowleft(+1e30f); Vector3d upright(-1e30f); for (int i=0; i<8; i++){ const Vector3d vvv(m_vVertex[i].x, m_vVertex[i].y, m_vVertex[i].z); Minimize(lowleft, vvv); Maximize(upright, vvv); } p->SetBoundingBox(AxisAlignedBox(lowleft, upright)); char namebuff[256]; sprintf(namebuff, "Brick%d", 0); p->SetObjectName(namebuff); //Set the new object for the preview window m_pGLPreviewWin->setObject(p); m_pGLPreviewWin->updateGL(); }
void Microphone::Triangulate() { vertices.clear(); edges.clear(); polygons.clear(); ExCone base(bH, bR, bR, bR * 0.824f, precision); Pyramid buttonL(bH * 0.6f, bW * 0.575f, bW, bW * 0.3f, bW, -bW * 0.1375f), buttonR(bH * 0.6f, bW * 0.575f, bW, bW * 0.3f, bW, -bW * 0.1375f); Cone shroudLow(uH * 0.21127f, uR, uR, precision), bridge (uH * 0.084537f, uR * 0.66667f, uR * 0.41667f, precision), shroudHi (uH - uG - shroudLow.getHeight() - uH * .04f - bridge.getHeight(), uR, uR, precision), upright (uH - bridge.getHeight(), uR * 0.66667f, uR * 0.66667f, precision); Pyramid handleBridgeUp (uH * 0.09155f, uR * 0.653f, hI, uR * 0.653f, hI), handleBridgeDown(uH * 0.077f, uR * 0.653f, hI, uR * 0.653f, hI), handle (uH * 0.7598f, uR * 0.792f, uR * 0.5418f, uR * 0.5418f, uR * 0.5418f, uR * 0.125f), handleTop (uH * 0.05647f, uR * 0.792f, uR * 0.5418f, uR * 0.792f, uR * 0.5418f,-uR * 0.3542f); Hole head (hD, hR, cR, hR, cR, precision), headFront(hD / 10.f, hR * 1.075f, cR * 0.9f, hR * 1.075f, cR * 0.9f, precision), headBack (hD / 10.f, hR * 1.075f, cR * 0.9f, hR * 1.075f, cR * 0.9f, precision); Cone core (hD * 1.43333f, cR, cR, precision); base.Yaw(-(FLOAT)M_PI_2); base.Transform(); buttonL.Translate(-bR * 0.2588f, bR * 0.824f, bH * 1.1f); buttonL.Pitch((FLOAT)M_PI); buttonL.Transform(); buttonR.Translate(bR * 0.2588f, bR * 0.824f, bH * 1.1f); buttonR.Pitch((FLOAT)M_PI); buttonR.Transform(); upright.Fly(bH); upright.Transform(); shroudLow.Fly(base.getHeight() + uH * .04f); shroudLow.Transform(); shroudHi.Fly(shroudLow.getPosition().z + shroudLow.getHeight() + uG); shroudHi.Transform(); bridge.Fly(shroudHi.getPosition().z + shroudHi.getHeight()); bridge.Transform(); handleBridgeUp.Fly(uH * 0.8f); handleBridgeUp.Follow(uR + hI / 2); handleBridgeUp.Transform(); handleBridgeDown.Fly(bH + uH * 0.15f); handleBridgeDown.Follow(handleBridgeUp.getPosition().x); handleBridgeDown.Transform(); handle.Translate(uR * 1.5f + hI, bR * 0.0059f, uH * .95f); handle.Pitch((FLOAT)M_PI); handle.Yaw((FLOAT)M_PI_2); handle.Transform(); handleTop.Translate(handle.getPosition().x, handle.getPosition().y, handle.getPosition().z); handleTop.Yaw((FLOAT)M_PI_2); handleTop.Transform(); head.Fly(bridge.getPosition().z + bridge.getHeight() + hR); head.Strafe(-hD/2); head.Pitch((FLOAT)M_PI_2); head.Roll((FLOAT)M_PI_2); head.Transform(); headFront.Fly(head.getPosition().z); headFront.Strafe(-head.getPosition().y); headFront.Pitch((FLOAT)M_PI_2); headFront.Roll((FLOAT)M_PI_2); headFront.Transform(); headBack.Translate(head.getPosition()); headBack.Pitch((FLOAT)M_PI_2); headBack.Roll((FLOAT)M_PI_2); headBack.Transform(); core.Fly(head.getPosition().z); core.Strafe(-core.getHeight() / 2.1f); core.Pitch((FLOAT)M_PI_2); core.Roll((FLOAT)M_PI_2); core.Transform(); addMesh(MIC_BASE, base); addMesh(MIC_BUTTON_L, buttonL); addMesh(MIC_BUTTON_R, buttonR); addMesh(MIC_UPRIGHT, upright); addMesh(MIC_SHROUD_LOW, shroudLow); addMesh(MIC_SHROUD_HI, shroudHi); addMesh(MIC_BRIDGE, bridge); addMesh(MIC_HANDLE_BU, handleBridgeUp); addMesh(MIC_HANDLE_BD, handleBridgeDown); addMesh(MIC_HANDLE, handle); addMesh(MIC_HANDLE_TOP, handleTop); addMesh(MIC_HEAD, head); addMesh(MIC_HEAD_FRONT, headFront); addMesh(MIC_HEAD_BACK, headBack); addMesh(MIC_CORE, core); Transform(); vertices.shrink_to_fit(); edges.shrink_to_fit(); polygons.shrink_to_fit(); // flipNormals(0, polygons.size()); }
static int addpoints(lulog *log, luary_ijz *ijz, size_t *current, ludta_ijz *pprev, int nextisup, size_t *index, ludta_ij bl, ludta_ij tr, luary_uint32 *indices, luary_uint32 *counts) { int status = LU_OK; do { size_t next = index[ij2index((nextisup ? upright : downright)(*pprev), bl, tr)]; ludta_ijz *pnext = next ? &ijz->ijz[next-1] : NULL; if (pnext) { if (!nextisup) { // we're walking geometrically (in i,j space) across the // points, but we need to keep the traversal of ijz (via // the current index) in step so we can restart correctly // for the next strip. this is only possible if the points // are sorted (which enumerate should guarantee). assert(ijeq(right(ijz->ijz[*current]), ijz2ij(ijz->ijz[*current+1])), LU_ERR, log, "Unsorted points? Current at (%d,%d), next at (%d,%d), prev at (%d,%d), downright at (%d,%d)", ijz->ijz[*current].i, ijz->ijz[*current].j, ijz->ijz[*current+1].i, ijz->ijz[*current+1].j, pprev->i, pprev->j, pnext->i, pnext->j) *current = *current + 1; } try(luary_uint32_push(log, indices, next-1)); // correct for 0/NULL counts->i[counts->mem.used-1]++; pprev = pnext; nextisup = !nextisup; } else { *current = *current + 1; goto finally; } } while (*current < ijz->mem.used); finally: return status; } static int addstrip(lulog *log, luary_ijz *ijz, size_t *current, size_t *index, ludta_ij bl, ludta_ij tr, luary_uint32 *indices, luary_uint32 *offsets, luary_uint32 *counts) { int status = LU_OK; ludta_ijz *p1 = &ijz->ijz[*current]; size_t i0 = index[ij2index(upleft(*p1), bl, tr)]; ludta_ijz *p0 = i0 ? &ijz->ijz[i0-1] : NULL; size_t i2 = index[ij2index(upright(*p1), bl, tr)]; ludta_ijz *p2 = i2 ? &ijz->ijz[i2-1] : NULL; // if at least three points exist, add the first two and then add the rest if (p0 && p2) { // here the initial triangle looks like \/ and (l-r) is CCW. // if we want CW front face then we need to add an extra point // at the start (a degenerate triangle). try(luary_uint32_push(log, offsets, indices->mem.used)); try(luary_uint32_push(log, indices, i0-1)); // correct for 0/NULL try(luary_uint32_push(log, indices, i0-1)); // correct for 0/NULL try(luary_uint32_push(log, indices, *current)); try(luary_uint32_push(log, counts, 3)); try(addpoints(log, ijz, current, p1, 1, index, bl, tr, indices, counts)); } else { // here the initial triangle looks like /\ and (l-r) is CW. size_t i3 = index[ij2index(right(*p1), bl, tr)]; ludta_ijz *p3 = i3 ? &ijz->ijz[i3-1] : NULL; if (p3) { assert(*current + 1 < ijz->mem.used, LU_ERR, log, "Unsorted points? No data at %zu", *current + 1); assert(p3 == &ijz->ijz[*current + 1], LU_ERR, log, "Unsorted points? p3=(%d,%d), p1=(%d,%d), next=(%d,%d)", p3->i, p3->j, p1->i, p1->j, ijz->ijz[*current + 1].i, ijz->ijz[*current + 1].j); } if (p2 && p3) { try(luary_uint32_push(log, offsets, indices->mem.used)); try(luary_uint32_push(log, indices, *current)); try(luary_uint32_push(log, indices, i2 - 1)); // correct for 0/NULL try(luary_uint32_push(log, counts, 2)); try(addpoints(log, ijz, current, p2, 0, index, bl, tr, indices, counts)); } else { *current = *current+1; } } finally: return status; } int strips(lulog *log, luary_ijz *ijz, luary_uint32 **indices, luary_uint32 **offsets, luary_uint32 **counts){ int status = LU_OK; ludta_ij bl, tr; size_t *index = NULL; try(lutle_range(log, ijz, &bl, &tr, NULL)); bl.i--; bl.j--; tr.i++; tr.j++; // add border for failed lookups try(index_mk(log, ijz, bl, tr, &index)); try(luary_uint32_mk(log, indices, 4 * ijz->mem.used)); // guess some overhead try(luary_uint32_mk(log, offsets, tr.j - bl.j + 1)); // optimistic? try(luary_uint32_mk(log, counts, tr.j - bl.j + 1)); // optimistic? size_t current = 0; while (current < ijz->mem.used) { try(addstrip(log, ijz, ¤t, index, bl, tr, *indices, *offsets, *counts)); } luinfo(log, "Generated %zu triangle strips", (*offsets)->mem.used); finally: free(index); return status; } int ijz2fxyzw(lulog *log, luary_ijz *ijz, float step, luary_fxyzw **fxyzw) { int status = LU_OK; try(luary_fxyzw_mk(log, fxyzw, ijz->mem.used)); for (size_t i = 0; i < ijz->mem.used; ++i) { ludta_ijz *p = &ijz->ijz[i]; float x = (p->i + p->j * cos(M_PI/3)) * step; float y = p->j * sin(M_PI/3) * step; float z = p->z; try(luary_fxyzw_push(log, *fxyzw, x, y, z, 1.0f)); } finally: return status; } int ijz2vecf4(lulog *log, luary_ijz *ijz, float step, luary_vecf4 **f4) { int status = LU_OK; try(luary_vecf4_mk(log, f4, ijz->mem.used)); float lo[] = {0, 0, ijz->ijz[0].z}, hi[] = {0, 0, ijz->ijz[0].z}; for (size_t i = 0; i < ijz->mem.used; ++i) { ludta_ijz *p = &ijz->ijz[i]; float x = (p->i + p->j * cos(M_PI/3)) * step; hi[0] = max(hi[0], x); lo[0] = min(lo[0], x); float y = p->j * sin(M_PI/3) * step; hi[1] = max(hi[1], y); lo[1] = min(lo[1], y); float z = p->z; hi[2] = max(hi[2], z); lo[2] = min(lo[2], z); try(luary_vecf4_push(log, *f4, x, y, z, 1.0f)); } ludebug(log, "Data cover range %0.2f - %0.2f, %0.2f - %0.2f, %0.2f - %0.2f", lo[0], hi[0], lo[1], hi[1], lo[2], hi[2]); finally: return status; } int offsets2void(lulog *log, luary_uint32 *in, size_t chunk, luary_void **out) { int status = LU_OK; try(luary_void_mk(log, out, in->mem.used)); for (size_t i = 0; i < in->mem.used; ++i) { try(luary_void_push(log, *out, (void*)(chunk * in->i[i]))); } finally:return status; } int normalize_z(lulog *log, luary_ijz *vertices) { int status = LU_OK; float zmax = vertices->ijz[0].z, zmin = zmax; for (size_t i = 0; i < vertices->mem.used; ++i) { zmax = max(zmax, vertices->ijz[i].z); zmin = min(zmin, vertices->ijz[i].z); } if (zmax > zmin) { for (size_t i = 0; i < vertices->mem.used; ++i) { vertices->ijz[i].z = 2 * ((vertices->ijz[i].z - zmin) / (zmax - zmin) - 0.5); } } else { luwarn(log, "Cannot normalize z data: constant values (setting to zero)"); for (size_t i = 0; i < vertices->mem.used; ++i) { vertices->ijz[i].z = 0.0; } } finally:return status; } // this duplicates points so that none are shared between two triangle // strips. this is necessary so that we can have a single normal for // each triangle (with no interpolation). int uniquify(lulog *log, luary_uint32 *indices, luary_uint32 *offsets, luary_uint32 *counts, luary_ijz *vertices) { int status = LU_OK; size_t before = vertices->mem.used; for (size_t i = 0; i < offsets->mem.used; ++i) { size_t large = max(indices->i[offsets->i[i]], indices->i[offsets->i[i]+1]); for (size_t j = 0; j < counts->i[i]; ++j) { size_t k = offsets->i[i] + j; if (indices->i[k] >= large) { ludta_ijz v = vertices->ijz[indices->i[k]]; indices->i[k] = vertices->mem.used; try(luary_ijz_push(log, vertices, v.i, v.j, v.z)); } } } ludebug(log, "Uniquify increased vertex count from %zu to %zu (%.0f%%)", before, vertices->mem.used, 100.0 * (vertices->mem.used - before) / before); finally: return status; } int normals(lulog *log, luary_uint32 *indices, luary_uint32 *offsets, luary_uint32 *counts, luary_vecf4 *vertices, luary_vnorm **vnorms) { int status = LU_OK; try(luary_vnorm_mk(log, vnorms, vertices->mem.used)); for (size_t i = 0; i < offsets->mem.used; ++i) { size_t offset = offsets->i[i]; for (size_t j = 0; j < counts->i[i]; ++j) { size_t k = offset + j; luglv n = {}; luglv *p0 = &vertices->v[indices->i[k]]; if (j > 1) { luglv *p1 = &vertices->v[indices->i[k-1]]; luglv *p2 = &vertices->v[indices->i[k-2]]; luglv e1 = {}, e2 = {}; luglv_sub(p1, p0, &e1); luglv_sub(p2, p1, &e2); luglv_cross(&e1, &e2, &n); luglv_norm_inplace(&n); // alternate windows are reversed in strip if (j % 2) luglv_scale_inplace(-1, &n); n[3] = 0; } assert(k == (*vnorms)->mem.used, HP_ERR, log, "Vertex gap (%zu/%zu)", k, (*vnorms)->mem.used); try(luary_vnorm_push(log, *vnorms, p0, &n)); } } finally: return status; } int uint2int(lulog *log, luary_uint32 *in, luary_int32 **out) { int status = LU_OK; try(luary_int32_mk(log, out, in->mem.used)); for (size_t i = 0; i < in->mem.used; ++i) { try(luary_int32_push(log, *out, in->i[i])); } finally: return status; }