Conversion rules: ----------------- Converting from a scalar or vector to a smaller scalar or vector will truncate values from the end of the source value. Converting from a scalar or vector to a larger vector will zero-fill at the end, unless the semantic-type is position, color or tangent, in which case the W component will be one. Converting from a scalar or vector to a larger matrix will zero-
| 504 | // Converting from a matrix to a larger matrix will write into the top-left portion of the destination matrix, and fill the remaining space with the identity matrix. |
| 505 | // Converting from a matrix to a vector will truncate values from the end of the source matrix. |
| 506 | uint8_t* WriteAttributes(uint8_t* write_ptr, uint32_t vertex_index, uint32_t vertex_count, const WriteAttributeParams& params) |
| 507 | { |
| 508 | UnpackAttributeData dst_data; |
| 509 | UnpackAttributeData src_data; |
| 510 | UnpackAttributeDataState unpack_state; |
| 511 | |
| 512 | for (int v = 0; v < vertex_count; ++v) { |
| 513 | memset(&dst_data, 0, sizeof(dst_data)); |
| 514 | memset(&src_data, 0, sizeof(src_data)); |
| 515 | memset(&unpack_state, 0, sizeof(unpack_state)); |
| 516 | |
| 517 | for (int i = 0; i < params.m_VertexAttributeInfos->m_NumInfos; ++i) |
| 518 | { |
| 519 | const VertexAttributeInfo& info = params.m_VertexAttributeInfos->m_Infos[i]; |
| 520 | if (info.m_StepFunction != params.m_StepFunction) |
| 521 | { |
| 522 | continue; |
| 523 | } |
| 524 | |
| 525 | dst_data.m_VectorType = info.m_VectorType; |
| 526 | dst_data.m_DataType = info.m_DataType; |
| 527 | dst_data.m_ElementCount = VectorTypeToElementCount(dst_data.m_VectorType); |
| 528 | dst_data.m_IsMatrix = VectorTypeIsMatrix(dst_data.m_VectorType); |
| 529 | |
| 530 | const uint32_t dst_element_byte_width = DataTypeToByteWidth(dst_data.m_DataType); |
| 531 | const size_t attribute_stride = dst_data.m_ElementCount * dst_element_byte_width; |
| 532 | |
| 533 | UnpackWriteAttributeBySemanticType(unpack_state, vertex_index + v, params, info, &src_data); |
| 534 | |
| 535 | // If there is no data available at all, we pick one of the default float arrays |
| 536 | if (src_data.m_ValuePtr == 0) |
| 537 | { |
| 538 | SetUnpackAttributeDataDefault(info, src_data, dst_data); |
| 539 | } |
| 540 | |
| 541 | if (src_data.m_VectorType == VertexAttribute::VECTOR_TYPE_SCALAR) |
| 542 | { |
| 543 | WriteScalar(write_ptr, src_data, dst_data); |
| 544 | } |
| 545 | else if (src_data.m_IsMatrix && dst_data.m_IsMatrix) |
| 546 | { |
| 547 | WriteMatrixToMatrix(write_ptr, src_data, dst_data); |
| 548 | } |
| 549 | else |
| 550 | { |
| 551 | if (src_data.m_ElementCount < dst_data.m_ElementCount && dst_data.m_ElementCount >= 4 && SemanticTypeRequiresOneAsW(info.m_SemanticType)) |
| 552 | { |
| 553 | uint8_t v4_one_as_w_backing[sizeof(float)*4] = {}; |
| 554 | memcpy(v4_one_as_w_backing, src_data.m_ValuePtr, src_data.m_ElementCount * DataTypeToByteWidth(src_data.m_DataType)); |
| 555 | |
| 556 | if (src_data.m_DataType == VertexAttribute::TYPE_FLOAT) |
| 557 | { |
| 558 | ((float*) v4_one_as_w_backing)[3] = 1.0; |
| 559 | } |
| 560 | else |
| 561 | { |
| 562 | WriteVertexAttributeFromFloat(v4_one_as_w_backing + 3 * dst_element_byte_width, 1.0, dst_data.m_DataType); |
| 563 | } |