예제 #1
0
파일: Mesh.cpp 프로젝트: ezEngine/ezEngine
  ezResult Mesh::ComputeNormals()
  {
    ezStopwatch timer;

    const VertexDataStream* positionStreamRaw = GetDataStream(ezGALVertexAttributeSemantic::Position);
    if (positionStreamRaw == nullptr)
    {
      ezLog::Error("Can't compute vertex normals for the mesh '{0}', because it doesn't have vertex positions.", m_Name);
      return EZ_FAILURE;
    }
    const TypedVertexDataStreamView<ezVec3> positionStream(*positionStreamRaw);

    VertexDataStream* normalStreamRaw = AddDataStream(ezGALVertexAttributeSemantic::Normal, 3);
    TypedVertexDataStreamView_ReadWrite<ezVec3> normalStream(*normalStreamRaw);

    // Normals have same mapping as positions.
    normalStream->m_IndexToData = positionStreamRaw->m_IndexToData;
    // Reset all normals to zero.
    normalStream->m_Data.SetCountUninitialized(positionStreamRaw->m_Data.GetCount());
    ezMemoryUtils::ZeroFill<char>(normalStream->m_Data.GetData(), normalStream->m_Data.GetCount());


    // Compute unnormalized triangle normals and add them to all vertices.
    // This way large triangles have an higher influence on the vertex normal.
    for (const Triangle& triangle : m_Triangles)
    {
      const VertexIndex v0 = triangle.m_Vertices[0];
      const VertexIndex v1 = triangle.m_Vertices[1];
      const VertexIndex v2 = triangle.m_Vertices[2];

      const ezVec3 p0 = positionStream.GetValue(v0);
      const ezVec3 p1 = positionStream.GetValue(v1);
      const ezVec3 p2 = positionStream.GetValue(v2);

      const ezVec3 d01 = p1 - p0;
      const ezVec3 d02 = p2 - p0;

      const ezVec3 triNormal = d01.CrossRH(d02);
      normalStream.SetValue(v0, normalStream.GetValue(v0) +
                                    triNormal); // (possible optimization: have a special addValue to avoid unnecessary lookup)
      normalStream.SetValue(v1, normalStream.GetValue(v1) + triNormal);
      normalStream.SetValue(v2, normalStream.GetValue(v2) + triNormal);
    }

    // Normalize normals.
    for (ezUInt32 n = 0; n < normalStream->m_Data.GetCount(); n += sizeof(ezVec3))
      reinterpret_cast<ezVec3*>(&normalStream->m_Data[n])->NormalizeIfNotZero();

    ezLog::Debug("Computed mesh normals ('{0}') in '{1}'s", m_Name, ezArgF(timer.GetRunningTotal().GetSeconds(), 2));
    return EZ_SUCCESS;
  }
