mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
optimzie base64
mcp w.i.p.
This commit is contained in:
@@ -36,7 +36,7 @@ sleep 1
|
|||||||
# remove '\r'
|
# remove '\r'
|
||||||
sess_id=`cat sess_id.txt | tr -d '\r'`
|
sess_id=`cat sess_id.txt | tr -d '\r'`
|
||||||
sess_header="mcp-session-id: ${sess_id}"
|
sess_header="mcp-session-id: ${sess_id}"
|
||||||
echo $sess_header
|
#echo $sess_header
|
||||||
|
|
||||||
curl -v -X POST \
|
curl -v -X POST \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
|
sess_id=`cat sess_id.txt | tr -d '\r'`
|
||||||
|
sess_header="mcp-session-id: ${sess_id}"
|
||||||
|
|
||||||
curl -X POST \
|
curl -X POST \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Accept: application/json, text/event-stream" \
|
||||||
|
-H "${sess_header}" \
|
||||||
-d '{
|
-d '{
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"method": "tools/call",
|
"method": "tools/call",
|
||||||
|
|||||||
134
src/str-util.cc
134
src/str-util.cc
@@ -5,6 +5,10 @@
|
|||||||
#include "unicode-xid.hh"
|
#include "unicode-xid.hh"
|
||||||
#include "common-macros.inc"
|
#include "common-macros.inc"
|
||||||
|
|
||||||
|
#ifdef __SSE2__
|
||||||
|
#include <emmintrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace tinyusdz {
|
namespace tinyusdz {
|
||||||
|
|
||||||
std::string buildEscapedAndQuotedStringForUSDA(const std::string &str) {
|
std::string buildEscapedAndQuotedStringForUSDA(const std::string &str) {
|
||||||
@@ -749,9 +753,12 @@ double atof(const std::string &s) {
|
|||||||
#pragma clang diagnostic ignored "-Wconversion"
|
#pragma clang diagnostic ignored "-Wconversion"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __SSE2__
|
||||||
|
#else
|
||||||
static inline bool is_base64(unsigned char c) {
|
static inline bool is_base64(unsigned char c) {
|
||||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string base64_encode(unsigned char const *bytes_to_encode,
|
std::string base64_encode(unsigned char const *bytes_to_encode,
|
||||||
unsigned int in_len) {
|
unsigned int in_len) {
|
||||||
@@ -798,7 +805,133 @@ std::string base64_encode(unsigned char const *bytes_to_encode,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SSE2-optimized base64 decode implementation
|
||||||
|
#ifdef __SSE2__
|
||||||
|
static std::string base64_decode_sse(std::string const &encoded_string) {
|
||||||
|
const size_t input_len = encoded_string.size();
|
||||||
|
if (input_len == 0) return std::string();
|
||||||
|
|
||||||
|
// Lookup table for base64 decoding (256 entries, -1 for invalid chars)
|
||||||
|
static const int8_t decode_table[256] = {
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
||||||
|
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-2,-1,-1,
|
||||||
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||||||
|
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
||||||
|
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||||||
|
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||||
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate output size (remove padding)
|
||||||
|
size_t padding = 0;
|
||||||
|
if (input_len >= 1 && encoded_string[input_len - 1] == '=') padding++;
|
||||||
|
if (input_len >= 2 && encoded_string[input_len - 2] == '=') padding++;
|
||||||
|
|
||||||
|
const size_t output_len = (input_len * 3) / 4 - padding;
|
||||||
|
std::string result;
|
||||||
|
result.reserve(output_len);
|
||||||
|
|
||||||
|
const uint8_t* input = reinterpret_cast<const uint8_t*>(encoded_string.data());
|
||||||
|
size_t input_pos = 0;
|
||||||
|
|
||||||
|
// Process 16 bytes at a time using SSE2
|
||||||
|
while (input_pos + 16 <= input_len) {
|
||||||
|
// Load 16 input bytes
|
||||||
|
__m128i input_chunk = _mm_loadu_si128(reinterpret_cast<const __m128i*>(input + input_pos));
|
||||||
|
|
||||||
|
// Decode using lookup table (split into two 8-byte chunks for table lookup)
|
||||||
|
alignas(16) uint8_t input_bytes[16];
|
||||||
|
_mm_store_si128(reinterpret_cast<__m128i*>(input_bytes), input_chunk);
|
||||||
|
|
||||||
|
alignas(16) int8_t decoded[16];
|
||||||
|
bool valid = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
decoded[i] = decode_table[input_bytes[i]];
|
||||||
|
if (decoded[i] < 0 && input_bytes[i] != '=') {
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid) break; // Fall back to scalar processing for invalid chars
|
||||||
|
|
||||||
|
// Pack groups of 4 decoded bytes into 3 output bytes
|
||||||
|
for (int group = 0; group < 4; group++) {
|
||||||
|
if (input_pos + group * 4 + 3 >= input_len) break;
|
||||||
|
|
||||||
|
int base_idx = group * 4;
|
||||||
|
if (decoded[base_idx] >= 0 && decoded[base_idx + 1] >= 0 &&
|
||||||
|
decoded[base_idx + 2] >= 0 && decoded[base_idx + 3] >= 0) {
|
||||||
|
|
||||||
|
uint32_t combined = (static_cast<uint32_t>(decoded[base_idx]) << 18) |
|
||||||
|
(static_cast<uint32_t>(decoded[base_idx + 1]) << 12) |
|
||||||
|
(static_cast<uint32_t>(decoded[base_idx + 2]) << 6) |
|
||||||
|
static_cast<uint32_t>(decoded[base_idx + 3]);
|
||||||
|
|
||||||
|
result.push_back(static_cast<char>((combined >> 16) & 0xFF));
|
||||||
|
result.push_back(static_cast<char>((combined >> 8) & 0xFF));
|
||||||
|
result.push_back(static_cast<char>(combined & 0xFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input_pos += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process remaining bytes with scalar code
|
||||||
|
while (input_pos + 4 <= input_len) {
|
||||||
|
uint8_t a = input[input_pos];
|
||||||
|
uint8_t b = input[input_pos + 1];
|
||||||
|
uint8_t c = input[input_pos + 2];
|
||||||
|
uint8_t d = input[input_pos + 3];
|
||||||
|
|
||||||
|
if (a == '=' || b == '=') break;
|
||||||
|
|
||||||
|
int8_t da = decode_table[a];
|
||||||
|
int8_t db = decode_table[b];
|
||||||
|
int8_t dc = decode_table[c];
|
||||||
|
int8_t dd = decode_table[d];
|
||||||
|
|
||||||
|
if (da < 0 || db < 0) break;
|
||||||
|
|
||||||
|
uint32_t combined = (static_cast<uint32_t>(da) << 18) |
|
||||||
|
(static_cast<uint32_t>(db) << 12);
|
||||||
|
|
||||||
|
result.push_back(static_cast<char>((combined >> 16) & 0xFF));
|
||||||
|
|
||||||
|
if (c != '=' && dc >= 0) {
|
||||||
|
combined |= static_cast<uint32_t>(dc) << 6;
|
||||||
|
result.push_back(static_cast<char>((combined >> 8) & 0xFF));
|
||||||
|
|
||||||
|
if (d != '=' && dd >= 0) {
|
||||||
|
combined |= static_cast<uint32_t>(dd);
|
||||||
|
result.push_back(static_cast<char>(combined & 0xFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input_pos += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // __SSE2__
|
||||||
|
|
||||||
|
// Fallback implementation (original)
|
||||||
std::string base64_decode(std::string const &encoded_string) {
|
std::string base64_decode(std::string const &encoded_string) {
|
||||||
|
#ifdef __SSE2__
|
||||||
|
// Use SSE2 optimized version if available
|
||||||
|
return base64_decode_sse(encoded_string);
|
||||||
|
#else
|
||||||
|
// Original scalar implementation
|
||||||
int in_len = static_cast<int>(encoded_string.size());
|
int in_len = static_cast<int>(encoded_string.size());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
@@ -847,6 +980,7 @@ std::string base64_decode(std::string const &encoded_string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
#endif // __SSE2__
|
||||||
}
|
}
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ source_group("Source Files" FILES ${SOURCES})
|
|||||||
if (EMSCRIPTEN)
|
if (EMSCRIPTEN)
|
||||||
|
|
||||||
if (TINYUSDZ_WASM_DEMODEV)
|
if (TINYUSDZ_WASM_DEMODEV)
|
||||||
set(OUTPUT_WASM_DIR ${PROJECT_SOURCE_DIR}/demo/node_modules/tinyusdz/)
|
set(OUTPUT_WASM_DIR ${PROJECT_SOURCE_DIR}/mcp-server/node_modules/tinyusdz/)
|
||||||
else()
|
else()
|
||||||
set(OUTPUT_WASM_DIR ${PROJECT_SOURCE_DIR}/js/src/tinyusdz/)
|
set(OUTPUT_WASM_DIR ${PROJECT_SOURCE_DIR}/js/src/tinyusdz/)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
107
web/demo/main.js
107
web/demo/main.js
@@ -6,6 +6,81 @@ import { GUI } from 'https://cdn.jsdelivr.net/npm/dat.gui@0.7.9/build/dat.gui.mo
|
|||||||
import { TinyUSDZLoader } from 'tinyusdz/TinyUSDZLoader.js'
|
import { TinyUSDZLoader } from 'tinyusdz/TinyUSDZLoader.js'
|
||||||
import { TinyUSDZLoaderUtils } from 'tinyusdz/TinyUSDZLoaderUtils.js'
|
import { TinyUSDZLoaderUtils } from 'tinyusdz/TinyUSDZLoaderUtils.js'
|
||||||
|
|
||||||
|
// Loading bar elements
|
||||||
|
const loadingContainer = document.createElement('div');
|
||||||
|
loadingContainer.id = 'loading-container';
|
||||||
|
loadingContainer.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
color: white;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const loadingText = document.createElement('div');
|
||||||
|
loadingText.id = 'loading-text';
|
||||||
|
loadingText.textContent = 'Loading...';
|
||||||
|
loadingText.style.cssText = `
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const progressBarContainer = document.createElement('div');
|
||||||
|
progressBarContainer.style.cssText = `
|
||||||
|
width: 300px;
|
||||||
|
height: 20px;
|
||||||
|
background: #333;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const progressBar = document.createElement('div');
|
||||||
|
progressBar.id = 'progress-bar';
|
||||||
|
progressBar.style.cssText = `
|
||||||
|
width: 0%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, #4CAF50, #8BC34A);
|
||||||
|
border-radius: 10px;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const progressText = document.createElement('div');
|
||||||
|
progressText.id = 'progress-text';
|
||||||
|
progressText.textContent = '0%';
|
||||||
|
progressText.style.cssText = `
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ccc;
|
||||||
|
`;
|
||||||
|
|
||||||
|
progressBarContainer.appendChild(progressBar);
|
||||||
|
loadingContainer.appendChild(loadingText);
|
||||||
|
loadingContainer.appendChild(progressBarContainer);
|
||||||
|
loadingContainer.appendChild(progressText);
|
||||||
|
document.body.appendChild(loadingContainer);
|
||||||
|
|
||||||
|
// Function to update loading progress
|
||||||
|
function updateLoadingProgress(progress, message = 'Loading...') {
|
||||||
|
loadingText.textContent = message;
|
||||||
|
progressBar.style.width = `${progress}%`;
|
||||||
|
progressText.textContent = `${Math.round(progress)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to hide loading screen
|
||||||
|
function hideLoadingScreen() {
|
||||||
|
loadingContainer.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const gui = new GUI();
|
const gui = new GUI();
|
||||||
|
|
||||||
let ui_state = {}
|
let ui_state = {}
|
||||||
@@ -17,6 +92,7 @@ ui_state['ambient'] = 0.4;
|
|||||||
let ambientLight = new THREE.AmbientLight(0x404040, ui_state['ambient']);
|
let ambientLight = new THREE.AmbientLight(0x404040, ui_state['ambient']);
|
||||||
ui_state['camera_z'] = 3.14; // TODO: Compute best fit from scene's bbox.
|
ui_state['camera_z'] = 3.14; // TODO: Compute best fit from scene's bbox.
|
||||||
ui_state['needsMtlUpdate'] = false;
|
ui_state['needsMtlUpdate'] = false;
|
||||||
|
ui_state['renderer'] = null;
|
||||||
|
|
||||||
|
|
||||||
// Create a parameters object
|
// Create a parameters object
|
||||||
@@ -24,6 +100,7 @@ const params = {
|
|||||||
envMapIntensity: ui_state['envMapIntensity'],
|
envMapIntensity: ui_state['envMapIntensity'],
|
||||||
rotationSpeed: ui_state['rot_scale'],
|
rotationSpeed: ui_state['rot_scale'],
|
||||||
camera_z: ui_state['camera_z'],
|
camera_z: ui_state['camera_z'],
|
||||||
|
take_screenshot: takeScreenshot
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add controls
|
// Add controls
|
||||||
@@ -38,31 +115,48 @@ gui.add(params, 'camera_z', 0, 20).name('Camera Z').onChange((value) => {
|
|||||||
gui.add(params, 'rotationSpeed', 0, 10).name('Rotation Speed').onChange((value) => {
|
gui.add(params, 'rotationSpeed', 0, 10).name('Rotation Speed').onChange((value) => {
|
||||||
ui_state['rot_scale'] = value;
|
ui_state['rot_scale'] = value;
|
||||||
});
|
});
|
||||||
|
gui.add(params, 'take_screenshot').name('Take Screenshot');
|
||||||
|
|
||||||
|
|
||||||
|
function takeScreenshot() {
|
||||||
|
|
||||||
|
const renderer = ui_state['renderer'];
|
||||||
|
const quality = 0.92; // JPEG quality, if you want to use JPEG format
|
||||||
|
|
||||||
|
const img = renderer.domElement.toDataURL('image/jpeg', quality)
|
||||||
|
console.log('Screenshot taken:', img);
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
async function loadScenes() {
|
async function loadScenes() {
|
||||||
|
|
||||||
|
updateLoadingProgress(20, 'Initializing TinyUSDZLoader...');
|
||||||
|
|
||||||
const loader = new TinyUSDZLoader();
|
const loader = new TinyUSDZLoader();
|
||||||
|
|
||||||
// it is recommended to call init() before loadAsync()
|
// it is recommended to call init() before loadAsync()
|
||||||
// (wait loading/compiling wasm module in the early stage))
|
// (wait loading/compiling wasm module in the early stage))
|
||||||
//await loader.init();
|
await loader.init();
|
||||||
|
|
||||||
// Use zstd compressed tinyusdz.wasm to save the bandwidth.
|
// Use zstd compressed tinyusdz.wasm to save the bandwidth.
|
||||||
await loader.init({useZstdCompressedWasm: true});
|
//await loader.init({useZstdCompressedWasm: true});
|
||||||
|
|
||||||
const suzanne_filename = "./assets/suzanne-pbr.usda";
|
const suzanne_filename = "./assets/suzanne-pbr.usda";
|
||||||
const texcat_filename = "./assets/texture-cat-plane.usdz";
|
const texcat_filename = "./assets/texture-cat-plane.usdz";
|
||||||
const cookie_filename = "./assets/UsdCookie.usdz";
|
const cookie_filename = "./assets/UsdCookie.usdz";
|
||||||
|
const usd_filename = "./assets/suzanne-pbr.usda";
|
||||||
|
|
||||||
var threeScenes = []
|
var threeScenes = []
|
||||||
|
|
||||||
const usd_scenes = await Promise.all([
|
const usd_scenes = await Promise.all([
|
||||||
//loader.loadAsync(texcat_filename),
|
//loader.loadAsync(texcat_filename),
|
||||||
loader.loadAsync(cookie_filename),
|
loader.loadAsync(usd_filename),
|
||||||
//loader.loadAsync(suzanne_filename),
|
//loader.loadAsync(suzanne_filename),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
hideLoadingScreen();
|
||||||
|
|
||||||
const defaultMtl = ui_state['defaultMtl'];
|
const defaultMtl = ui_state['defaultMtl'];
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
@@ -114,8 +208,13 @@ async function initScene() {
|
|||||||
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||||
camera.position.z = ui_state['camera_z'];
|
camera.position.z = ui_state['camera_z'];
|
||||||
|
|
||||||
const renderer = new THREE.WebGLRenderer();
|
const renderer = new THREE.WebGLRenderer({
|
||||||
|
preserveDrawingBuffer: true, // for screenshot
|
||||||
|
alpha: true, // Enable transparency
|
||||||
|
antialias: true
|
||||||
|
});
|
||||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||||
|
ui_state['renderer'] = renderer; // Store renderer in ui_state
|
||||||
document.body.appendChild(renderer.domElement);
|
document.body.appendChild(renderer.domElement);
|
||||||
|
|
||||||
const rootNodes = await loadScenes();
|
const rootNodes = await loadScenes();
|
||||||
|
|||||||
1333
web/demo/package-lock.json
generated
1333
web/demo/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@
|
|||||||
"vite": "^6.1.6"
|
"vite": "^6.1.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@modelcontextprotocol/sdk": "^1.15.1",
|
||||||
"fzstd": "^0.1.1",
|
"fzstd": "^0.1.1",
|
||||||
"gsap": "^3.13.0",
|
"gsap": "^3.13.0",
|
||||||
"lil-gui": "^0.19.2",
|
"lil-gui": "^0.19.2",
|
||||||
|
|||||||
Reference in New Issue
Block a user