【WebGL-iTwin.js】实战篇(一):使用itwin.js画一个立方体

代码地址:itwin-test: itwin.js demo

如下图所示,我们需要在iTwin.js中画出一个立方体模型,并给每个面着色:

效果图:

代码:

const { IModelHost, SubCategory, IModelJsFs, Subject, PhysicalPartition, PhysicalModel, DefinitionPartition, DefinitionModel, ModelSelector,
  SpatialCategory, CategorySelector, DisplayStyle3d, SpatialViewDefinition, RenderMaterialElement, StandaloneDb, IModelHostConfiguration, PhysicalObject } = require('@itwin/core-backend');
const { CodeScopeSpec, IModel, ColorDef, Code, ViewFlags, RenderMode, GeometryStreamBuilder } = require('@itwin/core-common');
const { IndexedPolyface, Point3d } = require('@itwin/core-geometry')
const math = require('mathjs')

/**
 * 例子:画一个立方体
 */
async function drawCubeWithColor () {

  //立方体数据
  const data = {
    // 顶点数据
    point: [
      [0.0, 1.0, 0.0], //点A 
      [0.0, 0.0, 0.0], //点B 
      [1.0, 0.0, 0.0], //点C 
      [1.0, 1.0, 0.0], //点D 
      [0.0, 1.0, 1.0], //点E 
      [0.0, 0.0, 1.0], //点F 
      [1.0, 0.0, 1.0], //点G 
      [1.0, 1.0, 1.0]  //点H 
    ],
    //顶点索引
    pointIndex: [
      [0, 1, 2, 3], //A-B-C-D 上面
      [4, 5, 6, 7], //E-F-G-H 下面
      [2, 3, 7, 6], //C-D-H-G 前面
      [1, 0, 4, 5], //B-A-E-F 后面
      [2, 1, 5, 6], //C-B-F-G 左面
      [3, 0, 4, 7]  //D-A-E-H 右面
    ]
  }

  // 初始化并启动imodelhost
  const imHostConfig = new IModelHostConfiguration();
  await IModelHost.startup(imHostConfig)

  //创建一个iModelDb
  if (IModelJsFs.existsSync("./cube.bim")) {
    IModelJsFs.unlinkSync("./cube.bim")
  }

  if (IModelJsFs.existsSync("./cube.bim.Tiles")) {
    IModelJsFs.unlinkSync("./cube.bim.Tiles")
  }

  const db = StandaloneDb.createEmpty("./cube.bim", { rootSubject: { name: "root" } })

  db.codeSpecs.insert("Generic:PhysicalObject", CodeScopeSpec.Type.Model)
  const subjectCode = Subject.createCode(db, IModel.rootSubjectId, "cube")
  const subjectId = Subject.insert(db, subjectCode.scope, subjectCode.value)

  const physicalPartitionCode = PhysicalPartition.createCode(db, subjectId, "cube")
  const physicalModelId = PhysicalModel.insert(db, physicalPartitionCode.scope, physicalPartitionCode.value)

  const definitionPartitionCode = DefinitionPartition.createCode(db, subjectId, "Definitions")
  const definitionModelId = DefinitionModel.insert(db, definitionPartitionCode.scope, definitionPartitionCode.value)

  const modelSelectorCode = ModelSelector.createCode(db, definitionModelId, "Physical Models")
  const modelSelectorId = ModelSelector.insert(db, definitionModelId, modelSelectorCode.value, [physicalModelId])

  const categoryId = SpatialCategory.insert(db, definitionModelId, "cube", { color: ColorDef.white })
  const CodeOfSpatialCategory = SpatialCategory.createCode(db, definitionModelId, "cube")
  const categoryCode = db.elements.queryElementIdByCode(CodeOfSpatialCategory)

  const specId = db.codeSpecs.getByName("Generic:PhysicalObject").id
  const scopeId = physicalModelId.toString()
  const codeTmp = new Code({ spec: specId, scope: scopeId, value: '0x1' })

  //依据立方体的data生成geometryStream
  const geometryStreamBuilder = new GeometryStreamBuilder()
  for (let i = 0; i < data.pointIndex.length; i++) {
    //indexed mesh
    const indexedPolyface = IndexedPolyface.create()
    for (let j = 0; j < data.pointIndex[i].length; j++) {
      //添加顶点
      let point = data.point[data.pointIndex[i][j]]
      indexedPolyface.addPoint(new Point3d(point[0], point[1], point[2]))

      //添加顶点索引
      indexedPolyface.addPointIndex(j, true)
    }

    indexedPolyface.terminateFacet()

    //着色
    const props = {
      material: undefined,
      color: undefined,
      transp: 0.5
    }
    const colorMode = ['material', 'draw']
    switch (colorMode[1]) {
      //漫反射颜色(将颜色以材质方式的贴上去)
      case 'material':
        const params = {
          color:  //颜色: 百分比格式的RGBA(100%,0%,0%,1.0)
            [
              math.fix(math.random(0, 1), 3),   //R
              math.fix(math.random(0, 1), 3),   //G
              math.fix(math.random(0, 1), 3),  //B
              1.0                              //alpha
            ],
          transmit: 0,  //透明度:0为不透明, 1为完全透明
          diffuse: 0.9 //颜色反射率:0最暗淡,1最鲜艳
        }
        const materialId = RenderMaterialElement.insert(db, definitionModelId, i, params)
        props.material = materialId
        break;
      //常规颜色(直接画上去)
      case 'draw':
        const color = ColorDef.from(math.randomInt(0, 255), math.randomInt(0, 255), math.randomInt(0, 255))
        props.color = color.toJSON()
        break;
    }
    const subCategoryId = SubCategory.insert(db, categoryId, i, props)
    geometryStreamBuilder.appendSubCategoryChange(subCategoryId)
    geometryStreamBuilder.appendGeometry(indexedPolyface)
  }

  const geometryStream = geometryStreamBuilder.geometryStream

  const buildingProps = {
    classFullName: PhysicalObject.classFullName,
    model: physicalModelId,
    category: categoryCode,
    code: codeTmp,
    userLabel: "cube",
    geom: geometryStream
  }

  //将立方体插入进模型里
  const elementId = db.elements.insertElement(buildingProps)
  const projectExtents = db.computeProjectExtents()
  const extents = projectExtents.extents

  const viewFlagProps = {
    cameraLights: true,
    sourceLights: true,
    visibleEdges: false,
    renderMode: RenderMode.SmoothShade
  }

  const viewFlags = ViewFlags.fromJSON(viewFlagProps)

  const displayStyle = {
    name: 'Default',
    lights: {
      solar: { direction: [-0.9833878378071199, -0.18098510351728977, 0.013883542698953828], intensity: 1.05 },
      ambient: { intensity: 0.25 },
      hemisphere: {
        upperColor: { r: 100, g: 100, b: 100 },
        intensity: 0.5,
      },
      portrait: { intensity: 0 },
    },
    viewFlags,
    backgroundColor: ColorDef.create('#E1FFFF')
  }

  const displayStyle3dCode = DisplayStyle3d.createCode(db, definitionModelId, displayStyle.name)
  const displayStyle3dId = DisplayStyle3d.insert(db, definitionModelId, displayStyle3dCode.value, displayStyle)

  const spatialCategorySelectorCode = CategorySelector.createCode(db, definitionModelId, "Spatial Categories")
  const spatialCategorySelectorId = CategorySelector.insert(db, definitionModelId, spatialCategorySelectorCode.value, [categoryCode])

  const viewCode = SpatialViewDefinition.createCode(db, definitionModelId, 'Default View')
  const viewId = SpatialViewDefinition.insertWithCamera(db, definitionModelId, viewCode.value, modelSelectorId, spatialCategorySelectorId, displayStyle3dId, extents)

  db.views.setDefaultViewId(viewId)
  db.updateProjectExtents(extents)
  db.saveChanges()
  db.close()
  console.log(`INSERT SUCCESS ElementId: ${elementId}`)
}

drawCubeWithColor()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔法战胜魔法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值