예제 #2
0
파일: Mesh.cpp 프로젝트: ezEngine/ezEngine
  void Mesh::AddData(const Mesh& mesh, const ezTransform& transform)
  {
    ezMat4 transformMat = transform.GetAsMat4();
    ezMat4 normalTransformMat = transformMat.GetInverse(0.0f).GetTranspose();

    // Create new triangles.
    ezUInt32 oldTriangleCount = GetNumTriangles();
    AddTriangles(mesh.GetNumTriangles());

    ezArrayPtr<const Mesh::Triangle> sourceTriangles = mesh.GetTriangles();
    ezArrayPtr<const Mesh::Triangle> targetTriangles = GetTriangles().GetSubArray(oldTriangleCount);
    EZ_ASSERT_DEBUG(sourceTriangles.GetCount() == targetTriangles.GetCount(), "Something is wrong with triangle allocation!");

    for (auto it = mesh.m_VertexDataStreams.GetIterator(); it.IsValid(); ++it)
    {
      const VertexDataStream* sourceStream = it.Value();
      VertexDataStream* targetStream = AddDataStream(static_cast<ezGALVertexAttributeSemantic::Enum>(it.Key()),
                                                     sourceStream->GetNumElementsPerVertex(), sourceStream->GetElementType());
      if (!targetStream)
      {
        ezLog::SeriousWarning("Cannot merge mesh {0} properly since it has a vertex data stream with semantic {1} that uses {2} elements "
                              "instead of 'unkown' which is used by the merge target. Skipping this data stream.",
                              mesh.m_Name, it.Key(), sourceStream->GetNumElementsPerVertex());
        continue;
      }

      // Copy data.
      ezUInt32 targetBaseDataIndex = targetStream->m_Data.GetCount();
      targetStream->m_Data.PushBackRange(sourceStream->m_Data);

      // Transform data.
      if (!transform.IsIdentical(ezTransform::IdentityTransform()))
      {
        const ezUInt32 attributeSize = targetStream->GetAttributeSize();

        // Positions
        if (it.Key() == ezGALVertexAttributeSemantic::Position)
        {
          for (ezUInt32 i = targetBaseDataIndex; i < targetStream->m_Data.GetCount(); i += attributeSize)
          {
            ezVec3& pos = *reinterpret_cast<ezVec3*>(&targetStream->m_Data[i]);
            pos = transformMat.TransformPosition(pos);
          }
        }
        // Directions
        else if (it.Key() == ezGALVertexAttributeSemantic::Normal || it.Key() == ezGALVertexAttributeSemantic::Tangent ||
                 it.Key() == ezGALVertexAttributeSemantic::BiTangent)
        {
          for (ezUInt32 i = targetBaseDataIndex; i < targetStream->m_Data.GetCount(); i += attributeSize)
          {
            ezVec3& dir = *reinterpret_cast<ezVec3*>(&targetStream->m_Data[i]);
            dir = normalTransformMat.TransformDirection(dir);
          }
        }
      }

      // Set mapping
      for (ezUInt32 tri = 0; tri < sourceTriangles.GetCount(); ++tri)
      {
        for (int v = 0; v < 3; ++v)
        {
          VertexDataIndex sourceDataIndex = sourceStream->GetDataIndex(sourceTriangles[tri].m_Vertices[v]);
          if (sourceDataIndex.IsValid())
            targetStream->SetDataIndex(targetTriangles[tri].m_Vertices[v], targetBaseDataIndex + sourceDataIndex.GetValue());
        }
      }
    }

    // Add submeshes.
    ezUInt32 oldSubMeshCount = m_SubMeshes.GetCount();
    m_SubMeshes.PushBackRange(mesh.m_SubMeshes);
    for (ezUInt32 i = oldSubMeshCount; i < m_SubMeshes.GetCount(); ++i)
    {
      m_SubMeshes[i].m_uiFirstTriangle += oldTriangleCount;
    }

    // Add skeleton if existent
    // TODO: What if multiple, incompatible skeletons are found(?)
    // For now: Remove skeleton and import unskinned
    // if (mesh.m_pSkeleton)
    //{
    //  if (m_pSkeleton)
    //  {
    //    if (!m_pSkeleton->IsCompatibleWith(mesh.m_pSkeleton.Borrow()))
    //    {
    //      ezLog::Warning("Found incompatible skeletons during mesh merging in mesh '{0}', import will be without skeletons!",
    //      m_Name.GetData()); m_pSkeleton.Reset();
    //    }
    //  }
    //  else
    //  {
    //    m_pSkeleton = EZ_DEFAULT_NEW(ezSkeleton, *mesh.m_pSkeleton);
    //  }
    //}
  }
예제 #3
0
파일: stream.c 프로젝트: refaim/paralabs
int main(int argc, char **argv)
{
    int iRetCode = EXIT_SUCCESS;

    char *szFilename = NULL;
    int iOptionIndex, iArgIndex, iMode, iGetoptRet;
    struct option arLongOpts[] =
    {
        { "add", no_argument, &iMode, MODE_ADD },
        { "list", no_argument, &iMode, MODE_LIST },
        { 0, 0, 0, 0 }
    };

    do
    {
        iGetoptRet = getopt_long(argc, argv, "", arLongOpts, &iOptionIndex);
        if (iGetoptRet == '?')
        {
            return EXIT_FAILURE;
        }
    } while (iGetoptRet != -1);

    iArgIndex = 1 + 1; // executable name + option
    if (iArgIndex == argc)
    {
        printf("stream: no filename specified\n");
        return EXIT_FAILURE;
    }
    szFilename = argv[iArgIndex];

    switch (iMode)
    {
        case MODE_ADD:
        {
            char *szStreamName = NULL;
            DWORD dwStreamSize;

            if (++iArgIndex == argc)
            {
                printf("stream: no stream specified\n");
                return EXIT_FAILURE;
            }
            szStreamName = argv[iArgIndex];

            if (++iArgIndex == argc)
            {
                dwStreamSize = DEFAULT_STREAM_SIZE_MB;
            }
            else
            {
                dwStreamSize = atoi(argv[iArgIndex]);
            }

            iRetCode = AddDataStream(szFilename, szStreamName, dwStreamSize);
            break;
        }
        case MODE_LIST:
        {
            iRetCode = ListDataStreams(szFilename);
            break;
        }
        default:
        {
            printf("stream: unknown mode %d\n", iMode);
            return EXIT_FAILURE;
        }
    }

    return iRetCode;
}