diff --git a/.gitignore b/.gitignore
index bd99fc5..799efd5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,5 @@
-outputs/
\ No newline at end of file
+outputs/
+
+data/objaverse/
+
+scripts/__pycache__/
\ No newline at end of file
diff --git a/README.md b/README.md
index 5b1bb59..6f17fa6 100644
--- a/README.md
+++ b/README.md
@@ -79,6 +79,10 @@ For the best quality of texture synthesis, there are some necessary pre-processi
We provide `scripts/normalize_mesh.py` and `scripts/rotate_mesh.py` to make the mesh preprocessing easy for you.
+If you already have a normalized mesh but haven't parameterized it yet, please use `scripts/parameterize_mesh.py` to generate the UV map.
+
+> NOTE: we expect the mesh to be triangulated.
+
A mesh ready for next steps should look like this:

@@ -112,6 +116,16 @@ python scripts/generate_texture.py \
If you want some high-res textures, you can set `--device` to `a6000` for 3k resolution. To play around other parameters, please check `scripts/generate_texture.py`, or simply run `python scripts/generate_texture.py -h`.
+## Benchmark on Objaverse subset
+
+To generate textures for the Objaverse objects we used in the paper, please run the following script to download and pre-process those meshes:
+
+```shell
+python scripts/download_objaverse_subset.py
+```
+
+All pre-processed meshes will be downloaded to `data/objaverse/`.
+
## Citation
If you found our work helpful, please kindly cite this papers:
diff --git a/data/objaverse_subset.txt b/data/objaverse_subset.txt
new file mode 100644
index 0000000..21aeb53
--- /dev/null
+++ b/data/objaverse_subset.txt
@@ -0,0 +1,410 @@
+Bible_3e5393bd35e34531a576e22d45611060
+Bible_ee7660359dda4c90990cb7440211b873
+Bible_f5bf29193be44caaad2df1db3db44871
+CD_player_00a66884dacb498b85701acd1cc77c5e
+CD_player_dbf0dbcf4229429088b0a984e8f05666
+Lego_8b1319902fef43dc904a257a377d9676
+Tabasco_sauce_0880be4c17d34b95af74efde0dea22c3
+Tabasco_sauce_d78ccbe406f744b881aa2c339fbd27ef
+aerosol_can_10ac5e64861a4cb4868a244d08496b97
+aerosol_can_211e925eaa5c49a2b9216d785413cc2a
+aerosol_can_4c8af55af44c4e888fa9e3ca037f65e3
+airplane_3ca2f507a0a749799e16a4eee12e456c
+alarm_clock_8464d97835954b7f9d4c35257f8f7bd4
+ambulance_ae7f73580602427b8352cedf8aaec0fa
+ambulance_fe533dcb116d4d35bf55fcf5c0bfb008
+apple_25baea74f1914aafb9ddef58d0106969
+apple_b496adbf9b924ff99939ad38330eb3cf
+apple_e3173857f9384aa4928daeabff75da44
+apricot_01994d08f4834acd9734f1a4281570d8
+armchair_0e06763d63f44733b99c06ae18dcb13d
+armchair_6e35f6fdf1264db4880049b802f18ea2
+armchair_d8072e417dbd476cadb270e39ad3d7c8
+army_tank_fe9bb26f88ce4efd9b0855ea383f3e78
+baby_buggy_a9e7ff47a1c442c9bd97b8fe8bfc8e12
+backpack_9fa2da2c42234b58896e8d23393cac24
+bagel_c2f9b76e6b184138a23dfda89829fa8b
+ball_80f10af6cb604d7cbbd141050d093b2b
+banana_1787fb8e12f14318899702ae6c502de5
+banana_5d99827c456940bf9055dfe2dbc561e8
+banana_ada7c35a1a5742f1b4c528eb3daee35b
+banjo_21d81a73dcdc48a3a4de947e3e4cde2d
+banjo_8c375ece6c444908bf8bfe784c332d30
+barrel_341eecd25e7f4914a6d321e71e5629af
+barrel_b53fb9b3547148d7afe84a073ccd99db
+barrel_eb700168ef994b96bc7865febae8c2ab
+baseball_0d784e804a764432a7111671257ffdf7
+baseball_bat_49b1172903c6436f9025bb288d9db518
+baseball_bat_97f741e3820a44a694fe27775dd1a7f5
+baseball_bat_d0bc56c99ce3427db7e925d5b0964256
+baseball_glove_52b2faaf84ff4300b64195757976509a
+basket_2a43e6e50fdf4d8aac6bccd9e4ba629d
+basket_7f39b77440c4416cab9dbba79f3262a2
+basketball_5fe39851c88f4db5b343fd38ce8ef4ce
+basketball_a8fcf2220c264a30aef6bd8fd51898d4
+bathtub_cf373495a56049f6be1692ca6463aa2a
+beanbag_0b420d09aa224062ad6c8031c382661e
+beanbag_a77f888bac654f8191442e74f0db4e7a
+bed_b547d81073b64d3e97200fd3ae9a74af
+bed_dc3024aa5e234f4299641f072558b9a8
+bed_ef4fef24c990461986a96f5462c5248d
+bedpan_0e5451ae286d40088fcaefa2b6fb5e97
+bench_9ef388cd9cb947f48957a497e8b8184a
+bicycle_d518e2ce054541e6b329dc2343307462
+binoculars_885f1fe05f924bd995a89cfc3b6fe8a9
+binoculars_8a3f1ff2c1c14f74915222454eba92b9
+binoculars_b77fcf18510f410c915456193111a8db
+birdhouse_8c19d6525acf441b9cf3c1fd91598ff6
+birdhouse_f1852103f68944b680ade1592ea50c1c
+birthday_cake_39e6c82654e843dd819a3408374da0a8
+birthday_cake_b095a072c707490ba8ff798e7177748c
+blimp_7b142df10734454da1fc8c98a2ccae89
+blimp_c7b8207727da4a2f9f22059a02f21725
+boat_72fed167ee4a4ff09193cf59f30e5033
+bookcase_51d928b33e5549898cc86cbdaf966d83
+bookcase_a4112060b9aa43a8af876f922f962cce
+bottle_4f458eea419347639f3e210201cd3a5f
+bottle_97802a0adf12404b8370a3b75c5b9237
+bowl_f1eccbd01c884fe28ec65ce699cf7b81
+bread_ba2dccb476b64730a0bf997855245d22
+bread_daf4801f72ae4f9eba9c338afbbb2926
+briefcase_4f4f28032a6e48eba05e51e7ea298334
+briefcase_cb5c52c48f6c4540b2eaae6852267cc5
+broccoli_a5971983ab3e4fa6b395e310490ccb9f
+broom_7d8682b03038465c96b3479a0368ec9a
+broom_addb9901772f488eac5476b1feb60914
+bucket_1702f71e798b4cc794ec12f8219405b9
+bucket_68d83e2d634940f594df30998aba652c
+bucket_998d8d17a4334167a4907f780491dff0
+bulldog_206d1a40d4654d1e940c9ec05b2cc14f
+bulldozer_23e952d905ca4bc788517afd9086edd7
+burrito_985466172dd34d4ca3a9b555a09ef1e2
+burrito_9999197bbac04e3796ce1f4f04470490
+cabinet_1bf163160fa34a2bac8c9c6218675478
+cabinet_b1a6eed00f1246d9b8f8f08003c59362
+cabinet_b7e25d2b684747c08e90b8cf446bdb43
+calculator_b4bb8bd7791648fdb36c458fd9a877bf
+camera_4b3a4cffbbe4499b9e69eaf3157abf06
+can_32c47e171fc54617aef4c5696f27a7a5
+can_b521c9a1162d45d2b4f138206e114fd2
+candle_222643de666b4dad9924bcf03fc7260a
+candle_7816316002f1426c94d4c9b4c59e5696
+candle_e327859b5b66470b9607f57af931646d
+canoe_45bd80f76b294b4985b76f055b7f8d72
+canoe_9922d5678af84adeb1c9b479856446ca
+cappuccino_04f2c34a3df94e58be97c2830e7e462a
+cappuccino_0592fecb8a124d598befd935159bd561
+carrot_53c1ac4a7089403a850519eba65de629
+chair_304253851afd493d958fc8e256c189df
+chair_99fc178ecc0943ae81454a3735e2eb5f
+chair_c5d80712ee2c4741a5f059530e523a7c
+chaise_longue_f25cb76a65ea4d88a92dc4d994cf4094
+chaise_longue_f53f358e46ae4768a97a3ee772dcc314
+chalice_3bc4be75e7634ce0bc8e07b50e2bc369
+chalice_e1a72a2329e942f584e379c24db4fe6a
+chalice_f2933520da4a415bac61ed677275d2f9
+chocolate_bar_6e9c67e3adc345a4b12d0e4f825851a2
+cigarette_e3a5fd374386419680a26a3acaa18728
+clipboard_1b418690fedc45739274d05e81b88ffd
+clipboard_c8a67ebe663544dd9dca484c16f7f21f
+clipboard_f0452a4970e04fc6960bb00bf02d5890
+clock_3031fd7b1adc408ba27ab3515a5c34d8
+clock_87f51c328f854b4582eb55f54b644bd2
+clock_c03d8b43ea2a455eb9f101eef1f0d95f
+clutch_bag_5c5a6601578346aa8ce974453909f175
+clutch_bag_c1969377971847a5aa98aab13613d424
+clutch_bag_e0bfc49fde124fb89cd5cacb0be1a1d6
+coconut_49a8eaee73a943e08fb77049f8b0d16d
+coffee_maker_383923d4412f4b66937d9c1779a9a0a2
+coffee_maker_6784e4f16a7248518cd5ef1118a2198a
+coffee_maker_9a87c4971eed4fd5aa6e1e3441cd1e70
+coffee_table_02302fca239e4d7a9d26ce5cc46225e5
+coffee_table_8d8bd092c4294c55ac726666306365d3
+coffee_table_d53bd92890934d249d4ea2e099ae0461
+coffeepot_7076495f9b5946c596dbd3475972a1db
+coffeepot_bb1023a8c09141d29996924e425fe6c5
+comic_book_728d17781c464189953e2d9482373b36
+compass_3ff33f5baae24b9eab100442fce797e7
+compass_5c47b26f85eb4659af66c10c568c1df3
+computer_keyboard_99de8bd7fb8d40c39989ddac0f98214a
+computer_keyboard_a884bf6ce8b74648b6813564a443824a
+computer_keyboard_b50191176b6a4509aabca39d93bf7c18
+cowboy_hat_2d400d61c1d14401865e8b74a0b72016
+cowboy_hat_4d0db60c85104d8880fab712f158b0b4
+cowboy_hat_e8d5a5d300024a7fa981cd294e97ce60
+crate_2f11377a2e6049049473f854007882d5
+crate_44734b4051d84aa0aeae7c6dad4d8c3f
+crate_fb9c3b70ceed474bb0e40717a6ad8ec8
+crown_bdeedbaad80e41f19d6a50b17cbe7051
+crown_bee9ec58623442249c2f531e7f313177
+crucifix_178f5f9db1644cbd86a770291b625a81
+cucumber_9231e77e152d4e54b1673eae6686ba0d
+cup_0c770364d18042148f398a0dcc722d9e
+cup_7867aa1e7d7041a3af665f329829a0c1
+cup_848e8db6ec734f06ac3920b58905b176
+cupcake_a11f63180d6f460b928ecfe85506d7b9
+cushion_32684986ac4548978035735edbf63709
+cushion_3c4ba0da6dc0439a9161e2def1635d21
+cushion_eef01b5f8ab14e3d8304bf6b437f2760
+dagger_0eb900e627dd4ddc905477d37b6df0c0
+dagger_3b1d248e9ae443ec9a5d154abe7e238d
+dagger_d0742ee791ad438f89ec1eec06c1f212
+deck_chair_44f7c6fffc0c4061905e4cab73953a56
+deck_chair_f0162201004b4aea8e29b754459d9f75
+deer_01f33919650c421e91666908db8c421e
+desk_1837f10d9b064fd88a607a3d391a17af
+desk_9824a5e58892410c956cfaf9f2b07c29
+dog_85229c525ded401ca3a1456e1f238758
+doll_a62703a137174702ae9de50d5d33524d
+dolphin_08a93ccc711c44d89eac6a845c927b4b
+dolphin_9c2c626c8dbb414eb632cc7923a69474
+dolphin_c9ec32a675ec44c7a5540eb3abfceddc
+doughnut_1e8d2897bdbc4f8fb2b8ed9ab9fac453
+doughnut_3d16c309fcbb4ec488faecb209e4ce2e
+doughnut_e5db252dcdc74bdf81cc4d7be5c03160
+duffel_bag_fad3c3c733f04bf599233bae74921ca6
+dumbbell_33d7aecfa8504b52b4740e684eb0eaca
+dumbbell_9a511d27d3e146189cf85535d010c145
+dumbbell_d01dad33772a42bfb6400291cefcc535
+dumpster_7cce16ad3deb472086c9997e01884115
+dumpster_bed7cc2208ae481f800a1d8516839be5
+dumpster_f80a2a0af6924562be10be7354b7a72f
+elephant_6eb0b6ef28e94f5bad9e4ac795c1d85d
+fan_87b4aecaf25a424a81f76d7c5da5b701
+faucet_13c190d8bd9340759c7c4480feb84c25
+faucet_37c810a063e84b93aa4405de11cd2866
+faucet_6023c6badaa646fb936218f77eb4de11
+file_cabinet_f323dd4bb9f640a4859bd8dd31ec233c
+file_cabinet_f5a20366fbfc4ee686025a5dd374d323
+fire_extinguisher_3bb4f120d0df42fcba3dc4f550aaa9e5
+fire_extinguisher_a390303a1e8e49afa629aa047d6493b1
+fire_extinguisher_ac2076c22a474f5c9b533727966d88e2
+first-aid_kit_38e725fbd2a24183a8f4563b68865e5f
+fish_81d01e6ce8f745778e2629bca80724af
+flashlight_147f57282f7046b09bc540bab1370db0
+flashlight_576daeaa281840cfb3ece4850cc42469
+forklift_99325395edd44438b36ad04cb308a3a0
+frog_0e6df765d30943bd877970b3da1aa90d
+frying_pan_09c0e8587a1148548a85014c34ee76c7
+frying_pan_127e434667c54313b9a9300404f7f8bd
+frying_pan_a3a5af14a6ef47fea2e513140503df1a
+gargoyle_cb31805592fc4a4a99d9a294cbe50694
+globe_f5beb76618cb40c9adcc4b3a40c615a3
+glove_b0c4b928c9ec4c3b997c35d9f7dd31a2
+goldfish_08cc55fc36994e04ad24bf36b9aef6e5
+goose_3784966feebe435b9a1bcd99d17800d9
+guitar_4142c4c8d5b8439eb40f68680f265df9
+guitar_4281970c9fe94a778df26fa6f0c58a96
+guitar_a1ad2734fdf14d0b90e90aea8a6c1dad
+gun_b45efecfd928440b9e7283789e5a9c3d
+hair_dryer_3ed91f860fc6461cbe95361f3b80e1c9
+hair_dryer_8ac03ddde0e349b18766e4dad7edab26
+hairbrush_8a5b6393546844d4913f0888042b90db
+hamburger_488802f3c3ad405f8a180bc2f67f04ce
+hamburger_e9cda9a048e64f9886a7d71d90f466b6
+hammer_1b32c678cb9e4d14805e48e77891c459
+hammer_5bdc836016a3444ea140b34d47fee024
+hammer_79f66456163749c0a8ed733698ca5a16
+hardback_book_0fa0174b26d34275bf09436927d42623
+hardback_book_b52fdceb5c4d4b94a78306ff13ab9872
+helicopter_209c56eb6c36418abafafca259a8b818
+helmet_1d489db9cdc24161a7537926a20bb17b
+helmet_4016930e82234387b4a1fcd3c5bb0c12
+helmet_7b45769ec16e4575b3fdf3f324f1c471
+highchair_925ccdc0b8d94d1f8250ac6faa9a1bae
+hippopotamus_aae1df2e73e141c081c92f64595a7d25
+hockey_stick_3f6b365520474d6c8353b40afece41dd
+hourglass_baafc6537f2c4b6696ff0829cc32f772
+hourglass_bcd15948e8124461bb811e95bf848552
+hummingbird_b1c02672937d4f2ba7124639c0781039
+iPod_6839a82c7c644fe5a99fce0bf11be727
+iPod_95c2cdb3812149c88daf1dc8431d1e05
+iPod_f24b0ed98e8e46f3a8441ebcb6f055f6
+jar_3de9bc73be624f47876d1a34b98813ab
+jar_72d084f7de4c4e599940410963702493
+jeep_33177fb8529643b5a263653e4f706e4d
+jeep_5cd3ea8eb94c4f5597cc086b2df40e58
+jet_plane_804d6814818247978f28d12efcc38cce
+jet_plane_ca46149feec7481289f4a3829c8a536d
+keg_0a3da81bfa904cafa446ab97e7a62cad
+keg_c8208a0a46304cf8a3b78c21dcf2dba7
+keg_d0fc5ee914c64e12a730f751df2a0f34
+kettle_057932f264fe4f84b070fc3d9104fde8
+kettle_0c55bd8e29384070a72c33ef744d11be
+kettle_4b277d86dbde4b538abd74266d0acb73
+key_7dd0e287b9634b9ab07ef7028e9e5e5d
+key_a03f60e8464e494a89a8565d31d57471
+key_d63a3622b7d24be785aee44635750fed
+knife_064fa20765464def90551197e32da7bb
+knife_6c13b2e374784df680276735ad6f1aa5
+knife_ec9c547a71a5441d8a066abed15ab62a
+ladybug_1fc1cabfad294fcd91689426f8b44554
+ladybug_c40bca9926264486be17efa258625b77
+lantern_583a67982908427298dd3e9204bdb4f2
+laptop_computer_9e37ff6c22094e91a81e9e3be1e32b80
+laptop_computer_a5483e74a73143cdb3a453ebd167ce06
+lemon_2a9e10ffd5b0405eaabfe496d61de0bd
+lightbulb_fc7dcd48bbce43c2b0b458a7beaec12d
+lizard_ab30351d594f40fa92ec4e98fec412e5
+machine_gun_a0c58606b1fd434a8db6983cf30c5375
+machine_gun_ee1c36acc61749f787be7e4a694e3b1f
+martini_ca451fe549c148bebe3666ea79f7249c
+matchbox_d6594cf163044fce92e4e8f539257391
+microscope_4530d07e89fd46fcab248e855cf5dc0f
+microscope_d40fdecddc254175996276153ea5ed7d
+microwave_oven_34a92d45ac344761a55b9fc69e0af333
+microwave_oven_59b932c6bf7842d59830e1b45bc9c261
+milk_4b64a7bbfc974893bd3a9c77cd3c9d2b
+milk_4f8003c35c13451eaf176ba3e44de20b
+milk_can_d7fc643e570545fb835e55d810cf597d
+milk_can_ee5edb945f33416a9e63f3b4aa665d56
+milk_e0b6c3a33221476cbb321468586677f9
+minivan_6f2f754c78794734b794237913ba97cc
+minivan_98d85b403ba0426f84636b575319e4f7
+money_49f31b8a421c4da1b9043fc53c9a5eb0
+motorcycle_4caff3c560474f8988a37d7ceed5236d
+muffin_511aa069fb8f4e759de014e569b22a05
+muffin_95c65289eab9470c9b74df95e5dc4b86
+mug_922cd7d18c6748d49fe651ded8a04cf4
+mushroom_0bbf336a2cb2467bb34608e6b38ef3ff
+mushroom_357416df2f5740a183e26c8b4c74a55c
+onion_b110a32f87714dbabc431410e47b9cab
+ottoman_8d23019e11a64894a8cdbb30e36bf1d6
+ottoman_a2f2aef33fb942cc9d72d13df8a8b09f
+ottoman_b3485341f15240279c180685f0e2cb86
+pancake_d96d5cd080e148898199ca775519b593
+pelican_ce594691279644ccb366dce0658ce756
+pen_44b6c784e189434596f126df05b7dfe2
+pen_9e0dba29de734ac4b20060ec873dc36c
+pencil_768e1a7e70ca4badb5cec0705c5a1b7c
+pencil_8b0f41f8b2dc475ca0083f381abc54bd
+pencil_box_160d40d975f94edfa5eb6e6f6a4201ee
+pencil_box_86ccd4717a3e423a98aebcca7fac3b7a
+pencil_fcab4a86262340a4ab7a3d9ea0585f85
+piano_1880032c6a634cf18b6e58e0972d4e90
+pickup_truck_40c94d8b31f94df3bd80348cac8624f1
+pickup_truck_df3578dca7f844ab8b7205a1fbea5ed5
+pie_57396e794e2947c5b29c36c7d4764dc3
+pigeon_901d1a2e9e26465db2432939b35bc384
+piggy_bank_ac418fa936fb448b8eac927ca99bbf30
+pillow_eab682dd4a834a2d8c318cbcfa65cb36
+pistol_dc0d58d286ad4efca1b1d68c278c518f
+pliers_a3a6436253c244cca0c280b9b4026c4b
+polar_bear_5c288986918b429fa5fd04edad5cf60e
+police_cruiser_3fee3d9c85b8468bb18833bf9521a87b
+police_cruiser_f1f9ffc006ce4b9c8661ef9a36951f83
+pot_6b77d17ccf304ebc9e576d1ab9c5f94b
+pretzel_9ce8ab24383c4c93b4c1c7c3848abc52
+pudding_16c2f3b8706f4fd7b64139238f5ab1f8
+pudding_5af966079ae64db9b89dd826ab6b54aa
+pumpkin_4e1a4eb6b9854983b66098d989dfc91a
+pumpkin_94244ddae2a0411fad12da680912b238
+race_car_8dd45092d0d34a398d1c0d8b1591a0f2
+radish_673907bd73384332b426d2dd8cc5edec
+rat_2b92a90c3fdd4460ab3ba2212868cc2f
+rat_ba8557c211ef42cc81aeb1103110c422
+refrigerator_55325e3b09ac48b2ae3803bccf804741
+refrigerator_8e1fddb38fa8400c9fcc784abe29aaaa
+remote_control_35ac912c7dc14175ab8be82a2c5fe551
+remote_control_424f51f77f7c4824a1453d1706f3f914
+remote_control_f1bbc61a42b94ee9a2976ca744f8962e
+rifle_2148cca2447d455d90b2001df1614a7a
+rifle_436c3cc7778d49ada714c4f4df894445
+rifle_6101793f444f40b0b2c238a7b2eb6e78
+rocking_chair_897ce33a65d04bb69eb3d87d0742464f
+rocking_chair_aad16a6c11fd4321b515f3292f45844b
+rocking_chair_db49335b96b94c4da10892f09ff6ee0c
+saltshaker_5ba5959ecc044c5fa44dded4c75ea25a
+saltshaker_c994f981028e4c4187d666e7c2620e4a
+saucepan_057934f97c4042e09a9882543dd5341e
+saucepan_e9bb779c489140518c4a9882636d1c8f
+sausage_5bec36e4ffb1434e8136088a6314bb6c
+sausage_602747b4fe4d435e8a37c7a2e3edce03
+school_bus_cd59a3e9fcea4e3cbb6918c1268a94e3
+screwdriver_0a154cfc51c4417485ddd19637982b33
+screwdriver_4cefe2f12a684cc4bf25c0e9f39b3d16
+screwdriver_82c3c56910be4bc9a1c973ea0c3b66a0
+sewing_machine_4f6c74f9f904439b8554078d1be14821
+shark_19c928e69d3748ea941e6c5537c7502b
+shark_aeb86b5a9233452a841dcf1882f22547
+sheep_67abff7459f34afca11e3effab62c761
+shield_041ee3f9d8ce453dbdc1a696431041c6
+shield_6e6984811b3c4e9ea5fd16e1fa47517e
+shield_f405dd5b3e304f66bb4502467ca7fec2
+shoe_b601649de568470db6e9d8d5c9c76b73
+shopping_bag_c7da540534134560af463fdd29ed209f
+shovel_27e4c28f2ad94fc3bd5dac5a5165e4ab
+shovel_3d90bd005c324876a49a19e694325173
+skateboard_59e9c369ae7148378c496aef09fa7cf1
+skateboard_c60420a840134dc9b4646f43911906d1
+snowman_37d1202f7f45483a88f5890c6daf8885
+snowman_a631ab27f32949e6a8f2ed94d040b9eb
+soccer_ball_3ceae2eee6264843a77aaaf298134744
+soccer_ball_6ef2e4a19ece4c568698e298c925bd3c
+sofa_a0d66f10a850469c9cb04c3cecc62a05
+sofa_bed_261076b1e9e94223bfb59a0d5577dd82
+sofa_ef3832963ab24d129ec88fd4cac4818f
+sofa_f8def3c5f656454c935fe3d626ed9fab
+space_shuttle_2a9c2b23a4124fc29f62bb1ae2e522f6
+space_shuttle_430a040458ad4db5b4fcde4c7db15e1a
+space_shuttle_892969a88e71495d9e869f96c95f0abf
+spider_6890f5b34af947f4b416a23cbd4e56c0
+stool_8ab0baf0f68f42788285e4f952c454ba
+stool_b221ad482e084c449408c229cab380d6
+suitcase_d622ab7c84f341628b6dd516ce39ccad
+suitcase_fb509f0edeae4f75ab4368a8133f4ccc
+sunflower_3e38e8351c6e48e786cdd8bd181a09db
+sunflower_589a1058cb424781b4970a469bf4f538
+sunhat_3598d9e686ad46dc838e1443b910d91e
+sunhat_f7bbf5d03a604452916d5c0cc85c867c
+sushi_5ee3c671e6014f04ba3971c243acdfb9
+sword_814a3d5f916e4439aa4bac2aa7b812ec
+sword_ac1ceaf3568c4f7ca335851279f922fc
+sword_ae3dcd8addb54abbb4c3b520571f1909
+syringe_324b3ed0026940808db353c8c6d7450e
+syringe_7c0620856f0444cf8e9bbcd8670b6247
+table_4d7f3c58a09c4a899e68ad837edd2b6b
+table_77ec465b45574d12bf527a26ece473e8
+table_lamp_2fd7954d31dc47d7a48f9e0cb8faeeba
+table_lamp_346d74713027437992db6afabb768694
+teacup_49d0b382def54ff1b544cc6293ea1b22
+teacup_edbb7502a3f54d638f7b66aaf3716b80
+teakettle_73d7b6f9a0b7410b945205338b090566
+teakettle_d3307264b4b14e079ba5c861eeac839e
+teapot_56dde1d5fdb44867b5a48e232cd95b2f
+teddy_bear_f6a6667cd63240639a4ea9598ca4d8fc
+telephone_b812224a5c354de5854c82547e1dc4ca
+telephone_bc379c569b8e4c34a1f9e64e626fe66c
+television_set_6099a956fb4c4a21b2957bc2e4874d55
+television_set_80a0f58dcb604405869637c8387f5d36
+toilet_1207c326615c43a78e9944c33ba401a5
+toilet_531e32a371004849bd72a507aaf81643
+toilet_60e93498c4ca47d48af8b7c60e0916c2
+toothbrush_2f4bd3002b2e456c99abee54b488967d
+toothbrush_8be42d538a6543a0981e3e48b11410fe
+trailer_truck_64d88784946d4172b9e8acd3b4154f8b
+trailer_truck_8cd40f962f2c440c9caf1db1a505357f
+trailer_truck_cbc508a5ad424d79b2f2c8a3de7e1cd3
+trash_can_269cc79ce7ca4dcf88030e7b7151dc36
+trash_can_e5e0f42aec4846a0bff905d0601fdd1e
+tricycle_158d45e79a9b449fbff24ddb7b36446d
+truck_4cb3b3029ed142cc9291e83e93a293a0
+truck_9e3400f575a541b88417e85f766fc773
+typewriter_0b6766c2df0e4901b8c387283d544027
+typewriter_22536ec10cc2462db661e5279d83ab7e
+umbrella_54daa7a355d64f29a82695adc2ac1918
+urn_77db9590a6314582ac9504e785449785
+videotape_29642e0a9cad4275ac78c1d4f12660d6
+violin_52d850660e1d4358ad96b922ea75f62c
+watch_a9ca3807f0f54df689bb6e77b732bc84
+watch_e3a78e329e7d4050a1c9d1c0bd19e47f
+water_cooler_d345524901c7482393c2c93560f2ed90
+water_faucet_5b8d5bb5ecdd4d8a80f71eabd4d08249
+water_faucet_69de7b6bd3004eba8c6aa41d37858d86
+watermelon_83f6af2628494e0384a995fcc7815240
+watermelon_d9c7f3d06d2a4e4eae0fd0cfca9870aa
+windmill_30deb775546f4059905c687933a32d1f
+wrench_0ac105eb165c40aba9dab37c0615bb17
+wrench_412fdac55c8649a89992dd52ac4d9e19
+wrench_a0fe4b9d7d324267b975f30bbfa3a81e
+zucchini_457cf1ce9c254830b59fc113371e5820
diff --git a/requirements.txt b/requirements.txt
index c5e3852..a94121e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,4 +11,7 @@ gradio
pytorch-lightning==1.9.1
omegaconf
triton
-accelerate
\ No newline at end of file
+accelerate
+objaverse
+mathutils
+iopath==0.1.10
\ No newline at end of file
diff --git a/scripts/blender_process_glb.py b/scripts/blender_process_glb.py
new file mode 100644
index 0000000..3f314fe
--- /dev/null
+++ b/scripts/blender_process_glb.py
@@ -0,0 +1,67 @@
+"""
+ Script of pre-processing GLB meshes via Blender
+ NOTE: Blender must be installed first!
+
+ Utils:
+ `
+ blender --background --factory-startup \
+ --python scripts/blender_process_glb.py -- \
+ \
+
+ `
+
+"""
+
+import sys
+import pathlib
+
+import numpy as np
+from mathutils import Vector, Matrix
+
+try:
+ import bpy
+except ImportError:
+ print("=> Please install Blender and add it to the PATH")
+
+def normalize(vector):
+ return vector / (np.linalg.norm(vector) + 1e-8)
+
+
+def center_and_rescale():
+ all_verts = []
+ for object in bpy.context.scene.objects:
+ if object.name not in ["Camera", "Light"] and object.data is not None:
+ vertices = object.data.vertices
+ verts = [object.matrix_world @ vert.co for vert in vertices]
+ np_verts = np.array([vert.to_tuple() for vert in verts])
+ all_verts.append(np_verts)
+
+ all_verts = np.concatenate(all_verts, axis=0)
+ mean_position = (all_verts.max(axis=0) + all_verts.min(axis=0)) / 2
+ bounds = all_verts.max(axis=0) - all_verts.min(axis=0)
+ scale_factor = 1 / bounds.max()
+
+ for object in bpy.context.scene.objects:
+ if object.name not in ["Camera", "Light"] and object.data is not None:
+ for vert in object.data.vertices:
+ non_inverted_new_position = (object.matrix_world @ vert.co - Vector((mean_position[0], mean_position[1], mean_position[2])))
+ non_inverted_new_position = Vector((scale_factor, scale_factor, scale_factor)) * non_inverted_new_position
+ new_position = object.matrix_world.inverted() @ non_inverted_new_position
+ vert.co = new_position
+
+bpy.data.objects['Cube'].select_set(True)
+bpy.ops.object.delete()
+bpy.data.objects['Light'].select_set(True)
+bpy.ops.object.delete()
+
+sys.argv = sys.argv[sys.argv.index("--python") + 2:]
+path_to_glb = pathlib.Path(sys.argv[1])
+obj_dir = pathlib.Path(sys.argv[2])
+
+print("=> Loading and preprocessing objects")
+bpy.ops.import_scene.gltf(filepath=str(path_to_glb))
+center_and_rescale()
+
+output_dir = obj_dir / path_to_glb.stem
+output_dir.mkdir(exist_ok=True)
+bpy.ops.export_scene.obj(filepath=str(output_dir / "mesh.obj"))
diff --git a/scripts/download_objaverse_subset.py b/scripts/download_objaverse_subset.py
new file mode 100644
index 0000000..d18b124
--- /dev/null
+++ b/scripts/download_objaverse_subset.py
@@ -0,0 +1,151 @@
+import os
+import sys
+import objaverse
+import subprocess
+import xatlas
+import trimesh
+
+from PIL import Image
+from pathlib import Path
+from tqdm import tqdm
+
+# torch
+import torch
+
+from torchvision import transforms
+
+# pytorch3d
+from pytorch3d.io import (
+ load_obj,
+ save_obj
+)
+
+# customized
+sys.path.append(".")
+from scripts.parameterize_mesh import parameterize_mesh
+
+SUBSET = "./data/objaverse_subset.txt"
+DATA_DIR = "./data/objaverse"
+
+# Setup
+if torch.cuda.is_available():
+ DEVICE = torch.device("cuda:0")
+ torch.cuda.set_device(DEVICE)
+else:
+ DEVICE = torch.device("cpu")
+
+os.makedirs(DATA_DIR, exist_ok=True)
+
+def get_objaverse_subset():
+ with open(SUBSET) as f:
+ ids = [l.rstrip().split("_")[-1] for l in f.readlines()]
+
+ return ids
+
+def adjust_uv_map(faces, aux, device=DEVICE):
+ """
+ adjust UV map to be compatiable with multiple textures.
+ UVs for different materials will be decomposed and placed horizontally
+
+ +-----+-----+-----+--
+ | 1 | 2 | 3 |
+ +-----+-----+-----+--
+
+ """
+
+ textures_ids = faces.textures_idx
+ materials_idx = faces.materials_idx
+ verts_uvs = aux.verts_uvs
+
+ num_materials = torch.unique(materials_idx).shape[0]
+
+ try:
+ new_verts_uvs = verts_uvs.clone()
+
+ # HACK map verts_uvs to 0 and 1
+ new_verts_uvs[new_verts_uvs != 1] %= 1
+
+ for material_id in range(num_materials):
+ # apply offsets to horizontal axis
+ faces_ids = textures_ids[materials_idx == material_id].unique()
+ new_verts_uvs[faces_ids, 0] += material_id
+
+ new_verts_uvs[:, 0] /= num_materials
+ new_faces_uvs = faces.textures_idx
+ except AttributeError:
+ new_verts_uvs = torch.tensor([
+ [0, 0],
+ [0, 1],
+ [1, 0]
+ ]).to(device)
+
+ num_faces = faces.verts_idx.shape[0]
+ new_faces_uvs = torch.tensor([[0, 1, 2]]).to(device).long()
+ new_faces_uvs = new_faces_uvs.repeat(num_faces, 1)
+
+ return new_verts_uvs, new_faces_uvs
+
+def load_and_adjust_mesh(mesh_path, device=DEVICE):
+ verts, faces, aux = load_obj(mesh_path, device=device)
+
+ dummy_texture = Image.open("./samples/textures/white.png").convert("RGB").resize((512, 512))
+
+ # collapse textures of multiple materials to one texture map
+ new_verts_uvs, new_faces_uvs = adjust_uv_map(faces, aux)
+
+ return verts, faces, new_verts_uvs, new_faces_uvs, dummy_texture
+
+def collapse_objects(input_path, output_path, device=DEVICE, inplace=False):
+ verts, faces, new_verts_uvs, new_faces_uvs, dummy_texture = load_and_adjust_mesh(input_path)
+ output_path = input_path if inplace else output_path
+ os.makedirs(output_path.parent, exist_ok=True)
+
+ texture_map = transforms.ToTensor()(dummy_texture).to(device)
+ texture_map = texture_map.permute(1, 2, 0)
+
+ save_obj(
+ str(output_path),
+ verts=verts,
+ faces=faces.verts_idx,
+ decimal_places=5,
+ verts_uvs=new_verts_uvs,
+ faces_uvs=new_faces_uvs,
+ texture_map=texture_map
+ )
+
+def remove_tails(mtl_path):
+ with open(mtl_path) as f:
+ mtl_data = [l.rstrip() for l in f.readlines()]
+
+ with open(mtl_path, "w") as f:
+ for l in mtl_data:
+ if "map_Bump" not in l and "map_Kd" not in l:
+ f.write(l+'\n')
+
+if __name__ == "__main__":
+ objaverse_subset = get_objaverse_subset()
+
+ # cache objects to ~/.objaverse/
+ objects = objaverse.load_objects(objaverse_subset)
+
+ print("=> processing...")
+ for key, value in tqdm(objects.items()):
+ # convert glb to obj
+ cmd = [
+ "blender", # NOTE please make sure you installed blender
+ "--background", "--factory-startup", "--python", "scripts/blender_process_glb.py", "--",
+ str(value),
+ DATA_DIR
+ ]
+ _ = subprocess.call(cmd, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
+
+ output_dir = Path(DATA_DIR) / str(Path(value).stem)
+
+ obj_path = output_dir / "mesh.obj"
+ mtl_path = output_dir / "mesh.mtl"
+
+ remove_tails(mtl_path)
+ collapse_objects(obj_path, obj_path, DEVICE, inplace=True)
+ parameterize_mesh(obj_path, obj_path) # xatlas produces great UVs
+
+ print("=> done!")
\ No newline at end of file
diff --git a/scripts/parameterize_mesh.py b/scripts/parameterize_mesh.py
new file mode 100644
index 0000000..093a675
--- /dev/null
+++ b/scripts/parameterize_mesh.py
@@ -0,0 +1,20 @@
+import xatlas
+import trimesh
+import argparse
+
+def parameterize_mesh(input_path, output_path):
+ # parameterize the mesh
+ mesh = trimesh.load_mesh(input_path, force='mesh')
+ vertices, faces = mesh.vertices, mesh.faces
+
+ vmapping, indices, uvs = xatlas.parametrize(vertices, faces)
+ xatlas.export(str(output_path), vertices[vmapping], indices, uvs)
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--input_path", type=str, required=True)
+ parser.add_argument("--output_path", type=str, required=True)
+ args = parser.parse_args()
+
+ parameterize_mesh(args.input_path, args.output_path)
+
\ No newline at end of file