Compare commits
890 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2758acfd42 | |||
| 54c3031d74 | |||
| 9a9c7856b3 | |||
| 401b2fb524 | |||
| 0a0a2da680 | |||
| e4df76d986 | |||
| 79028f1627 | |||
| d87e5cb809 | |||
| 3484334d15 | |||
| 9ab6571b3f | |||
| dad5600e7e | |||
| ee56d58173 | |||
| 9f8f2a2449 | |||
| f591534a0f | |||
| 7a2e0c6632 | |||
| 29519c5fda | |||
| 4b996f6bbe | |||
| e4a5bfc788 | |||
| 4c58397949 | |||
| 011b4027db | |||
| a1adc59cb8 | |||
| ee4a8fc05a | |||
| 420a3ce498 | |||
| 9b6798c479 | |||
| 765816ccb1 | |||
| f3e9e3497b | |||
| 8e9e1a618b | |||
| 7272020cd3 | |||
| 16fff71c31 | |||
| 190223949c | |||
| 38d463ae49 | |||
| 73193196d2 | |||
| 2975e85950 | |||
| b2fbf982a8 | |||
| 0843fbf904 | |||
| 8dab9041e4 | |||
| 6aed98f795 | |||
| c20a76f3e2 | |||
| 435b1720c3 | |||
| 22bdf37fc2 | |||
| 9e3ac0eafb | |||
| 5c1c24cdab | |||
| c9cc824761 | |||
| b3c1e0330a | |||
| 4506fb2022 | |||
| ecec324121 | |||
| 959b33c59b | |||
| d6646c34ef | |||
| b56ac54cb2 | |||
| 5bc47a0c3b | |||
| f2db83008a | |||
| 9a01cf1b35 | |||
| 0f6f30b26e | |||
| 8219334806 | |||
| e6997d87b3 | |||
| 13b453c21e | |||
| 4ec3f18fda | |||
| fc8ffd8421 | |||
| 4551651777 | |||
| 82f2e8c344 | |||
| b76c5c9433 | |||
| 1737927814 | |||
| 38d7ac6d9c | |||
| db1bf4351b | |||
| 2d491f9cbd | |||
| a58d0f8a67 | |||
| 42cd6ca4ca | |||
| f292f1628b | |||
| 20909d4948 | |||
| 1f6ff4a519 | |||
| 07568f87c3 | |||
| 267e510071 | |||
| 73b921d591 | |||
| 8677035989 | |||
| a179893d70 | |||
| 540fb91d34 | |||
| 591a07d2d9 | |||
| f607e913d5 | |||
| 3d57de91e8 | |||
| 9fbceaa458 | |||
| 281180512f | |||
| 50fa1937f9 | |||
| d79aee3f78 | |||
| f599185e2d | |||
| fd79c7ae46 | |||
| 9de0846f3e | |||
| f168ece461 | |||
| 4100650ce1 | |||
| 87bb437fd3 | |||
| 626c671448 | |||
| b532c4a2b8 | |||
| 276cb7590d | |||
| f66aae2213 | |||
| 17c4e21f34 | |||
| 3613bca5ea | |||
| eff9c46e59 | |||
| c186a42a54 | |||
| 676d35f559 | |||
| e8bc4632b4 | |||
| 222158e954 | |||
| dde87b2f45 | |||
| 789284f519 | |||
| 19576ae167 | |||
| be8fe7bdd6 | |||
| d7a6a2cc71 | |||
| 7eea344f91 | |||
| 2bd0b67591 | |||
| d9307a174d | |||
| 59c5b30f3f | |||
| 938859f10a | |||
| a9b53d94e8 | |||
| a33e2ed9b1 | |||
| 7687ca2080 | |||
| 2a1a6e8cbe | |||
| 45fa9e8448 | |||
| 0ca66d1af3 | |||
| 63baa69342 | |||
| 894291faba | |||
| 51708bab49 | |||
| 4497a754fb | |||
| 6223e7475c | |||
| bf97378168 | |||
| 5a6f291c72 | |||
| 3404f4e86b | |||
| 6c07ebe5f2 | |||
| 24a4f06013 | |||
| 73bf4cbce7 | |||
| 67c8071bf4 | |||
| 9b163cb444 | |||
| 83d6a77617 | |||
| e5e174a20e | |||
| 8aede85214 | |||
| c625b9e3cc | |||
| 222d44a8d8 | |||
| 386f827d38 | |||
| 831c51c875 | |||
| 2d25d37112 | |||
| a3172d643f | |||
| 02787784a4 | |||
| 967f390aec | |||
| 89951b01ff | |||
| ca8f026bc3 | |||
| 4c14d7ef5a | |||
| 8234c20e28 | |||
| 52e272954f | |||
| 77caf50265 | |||
| 2ab8751fd4 | |||
| 54589c0828 | |||
| 1fdb247167 | |||
| 49cc47afd1 | |||
| 673677c831 | |||
| c30dc04571 | |||
| f58de79ceb | |||
| 8d9bb7a63e | |||
| 18490162f7 | |||
| bf71a4e012 | |||
| d29edf6381 | |||
| b087b7743e | |||
| 8ee1a7f67f | |||
| 475385d876 | |||
| 1b967a07e5 | |||
| 1088d613d5 | |||
| 1b2d4d6522 | |||
| 0fd1214dea | |||
| 00547b7aac | |||
| 621bfe36a8 | |||
| c1849f7e00 | |||
| b23db7c4cb | |||
| b3525bc642 | |||
| 589951eaea | |||
| 74adbbcc5d | |||
| bab61dd249 | |||
| 5c3bcb09fa | |||
| f0b94dd0d4 | |||
| ba5ab99a03 | |||
| 9bc3028eb7 | |||
| 5ef9db6d67 | |||
| 86a710e175 | |||
| 1797a9c61a | |||
| fd49bc5d8d | |||
| de4c6c6fab | |||
| 78a7dd3269 | |||
| 0cf53da0fe | |||
| 13b8708e58 | |||
| b6d91bd28a | |||
| 5bdc78e3ba | |||
| bce8fb31ab | |||
| 77d7d21130 | |||
| fed1520a8e | |||
| 284d5861dd | |||
| ee6154c842 | |||
| 709197c294 | |||
| fd55b7b4ed | |||
| 5bca5e2d77 | |||
| ee96937fd4 | |||
| a370d69542 | |||
| 24aad2eed4 | |||
| 910605cc7d | |||
| 7194e25bba | |||
| 7f287cb8f9 | |||
| a0ce1491d9 | |||
| 26035d23fe | |||
| 835debe75e | |||
| b482deb8b0 | |||
| 76fd1e6f5a | |||
| abb45fbe45 | |||
| 567ce48cc1 | |||
| 56a17b4e68 | |||
| c027e72439 | |||
| 25b8da8e3b | |||
| 5b47d1a910 | |||
| a844c3043c | |||
| e099a82d15 | |||
| b681af4556 | |||
| 78d66a9ac3 | |||
| bfe4d9f3f4 | |||
| a02ee3719c | |||
| 542f713678 | |||
| 2395c6fdaa | |||
| c7f02d5e51 | |||
| 55a726e933 | |||
| 601633347c | |||
| 182973c0ee | |||
| a16e9ac76a | |||
| 66f70e5da6 | |||
| 5a187c6ca8 | |||
| c6042100f9 | |||
| fde7ae4d19 | |||
| e37e13e700 | |||
| d22003578e | |||
| 52139cf0c4 | |||
| 37b723d8ae | |||
| aec3649524 | |||
| 36d716bb50 | |||
| f61c692929 | |||
| 3f717f3baf | |||
| ffc95090aa | |||
| 2eaa9236f2 | |||
| e4bab37b62 | |||
| 105c9c71ee | |||
| e135229ca6 | |||
| 97dea6ede5 | |||
| d871a92d1c | |||
| a152aa125b | |||
| 4e217d4028 | |||
| e5da7a4606 | |||
| faace3090c | |||
| d3e2345f94 | |||
| a3e087ab51 | |||
| 3a614a8ea1 | |||
| 9cb60dcdf5 | |||
| af6db68816 | |||
| 305ed0b65a | |||
| 263efb41e8 | |||
| d6312c7b92 | |||
| b31af4891d | |||
| 0ba08f57f2 | |||
| a2d7881afe | |||
| d79e598bf8 | |||
| a6a39cb842 | |||
| 5d0883c0e4 | |||
| e6d49424cf | |||
| 72abcd5991 | |||
| 9c2bb85858 | |||
| e9b059ee94 | |||
| 7a913844e2 | |||
| f8be7e1f57 | |||
| d5c43c4675 | |||
| 85fa6d8025 | |||
| 6b2a8f54a1 | |||
| bd1fb845b1 | |||
| 9c64c9af5d | |||
| 1057eceb2f | |||
| 445bc75319 | |||
| 4fb7ee02cd | |||
| ad11b7ebd0 | |||
| 5d9bda6f97 | |||
| 54be07c17d | |||
| 2c7ab3a28e | |||
| 3cc3c1bbd3 | |||
| ddedf2e046 | |||
| a60c339f85 | |||
| ce2c5d6528 | |||
| fd81f70355 | |||
| 100bb7c6ca | |||
| 1ffcedd9d4 | |||
| fc1f713106 | |||
| 83c3a78e6d | |||
| e6a3e7024d | |||
| d62fde0d79 | |||
| a70cf464d6 | |||
| 546260348d | |||
| 693aec949c | |||
| 5c7ac1bb7e | |||
| 8862752523 | |||
| 201c380925 | |||
| c7230a6f77 | |||
| 6b78fdf822 | |||
| 3cb326e426 | |||
| d3f9332372 | |||
| be0f6a6af2 | |||
| 25aa233cef | |||
| 5fdc424202 | |||
| 9b74bb5c92 | |||
| 8bf8a649c8 | |||
| 7ba8d8b608 | |||
| e35328fece | |||
| 366d4d7b0b | |||
| 3af1e75084 | |||
| dabd80fe4c | |||
| cb711a648f | |||
| 5b58dbc980 | |||
| 8b3c0a941c | |||
| 3ce29a3d7e | |||
| dc3c6b2f39 | |||
| 1cbee4c504 | |||
| 798e4c288a | |||
| ac39e32bc9 | |||
| 52da7f931b | |||
| fcb6f814de | |||
| 9e6b56d783 | |||
| 923dad6ca8 | |||
| 9f17d91b32 | |||
| 2bcb04a3b1 | |||
| a530b600b8 | |||
| d494a2bee2 | |||
| 6a027662ae | |||
| 577bb7bf31 | |||
| df664bd55f | |||
| 8a2705f81f | |||
| fcaf11422a | |||
| 3444409554 | |||
| 683c01b301 | |||
| e2492f773d | |||
| 1f3a2dcd1d | |||
| 4205cb32c5 | |||
| 6ab9bdb346 | |||
| a4aec1919c | |||
| 5b97d70d57 | |||
| eeeb4596c3 | |||
| 23853cae14 | |||
| 87f6f33b37 | |||
| 8c03d1bdde | |||
| 7f1c7d808d | |||
| be12aece5b | |||
| d7605f1449 | |||
| ef80642dec | |||
| a5622c93d4 | |||
| b6f9bfe9a5 | |||
| 79954657e2 | |||
| 35d3f1f72a | |||
| 388d74faf4 | |||
| 0f8747e194 | |||
| 93f16ba9e3 | |||
| bea2d42e8c | |||
| 68d644fd28 | |||
| f6e33450ff | |||
| 65008c5c0b | |||
| dbfaf568fc | |||
| 58fd6ac03e | |||
| 1e64524afb | |||
| 20a5d8effd | |||
| 8c7e0bcb0a | |||
| c69080f11e | |||
| 5a48c800ee | |||
| c6eff4d373 | |||
| 5c056c2a3e | |||
| 61f593f350 | |||
| 6cc7dc7aaa | |||
| 239f040a98 | |||
| 3827c16fde | |||
| e299343807 | |||
| 4130ce2b93 | |||
| d6acb64514 | |||
| 8e233e2591 | |||
| 9cda16220e | |||
| 36acadbd52 | |||
| 37b6552c42 | |||
| 1903052d79 | |||
| 2b4cfd9a60 | |||
| decbb65f09 | |||
| 8e2ca37edc | |||
| 8fb6bcc8b1 | |||
| 2f36c670ff | |||
| d701c3a480 | |||
| cd7f3375b2 | |||
| 46cd185524 | |||
| e04d82e940 | |||
| 26d0863921 | |||
| 37f23fa537 | |||
| 167d408b5e | |||
| d4a8ff4872 | |||
| fb9b12a982 | |||
| 88a03f1a1d | |||
| ba7e400e13 | |||
| 57f0f88552 | |||
| 42a0cf6283 | |||
| b67acd5ea1 | |||
| 5e2721d2f5 | |||
| 2cd43aee0a | |||
| fb1570d290 | |||
| 79972ad4db | |||
| 61934c285c | |||
| a7d554971c | |||
| e54ea90607 | |||
| fda403a079 | |||
| f2e75c96be | |||
| 322eb2b8a8 | |||
| 6f71183d0e | |||
| 5d852cf6ae | |||
| 2d1ea1618b | |||
| 50723d07a6 | |||
| 1161562bc8 | |||
| 0c8b3aaced | |||
| b81b7decf6 | |||
| e5463330ef | |||
| 17c0b3e460 | |||
| 3bc3193805 | |||
| d6db6dedca | |||
| d931bc72c7 | |||
| 6506f77689 | |||
| 0d64b38dbc | |||
| 7856061cf0 | |||
| 0210e414d2 | |||
| 41231e8ae2 | |||
| ba2e34682e | |||
| b234ff9234 | |||
| 3442cc3d1a | |||
| e618e34c94 | |||
| 105c3b0a4c | |||
| 69d0446019 | |||
| 078045f73b | |||
| 78af1daa2e | |||
| 0bd0d57a81 | |||
| 9dd5b6ce37 | |||
| d862cdaa72 | |||
| 4f57de9688 | |||
| 92b6e05909 | |||
| 2bd0bae2f7 | |||
| 69b5d24f28 | |||
| e5dcb9d9da | |||
| 4db8638f7e | |||
| cec885daf9 | |||
| 90fbf27114 | |||
| f1436cec9b | |||
| cf968cb6b5 | |||
| 2278f40051 | |||
| 18a76d3a87 | |||
| 6a65461ec7 | |||
| a5a0a7c4f3 | |||
| f1e6f8042c | |||
| 848873d87e | |||
| 75bb864237 | |||
| d5275b16aa | |||
| 15d1b6cef0 | |||
| 6d4dd3e17a | |||
| 649c22a34e | |||
| 8d04d39036 | |||
| 0e90c719b0 | |||
| a79526cad8 | |||
| d05d8b6100 | |||
| 9856867954 | |||
| 19064b680e | |||
| 95265c765b | |||
| 1ed8912f57 | |||
| 82a0eb4413 | |||
| be7215402b | |||
| 4500b064d8 | |||
| 93d191d7c9 | |||
| 1607ceaf3e | |||
| 5b24ea9dd9 | |||
| c879dcaf7d | |||
| 86691dabbf | |||
| fe71a66bb9 | |||
| 80e0d848f2 | |||
| 8b3a2984bf | |||
| fccce265aa | |||
| a43a228f78 | |||
| dd8610fd5c | |||
| b991beb712 | |||
| 25f6483488 | |||
| efc0325e14 | |||
| d19ec021fe | |||
| b34a307936 | |||
| fb565caf7b | |||
| 6796e8fff6 | |||
| 213547f545 | |||
| 73851e962b | |||
| de22204514 | |||
| ebba15fe67 | |||
| c1cd3339fa | |||
| 713a296a59 | |||
| 06bde527d5 | |||
| dcd31f5701 | |||
| 65f2af5849 | |||
| 2dd7a8637c | |||
| 211d056728 | |||
| dc0aed5b16 | |||
| 5064df4ba2 | |||
| 469c31da97 | |||
| 5fb41e6ecc | |||
| a68a442bbb | |||
| 84db5644d6 | |||
| fc1fb7a590 | |||
| dc91d4eca8 | |||
| f6a42a36d6 | |||
| 2a769dc0b0 | |||
| 3475bfb2aa | |||
| f9f8fade89 | |||
| e404fb772b | |||
| 2a9412042c | |||
| e8ab661504 | |||
| 3f91db25d4 | |||
| 300381ba4d | |||
| 4363e6a213 | |||
| 450dac4b1e | |||
| 278127fe29 | |||
| 23d71de75f | |||
| d86789898d | |||
| c3dc1f65d4 | |||
| 238fb00727 | |||
| 2d48c81d58 | |||
| 0893e0043f | |||
| 72c0267fe6 | |||
| c9956def36 | |||
| 5d60fe6812 | |||
| 6051dfae30 | |||
| 3518153d5b | |||
| cf949609b2 | |||
| d482a8805c | |||
| 161dc9ce7e | |||
| 090073cc3b | |||
| 6ae718e4d6 | |||
| 783b1cb611 | |||
| 4b01f80e8d | |||
| c8278f377b | |||
| d34b664933 | |||
| c8f40e1d26 | |||
| 185a8d7582 | |||
| 8373e91a1b | |||
| 6aeedfb70c | |||
| e7f3851212 | |||
| 7df05ade4c | |||
| 24b032ce5b | |||
| b6fe4ff637 | |||
| 8f1aa28b37 | |||
| 55c1e22a67 | |||
| ca0d4511a9 | |||
| b56855c542 | |||
| 72e8eb3b94 | |||
| 281a1cdc2c | |||
| 3c8f901a1f | |||
| e0589d2908 | |||
| dfd53976d4 | |||
| 02d43be93c | |||
| 2e8bceb676 | |||
| 16f9e697ab | |||
| 269f88ee28 | |||
| f11d950448 | |||
| 6ba2c44e88 | |||
| d1ed4665de | |||
| 5b68cfa018 | |||
| 85f88b6b05 | |||
| ea467441d2 | |||
| 40ba502853 | |||
| 09d7d0f1bc | |||
| 3418d53a6d | |||
| d5440d60ab | |||
| 2ba237ec12 | |||
| 01a343f28e | |||
| 85220591e2 | |||
| ecadc8bbba | |||
| 26c92eaf0f | |||
| d129abb9c9 | |||
| 3b98b00d6f | |||
| ce329e13fb | |||
| be9cd98cb1 | |||
| 216acd98d6 | |||
| 10fd8a59b2 | |||
| 3974c6fd89 | |||
| f82962e42c | |||
| bf1ced4184 | |||
| cabfcbc73c | |||
| 574473c480 | |||
| 17143fd53f | |||
| b8fff99e68 | |||
| 3b038feae0 | |||
| 032bda223e | |||
| b16d4d18e0 | |||
| df3a57dcda | |||
| 3bf7ab910f | |||
| e8ce0ba6ef | |||
| d8fff5c820 | |||
| aa9897d932 | |||
| f265a52c96 | |||
| f214cfae12 | |||
| febc8cd6aa | |||
| 463e061740 | |||
| d80759efb8 | |||
| 1d66aad4df | |||
| f5284ced54 | |||
| c951ca6f47 | |||
| f25ae373bb | |||
| 845833e8fd | |||
| f0ac61a8fd | |||
| 8f7278e34f | |||
| b124599de3 | |||
| 697234dd51 | |||
| ba97494d6f | |||
| 1996fba8a6 | |||
| a6bbe907ee | |||
| 43579f4c02 | |||
| 909a25c147 | |||
| aa3aafc4ff | |||
| b32439a694 | |||
| ddbc25077c | |||
| b075886b19 | |||
| eae999a85a | |||
| 77f0799750 | |||
| 8de93ad8b4 | |||
| b377b5bbed | |||
| 75b5324762 | |||
| 610d200e8a | |||
| 8002692f3e | |||
| 9496b57b01 | |||
| a5cd5844ec | |||
| da16b479a0 | |||
| 44f1059000 | |||
| cf4b41f7d9 | |||
| a84ca5b147 | |||
| 71f5f96e64 | |||
| 2aa8e444ee | |||
| cfa187f477 | |||
| 1ed411e431 | |||
| 9233ae97d0 | |||
| 0ee38653f7 | |||
| df89b5bf8a | |||
| cca4037fec | |||
| e015da8d95 | |||
| 4ceb186251 | |||
| 370109b868 | |||
| 3b3165ad51 | |||
| 98e68cd66a | |||
| 407301a28c | |||
| 5ce0e7265b | |||
| f1704fd61a | |||
| 35e87128f5 | |||
| dd93f89931 | |||
| fb85612f81 | |||
| 966173c129 | |||
| 55757039fa | |||
| 1113e18c40 | |||
| 02947345e8 | |||
| 63f18f0b03 | |||
| cd6da987cc | |||
| 006d7ddd31 | |||
| 81842fc9d0 | |||
| ec9e0b2086 | |||
| 64b71644bb | |||
| 1e58b09d96 | |||
| 455136ee50 | |||
| 1058ba6a0f | |||
| f8c541c0d7 | |||
| b485e78030 | |||
| d8e7892081 | |||
| 1638c3b1c2 | |||
| 2d0e92d412 | |||
| f1a43f4977 | |||
| 18f7d0129a | |||
| 356ccd0314 | |||
| 4adf89b40b | |||
| eb4aded5d6 | |||
| 5230f45658 | |||
| b4e70e56a6 | |||
| cb3edf2607 | |||
| 720b26d11e | |||
| e35be13b23 | |||
| ba19d93df9 | |||
| 5d1dcb4387 | |||
| f101934909 | |||
| ede2575018 | |||
| fb80ee5a0e | |||
| 44fc69398c | |||
| c162337cab | |||
| 821faaf3c0 | |||
| bf85eb9b4e | |||
| 691c6614a8 | |||
| 6db7cb8937 | |||
| 6afc572eae | |||
| 2a932a2176 | |||
| b2bcde1bfc | |||
| ec6fd23636 | |||
| 6f34f95c52 | |||
| 94e5b36279 | |||
| f0ce4d6336 | |||
| d06b42b917 | |||
| 764986a9b0 | |||
| c4efa95b4a | |||
| 5a655779d7 | |||
| 0403437ad0 | |||
| b62f94f5c2 | |||
| daf09ed9fe | |||
| 72794f1416 | |||
| b00e20b23f | |||
| e99a2181ff | |||
| 65b38e8dcf | |||
| 9b8780a2fd | |||
| 9c0e4cae74 | |||
| deb387f54c | |||
| 5d5422b4c5 | |||
| 85b8dd8b34 | |||
| b93d34dff4 | |||
| e997a7db9a | |||
| d1a065119e | |||
| 1dab468e20 | |||
| c5cd0c73a3 | |||
| ae139403e4 | |||
| d3c9154f9a | |||
| caba60968a | |||
| 2e0def8670 | |||
| 8c3d16a395 | |||
| 3f48531da7 | |||
| 128cdca068 | |||
| bd997a3900 | |||
| 8e93eda449 | |||
| a6674ecd56 | |||
| 654651856f | |||
| c489659a20 | |||
| 18377e0c9f | |||
| cebba6c0b9 | |||
| 89f9bf545d | |||
| 055d36abd7 | |||
| 7bafc5fa8b | |||
| 6946c0bedb | |||
| bb40f86daa | |||
| 89d198659c | |||
| c56e540e5d | |||
| d3fd74246f | |||
| 616061a6ca | |||
| d94b8b9c0e | |||
| 89d39cf8ff | |||
| 0ba130dbd3 | |||
| 434935613c | |||
| 454585d3d2 | |||
| 65a6e341ad | |||
| fc933034db | |||
| 20c8b094d6 | |||
| 552ddfbdfa | |||
| 9743eec3ab | |||
| b3ad1dc26e | |||
| b6c9d4a88c | |||
| 25b6ac61cb | |||
| 9c9252e8a3 | |||
| 3a744ad72f | |||
| 554e2a4bce | |||
| 6e8979d8d8 | |||
| 583d416640 | |||
| 03b50b4f85 | |||
| 440e135e3a | |||
| ab39f06003 | |||
| 98f78f534c | |||
| d18b12c1a3 | |||
| 6a7b1aa39a | |||
| c4be74a9d0 | |||
| 9092048dbc | |||
| bb419f1201 | |||
| d505fd2b60 | |||
| a771e0eccb | |||
| 593a5181d7 | |||
| c29274e760 | |||
| 216573bf48 | |||
| 1c235a5c89 | |||
| f90049dd9e | |||
| 90787e84bf | |||
| c36c80a077 | |||
| 227333239f | |||
| 2d43fcf9ee | |||
| 3edad56e6b | |||
| 4e2d900775 | |||
| 4dae82054e | |||
| cb5948d3a5 | |||
| 9fc7281fab | |||
| bb779b237a | |||
| 1294b4fec8 | |||
| 0b754562f6 | |||
| 15cb032ab7 | |||
| c85d2fd3bf | |||
| bc821ff47d | |||
| 42d9f42807 | |||
| 7ceff4cf5d | |||
| 4147da312b | |||
| 439891c31f | |||
| 322524101d | |||
| fd698653d9 | |||
| 8b503a06fa | |||
| 4a201df556 | |||
| 577b9f478b | |||
| f5a2eb1ab0 | |||
| 4379480d4b | |||
| dfa4afa826 | |||
| a533514763 | |||
| 952aaef52a | |||
| a54016a6f7 | |||
| 0c8a95c44b | |||
| 403633d21f | |||
| cc6f1d784d | |||
| e07ef3be9c | |||
| f35f534ff4 | |||
| 3899ec136b | |||
| 91ee809558 | |||
| 4c94e2729f | |||
| 2a5a207148 | |||
| c75bd89d63 | |||
| f58844bf8b | |||
| 07ac3499f3 | |||
| 050b64b822 | |||
| 43aa94dcfc | |||
| b2e54a432b | |||
| e766732020 | |||
| 3a5e01c44a | |||
| d4883da98b | |||
| 7cc3e9a16d | |||
| 9ad352d4bd | |||
| 031173bc47 | |||
| 658820a25e | |||
| 17fdce01a9 | |||
| bc4cc00332 | |||
| b57e9492b1 | |||
| 712bdc9d8d | |||
| 33a7c95455 | |||
| f054dcc77d | |||
| 95858b77c1 | |||
| 4afbce5ad6 | |||
| 93956002ac | |||
| 006dd290e9 | |||
| fb875145aa | |||
| 77993ced7e | |||
| e1f64d6283 | |||
| 2b60ce484e | |||
| a21b336138 | |||
| 0655280f2c | |||
| 2793578dcb | |||
| f1a70662c5 | |||
| 8a7e501fe6 | |||
| 86fc2dc2ba | |||
| 9cff42b4ed | |||
| 55546126a1 | |||
| 5a11dacd9e | |||
| bb5873bf20 | |||
| 20eda54349 | |||
| c98461f59e | |||
| b154c9a5c4 | |||
| 12255e3680 | |||
| 473c41ddbf | |||
| b93382831c | |||
| 5ee61f5ae7 | |||
| 082bbd49e7 | |||
| 4e2e69c9cb | |||
| 6f78bb6960 | |||
| a00caac789 | |||
| 4e8f191f43 | |||
| b1c5afd72f | |||
| aa5a2225e7 | |||
| 4c7672b581 | |||
| 5f9fa05e21 | |||
| ee92fa51bc | |||
| 63b3960120 | |||
| e5c76ddf3e | |||
| 4b07979008 | |||
| 168fa09f5f | |||
| 4facd57cb7 | |||
| e999636048 | |||
| 5bd769ea40 | |||
| bd693f97a1 | |||
| af0cb68c1b | |||
| 761d7fd438 | |||
| c537e8a892 | |||
| 702e85cd96 | |||
| c93e0b6c5e | |||
| f7b4a20066 | |||
| 49ac89bfed | |||
| 16e62b29f9 | |||
| b8180b0459 | |||
| 37f250b384 | |||
| 5685ec525b | |||
| 5be59ea8dd | |||
| 5855f2d909 | |||
| 5424223949 | |||
| de22148b44 | |||
| 73664e610b |
@@ -1,57 +0,0 @@
|
||||
# minimum clang-format 10
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: [ BOOST_FOREACH ]
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: Inner
|
||||
PointerAlignment: Left
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: Never
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: true
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++11
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
@@ -1,5 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Checks: '-clang-diagnostic-*,clang-analyzer-*, bugprone-*, modernize-deprecated-headers, modernize-loop-convert, modernize-use-override, modernize-redundant-void-arg, modernize-use-emplace, modernize-use-noexcept, modernize-use-bool-literals, modernize-pass-by-value, modernize-use-equals-default, modernize-use-equals-delete, modernize-use-default-member-init, cppcoreguidelines-prefer-member-initializer, cppcoreguidelines-init-variables, cppcoreguidelines-pro-type-member-init'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: '.*'
|
||||
FormatStyle: 'file'
|
||||
+2
-7
@@ -1,9 +1,9 @@
|
||||
|
||||
# Custom attribute to mark source files using KiCad C++ formatting
|
||||
[attr]kicad-cpp-source text=auto whitepace=tab-in-indent format.clang-format-kicad
|
||||
[attr]kicad-cpp-source whitepace=tab-in-indent format.clang-format-kicad
|
||||
|
||||
# Custom attribute to mark KiCad's own CMake files
|
||||
[attr]kicad-cmake-source text=auto whitespace=tab-in-indent
|
||||
[attr]kicad-cmake-source whitespace=tab-in-indent
|
||||
|
||||
# Custom attribute for auto-generated sources:
|
||||
# * Do not perform whitespace checking
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
*.cmake kicad-cmake-source
|
||||
*.txt kicad-cmake-source
|
||||
*.md text=auto
|
||||
|
||||
# Compiled bitmap sources
|
||||
bitmaps_png/cpp_*/*.cpp generated
|
||||
@@ -30,7 +29,3 @@ bitmaps_png/cpp_*/*.cpp generated
|
||||
# Lemon grammars
|
||||
common/libeval/grammar.c generated
|
||||
common/libeval/grammar.h generated
|
||||
|
||||
# Scripts
|
||||
*.sh text eol=lf
|
||||
*.bat text eol=crlf
|
||||
@@ -1,2 +0,0 @@
|
||||
custom: "https://donate.kicad.org"
|
||||
community_bridge: kicad
|
||||
@@ -1,26 +0,0 @@
|
||||
name: 'Redirect PRs'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: opened
|
||||
|
||||
jobs:
|
||||
lockdown:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/repo-lockdown@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
pr-comment: >
|
||||
Thank you for offering to help improve KiCad.
|
||||
This repository is a one-way mirror that can not accept pull requests.
|
||||
Please submit your merge request to the official KiCad repository
|
||||
at https://gitlab.com/kicad/code/kicad/-/merge_requests
|
||||
While we know that _your_ PR is not spam, we mark it as such to dissuade
|
||||
the Hacktoberfest PRs. Please join us over at GitLab. You can even use
|
||||
your GitHub credentials to log in there without creating a new account.
|
||||
skip-closed-pr-comment: true
|
||||
pr-labels: 'spam'
|
||||
close-pr: true
|
||||
lock-pr: true
|
||||
pr-lock-reason: 'spam'
|
||||
+19
-43
@@ -1,38 +1,41 @@
|
||||
.downloads-by-cmake
|
||||
.gdb_history
|
||||
boost_root
|
||||
/Build*
|
||||
/build*
|
||||
/cmake-build-*
|
||||
Build*
|
||||
build*
|
||||
common/fp_lib_table_keywords.cpp
|
||||
common/drc_rules_keywords.cpp
|
||||
common/drc_rules_lexer.h
|
||||
common/netlist_keywords.*
|
||||
common/netlist_lexer.h
|
||||
common/pcb_plot_params_lexer.h
|
||||
common/drawing_sheet/drawing_sheet_reader_keywords.cpp
|
||||
common/page_layout/page_layout_reader_keywords.cpp
|
||||
common/lib_table_keywords.*
|
||||
common/gal/opengl/shader_src.h
|
||||
include/fp_lib_table_lexer.h
|
||||
include/lib_table_lexer.h
|
||||
include/netlist_lexer.h
|
||||
include/page_layout_reader_lexer.h
|
||||
eeschema/cmp_library_lexer.h
|
||||
eeschema/cmp_library_keywords.*
|
||||
eeschema/dialogs/dialog_bom_cfg_keywords.cpp
|
||||
eeschema/dialogs/dialog_bom_cfg_lexer.h
|
||||
common/template_fieldnames_keywords.cpp
|
||||
common/template_fieldnames_lexer.h
|
||||
eeschema/schematic_keywords.*
|
||||
eeschema/dialogs/dialog_bom_help_html.h
|
||||
eeschema/template_fieldnames_keywords.*
|
||||
eeschema/template_fieldnames_lexer.h
|
||||
pcbnew/pcb_plot_params_keywords.cpp
|
||||
pcbnew/pcb_plot_params_lexer.h
|
||||
pcb_calculator/attenuators/bridget_tee_formula.h
|
||||
pcb_calculator/attenuators/pi_formula.h
|
||||
pcb_calculator/attenuators/splitter_formula.h
|
||||
pcb_calculator/attenuators/tee_formula.h
|
||||
Makefile
|
||||
CMakeUserPresets.json
|
||||
CMakeCache.txt
|
||||
.cache/
|
||||
auto_renamed_to_cpp
|
||||
Testing
|
||||
version.h
|
||||
config.h
|
||||
install_manifest.txt
|
||||
doxygen/out
|
||||
Documentation/doxygen
|
||||
Documentation/development/doxygen
|
||||
*.bak
|
||||
*.pyc
|
||||
common/pcb_plot_params_keywords.cpp
|
||||
@@ -46,17 +49,16 @@ new/sch_lib_table_keywords.cpp
|
||||
new/sch_lib_table_lexer.h
|
||||
new/sweet_keywords.cpp
|
||||
new/sweet_lexer.h
|
||||
bitmaps_png/png*
|
||||
bitmaps_png/tmp
|
||||
common/pcb_keywords.cpp
|
||||
include/pcb_lexer.h
|
||||
fp-info-cache
|
||||
qa/tests/output/**
|
||||
|
||||
# demo project auxiliary files
|
||||
# demo project auxillary files
|
||||
demos/**/*-bak
|
||||
demos/**/_autosave-*
|
||||
demos/**/fp-info-cache
|
||||
demos/**/~*.lck
|
||||
|
||||
# MacOS package info created by CMake
|
||||
bitmap2component/Info.plist
|
||||
@@ -76,9 +78,8 @@ pcbnew/Info.plist
|
||||
*.png
|
||||
*.kiface
|
||||
*.o
|
||||
*.o.*
|
||||
*.a
|
||||
*.a.*
|
||||
*.cmake
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
@@ -88,10 +89,9 @@ pcbnew/Info.plist
|
||||
*.patch
|
||||
|
||||
# These CMake files are wanted
|
||||
!cmake/**/*.cmake
|
||||
!CMakeModules/*.cmake
|
||||
|
||||
# Eclipse IDE
|
||||
.settings/
|
||||
.project
|
||||
.cproject
|
||||
.pydevproject
|
||||
@@ -101,10 +101,6 @@ __pycache__
|
||||
.vs/
|
||||
.editorconfig
|
||||
CMakeSettings.json
|
||||
.vscode/
|
||||
compile_commands.json
|
||||
/vcpkg_installed
|
||||
CMakePresets.json
|
||||
|
||||
# Sublime Text
|
||||
*.sublime-*
|
||||
@@ -113,27 +109,7 @@ CMakePresets.json
|
||||
.kdev4/
|
||||
*.kdev4
|
||||
|
||||
# Qt Creator
|
||||
CMakeLists.txt.user
|
||||
*.autosave
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
i18n_status.svg
|
||||
i18n_status.csv
|
||||
|
||||
# Project local settings files and backups (in demos and qa tests)
|
||||
*.kicad_prl
|
||||
*-backups
|
||||
|
||||
# QA dataoutput
|
||||
qa/data/**/*.csv
|
||||
|
||||
# Don't actually ignore any of these files, since we need them in the tree
|
||||
!resources/linux/icons/hicolor/**/**/*
|
||||
!resources/linux/icons-nightly/hicolor/**/**/*
|
||||
!CMakeModules/**/*
|
||||
!resources/bitmaps_png/png/**/*
|
||||
|
||||
# Junk temp files generated by MSVC for resource files
|
||||
/resources/msw/RC*
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- report
|
||||
|
||||
variables:
|
||||
DEFAULT_FEDORA_IMAGE: registry.gitlab.com/kicad/kicad-ci/source_containers/master/fedora:40
|
||||
|
||||
default:
|
||||
image:
|
||||
name: $DEFAULT_FEDORA_IMAGE
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
|
||||
include:
|
||||
- local: '/.gitlab/templates.yml'
|
||||
- local: '/.gitlab/Fedora-Linux-CI.yml'
|
||||
- local: '/.gitlab/Ubuntu-20.04-CI.yml'
|
||||
- local: '/.gitlab/Windows-CI.yml'
|
||||
- local: '/.gitlab/macOS-CI.yml'
|
||||
- local: '/.gitlab/coverity.yml'
|
||||
- local: '/.gitlab/linux-metadata-validate.yml'
|
||||
- local: '/.gitlab/doxygen.yml'
|
||||
- local: '/.gitlab/mr_formatting.yml'
|
||||
@@ -1,179 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Fedora and save the results
|
||||
##########################################################################
|
||||
.fedora_build_linux_base:
|
||||
stage: build
|
||||
# Don't tag until we have separate CI for MRs
|
||||
# tags:
|
||||
# - kicad-fedora
|
||||
image: $DEFAULT_FEDORA_IMAGE
|
||||
extends: .only_code
|
||||
interruptible: false
|
||||
cache:
|
||||
key: "cache-fedora-linux"
|
||||
paths:
|
||||
- ccache/
|
||||
before_script:
|
||||
# CCache Config
|
||||
- mkdir -p ccache
|
||||
- export CCACHE_BASEDIR=${PWD}
|
||||
- export CCACHE_DIR=${PWD}/ccache
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_BUILD_TYPE=QABUILD
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
-DKICAD_TEST_XML_OUTPUT=ON
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON
|
||||
-DKICAD_USE_CMAKE_FINDPROTOBUF=ON
|
||||
../../
|
||||
- ninja 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/linux/3d-viewer/
|
||||
- build/linux/api/libkiapi.so*
|
||||
- build/linux/common/libkicommon.so*
|
||||
- build/linux/common/gal/libkigal.so*
|
||||
- build/linux/eeschema/_eeschema.kiface
|
||||
- build/linux/cvpcb/_cvpcb.kiface
|
||||
- build/linux/kicad/kicad-cli
|
||||
- build/linux/pcbnew/pcbnew.py
|
||||
- build/linux/pcbnew/_pcbnew.kiface
|
||||
- build/linux/pcbnew/_pcbnew.so
|
||||
- build/linux/qa/
|
||||
- build/linux/schemas/
|
||||
- build/linux/compilation_log.txt
|
||||
exclude:
|
||||
- build/linux/**/*.o
|
||||
- build/linux/**/*.a
|
||||
|
||||
# This split is to ensure we can always use our runner for our jobs
|
||||
fedora_build_linux_kicad:
|
||||
extends: .fedora_build_linux_base
|
||||
tags:
|
||||
- kicad-fedora
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
fedora_build_linux_public:
|
||||
extends: .fedora_build_linux_base
|
||||
tags:
|
||||
- saas-linux-medium-amd64
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
|
||||
# Upload the compilation log in an easily downloadable form
|
||||
.fedora_report_build_warn:
|
||||
stage: report
|
||||
extends: .only_code
|
||||
when: always
|
||||
script:
|
||||
- echo "Uploading compilation log"
|
||||
- cp build/linux/compilation_log.txt compilation_log.txt
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Build log'
|
||||
name: "build_log.txt"
|
||||
paths:
|
||||
- compilation_log.txt
|
||||
|
||||
fedora_report_build_warn_kicad:
|
||||
extends: .fedora_report_build_warn
|
||||
tags:
|
||||
- kicad-fedora
|
||||
needs:
|
||||
- job: fedora_build_linux_kicad
|
||||
artifacts: true
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
fedora_report_build_warn_public:
|
||||
extends: .fedora_report_build_warn
|
||||
needs:
|
||||
- job: fedora_build_linux_public
|
||||
artifacts: true
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
|
||||
# Report on the metrics of the code
|
||||
.fedora_report_metrics:
|
||||
stage: report
|
||||
extends: .only_code
|
||||
when: always
|
||||
script:
|
||||
- cat build/linux/compilation_log.txt | { grep "warning:" || test $? = 1; } | awk 'END{print "number_of_fedora_warnings "NR}' > metrics.txt
|
||||
- cat metrics.txt
|
||||
artifacts:
|
||||
reports:
|
||||
metrics: metrics.txt
|
||||
|
||||
fedora_report_metrics_kicad:
|
||||
extends: .fedora_report_metrics
|
||||
tags:
|
||||
- kicad-fedora
|
||||
needs:
|
||||
- job: fedora_build_linux_kicad
|
||||
artifacts: true
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
fedora_report_metrics_public:
|
||||
extends: .fedora_report_metrics
|
||||
needs:
|
||||
- job: fedora_build_linux_public
|
||||
artifacts: true
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
##########################################################################
|
||||
# Run the code unit tests.
|
||||
##########################################################################
|
||||
.fedora_qa:
|
||||
image: $DEFAULT_FEDORA_IMAGE
|
||||
extends:
|
||||
- .unit_test
|
||||
- .only_code
|
||||
before_script:
|
||||
- if [ "$TEST" == "cli" ] || [ "$TEST" == "python" ]; then python3 -m pip install -r qa/tests/requirements.txt; fi
|
||||
- if [ "$TEST" == "cli" ]; then sudo dnf -y install gerbv; fi
|
||||
parallel:
|
||||
matrix:
|
||||
# The name of the test without the qa_ prefix
|
||||
- TEST: [python, cli, common, gerbview, pcbnew, pns_regressions, eeschema, kimath, sexpr, kicad2step, spice, api]
|
||||
|
||||
fedora_qa_kicad:
|
||||
extends: .fedora_qa
|
||||
tags:
|
||||
- kicad-fedora
|
||||
needs:
|
||||
- job: fedora_build_linux_kicad
|
||||
artifacts: true
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
fedora_qa_public:
|
||||
extends: .fedora_qa
|
||||
needs:
|
||||
- job: fedora_build_linux_public
|
||||
artifacts: true
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
@@ -1,118 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Ubuntu 20.04 and save the results
|
||||
##########################################################################
|
||||
.ubuntu20.04_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-ubuntu20.04
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/ubuntu:20.04
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
interruptible: false
|
||||
cache:
|
||||
key: "cache-ubuntu20.04-linux"
|
||||
paths:
|
||||
- ccache/
|
||||
before_script:
|
||||
# CCache Config
|
||||
- mkdir -p ccache
|
||||
- export CCACHE_BASEDIR=${PWD}
|
||||
- export CCACHE_DIR=${PWD}/ccache
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_USE_OCC=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON
|
||||
../../
|
||||
- ninja 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/linux/3d-viewer/
|
||||
- build/linux/pcbnew/pcbnew.py
|
||||
- build/linux/pcbnew/_pcbnew.kiface
|
||||
- build/linux/pcbnew/_pcbnew.so
|
||||
- build/linux/qa/
|
||||
- build/linux/compilation_log.txt
|
||||
exclude:
|
||||
- build/linux/**/*.o
|
||||
- build/linux/**/*.a
|
||||
|
||||
# Upload the compilation log in an easily downloadable form
|
||||
.ubuntu20.04_report_build_warn:
|
||||
stage: report
|
||||
when: always
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
script:
|
||||
- echo "Uploading compilation log"
|
||||
- cp build/linux/compilation_log.txt compilation_log.txt
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Build log'
|
||||
name: "build_log.txt"
|
||||
paths:
|
||||
- compilation_log.txt
|
||||
|
||||
# Report on the metrics of the code
|
||||
.ubuntu20.04_report_metrics:
|
||||
stage: report
|
||||
when: always
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
script:
|
||||
- cat build/linux/compilation_log.txt | { grep "warning:" || test $? = 1; } | awk 'END{print "number_of_ubuntu_20.04_warnings "NR}' > metrics.txt
|
||||
- cat metrics.txt
|
||||
artifacts:
|
||||
reports:
|
||||
metrics: metrics.txt
|
||||
|
||||
##########################################################################
|
||||
# Run the code unit tests.
|
||||
##########################################################################
|
||||
.ubuntu20.04_qa:
|
||||
extends:
|
||||
- .unit_test
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
tags:
|
||||
- kicad-ubuntu20.04
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/ubuntu:20.04
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
parallel:
|
||||
matrix:
|
||||
# The name of the test without the qa_ prefix
|
||||
- TEST: [python, common, gerbview, pcbnew, eeschema, kimath, sexpr, kicad2step, spice]
|
||||
@@ -1,47 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Windows and save the results
|
||||
##########################################################################
|
||||
win64_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-windows-ltsc2022
|
||||
interruptible: false
|
||||
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
|
||||
variables:
|
||||
# Switch the compressor to fastzip and reduce the compression level
|
||||
FF_USE_FASTZIP: "true"
|
||||
CACHE_COMPRESSION_LEVEL: "fast"
|
||||
cache:
|
||||
key: win64-vcpkg-$CI_COMMIT_REF_SLUG
|
||||
paths:
|
||||
- build\windows\vcpkg_installed
|
||||
- .vcpkgCache
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
when: never
|
||||
- if: $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
script:
|
||||
- C:\builder\build.ps1 -Env -Arch x64
|
||||
- $vcpkgCache=Join-Path -Path (Get-Location) -ChildPath ".vcpkgCache";$env:VCPKG_DEFAULT_BINARY_CACHE=$vcpkgCache;New-Item -ItemType Directory -Force -Path $vcpkgCache
|
||||
- mkdir -p build/windows -Force
|
||||
- cd build/windows
|
||||
- cmake `
|
||||
-G "Ninja" `
|
||||
-DCMAKE_TOOLCHAIN_FILE=C:\builder\vcpkg\scripts\buildsystems\vcpkg.cmake `
|
||||
-DCMAKE_BUILD_TYPE=Debug `
|
||||
-DKICAD_SCRIPTING_WXPYTHON=OFF `
|
||||
-DKICAD_USE_OCC=ON `
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON `
|
||||
-DKICAD_USE_3DCONNEXION=ON `
|
||||
-DVCPKG_BUILD_TYPE=debug `
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/windows/compilation_log.txt
|
||||
@@ -1,76 +0,0 @@
|
||||
# This script is responsible for configuring the coverity file from the cache
|
||||
# (e.g. extracting it or updating it if needed)
|
||||
.coverity_cache_prep: &coverity_cache_prep |
|
||||
echo "Downloading MD5 hash of current Coverity Scan version to compare against cache"
|
||||
curl --output cov-analysis-linux64.md5 https://scan.coverity.com/download/linux64 \
|
||||
--form project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN \
|
||||
--form md5=1
|
||||
echo " *cov-analysis-linux64.tgz" >> cov-analysis-linux64.md5
|
||||
(md5sum --ignore-missing -c cov-analysis-linux64.md5) || (
|
||||
echo "Downloading new Coverity Scan version"
|
||||
curl --output cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 \
|
||||
--form project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN
|
||||
)
|
||||
echo "Extracting Coverity Scan"
|
||||
mkdir coverity/
|
||||
tar xzf cov-analysis-linux64.tgz --strip-components=1 -C coverity
|
||||
test -d coverity/bin
|
||||
|
||||
# This script is responsible for tar'ing and submitting the results of the build.
|
||||
# These results will be saved for 1 day if the build fails.
|
||||
.coverity_submit: &coverity_submit |
|
||||
echo "Creating tar file of scan results"
|
||||
export COV_INT_FILENAME=cov-int-$(date +"%Y%m%d%H%M").tar.gz
|
||||
tar cfz $COV_INT_FILENAME cov-int
|
||||
echo "Submitting scan results"
|
||||
s5cmd/s5cmd cp $COV_INT_FILENAME s3://$KICAD_CI_R2_BUCKET/coverity/
|
||||
export FILE_URL="$KICAD_CI_R2_PUBLIC_BASE/coverity/$COV_INT_FILENAME"
|
||||
export KICAD_VERSION=$(sed 's/[()]//g' kicad_build_version.txt)
|
||||
curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN \
|
||||
--form email=$GITLAB_USER_EMAIL \
|
||||
--form url="$FILE_URL" \
|
||||
--form version="$KICAD_VERSION" \
|
||||
--form description="$KICAD_VERSION / $CI_COMMIT_TITLE" 2>&1 \
|
||||
| tee curl-response.txt
|
||||
grep -q 'Build successfully submitted' curl-response.txt
|
||||
|
||||
|
||||
Coverity:
|
||||
tags:
|
||||
- coverity
|
||||
stage: build
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/fedora:40
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULED_JOB_NAME == "coverity"
|
||||
cache:
|
||||
key: coverity
|
||||
paths:
|
||||
- cov-analysis-linux64.tgz
|
||||
before_script:
|
||||
- export COVERITY_SCAN_PROJECT_NAME="kicad"
|
||||
- test "$(git rev-parse --is-shallow-repository)" = "false" || (git fetch --unshallow)
|
||||
- git fetch origin
|
||||
- curl -LO https://github.com/peak/s5cmd/releases/download/v2.0.0/s5cmd_2.0.0_Linux-64bit.tar.gz
|
||||
- mkdir s5cmd
|
||||
- tar -xvf ./s5cmd_2.0.0_Linux-64bit.tar.gz -C s5cmd
|
||||
- export AWS_ACCESS_KEY_ID=$KICAD_CI_R2_KEY_ID
|
||||
- export AWS_SECRET_ACCESS_KEY=$KICAD_CI_R2_ACCESS_KEY
|
||||
- export S3_ENDPOINT_URL=$KICAD_CI_R2_ENDPOINT
|
||||
script:
|
||||
- *coverity_cache_prep
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_USE_CMAKE_FINDPROTOBUF=ON
|
||||
- coverity/bin/cov-build --dir cov-int make -j10
|
||||
- *coverity_submit
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Coverity log'
|
||||
name: "coverity_log.txt"
|
||||
paths:
|
||||
- cov-int/build-log.txt
|
||||
@@ -1,15 +0,0 @@
|
||||
build_doxygen_docker:
|
||||
image: docker:stable
|
||||
services:
|
||||
- docker:dind
|
||||
stage: build
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULED_JOB_NAME == "doxygen"
|
||||
tags:
|
||||
- gitlab-org-docker
|
||||
before_script:
|
||||
- docker info
|
||||
- docker login -u gitlab-ci-token -p "$CI_JOB_TOKEN" "$CI_REGISTRY"
|
||||
script:
|
||||
- docker build -t "${CI_REGISTRY_IMAGE}/doxygen:$CI_COMMIT_BRANCH" -f ./doxygen/doxygen.Dockerfile .
|
||||
- docker push "${CI_REGISTRY_IMAGE}/doxygen:$CI_COMMIT_BRANCH"
|
||||
@@ -1,20 +0,0 @@
|
||||
<!-- --------Before Creating a New Issue-----------
|
||||
* Limit report to a single issue.
|
||||
* Search the issue tracker to verify the issue has not already been reported.
|
||||
* Complete all instructions between `template comment markers <>.
|
||||
* Keep report contents limited to the necessary information required to fix the issue.
|
||||
* When creating an issue against the stable version of KiCad, make sure the latest available stable version is installed as issues may have already been resolved in later stable versions. -->
|
||||
# Description
|
||||
<!-- What is the current behavior and what is the expected behavior? -->
|
||||
<!-- If the issue is visual/graphical, please attach screenshots of the problem. -->
|
||||
<!-- Add the issue details below this line and before the "Steps to reproduce" heading. -->
|
||||
|
||||
# Steps to reproduce
|
||||
<!-- If there are multiple steps to reproduce it or it is a visual issue, then providing a screen recording as an attachment to this report is recommended. -->
|
||||
<!-- If this issue is specific to a project, please attach the necessary files to this issue. -->
|
||||
<!-- Add the steps to reproduce using the numbers below -->
|
||||
<!-- Add new step numbers before the "KiCad Version" heading. -->
|
||||
1.
|
||||
|
||||
# KiCad Version
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
##########################################################################
|
||||
# Run a validation of the metadata files for Linux
|
||||
##########################################################################
|
||||
validate_linux_metadata:
|
||||
stage: test
|
||||
needs: []
|
||||
interruptible: false
|
||||
image: $DEFAULT_FEDORA_IMAGE
|
||||
# Due to bug https://github.com/hughsie/appstream-glib/issues/381, this doesn't think our description tag
|
||||
# is localized even though it actually is.
|
||||
allow_failure: true
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
changes:
|
||||
- resources/linux/**/*
|
||||
- qa/resources/linux/**/*
|
||||
- translation/**/*
|
||||
# Only build the metadata files in this CI job
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
../../
|
||||
- make metadata
|
||||
- cd ../../
|
||||
- ./qa/resources/linux/verifyMetadataFiles.sh ./ ./build/linux
|
||||
@@ -1,29 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Windows and save the results
|
||||
##########################################################################
|
||||
macos_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-macos
|
||||
interruptible: false
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
when: never
|
||||
- if: $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
script:
|
||||
- mkdir -p build/macos
|
||||
- cd build/macos
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_TOOLCHAIN_FILE=/Users/$USER/kicad-mac-builder/toolchain/kicad-mac-builder.cmake
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/macos/compilation_log.txt
|
||||
@@ -1,27 +0,0 @@
|
||||
##########################################################################
|
||||
# Test the formatting in a merge request using clang-format
|
||||
##########################################################################
|
||||
# The variable CI_COMMIT_BEFORE_SHA is not available in normal merge requests
|
||||
# so we must build the commit hash ourselves, see:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/12850
|
||||
test_formatting:
|
||||
stage: test
|
||||
needs: []
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
allow_failure: true
|
||||
before_script:
|
||||
# We must manually add the KiCad remote to ensure it is named sensibly
|
||||
- git remote add product https://gitlab.com/kicad/code/kicad.git ||
|
||||
git remote set-url product https://gitlab.com/kicad/code/kicad.git
|
||||
- git remote add source ${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}.git ||
|
||||
git remote set-url source ${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}.git
|
||||
- git fetch -n product
|
||||
- git fetch -n source
|
||||
# Get the SHAs of the commits
|
||||
- "TARGET_HEAD_SHA=$(git rev-parse product/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME})"
|
||||
- "SOURCE_HEAD_SHA=$(git rev-parse source/${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME})"
|
||||
- "MERGE_BASE_SHA=$(git merge-base ${TARGET_HEAD_SHA} ${SOURCE_HEAD_SHA})"
|
||||
script:
|
||||
- echo "Testing formatting from commit ${MERGE_BASE_SHA}"
|
||||
- ./tools/check_coding.sh --diff --ci --commit ${MERGE_BASE_SHA}
|
||||
@@ -1,37 +0,0 @@
|
||||
##########################################################################
|
||||
# This will allow the job to run whenever code events trigger it.
|
||||
##########################################################################
|
||||
.only_code:
|
||||
only:
|
||||
- master
|
||||
- branches
|
||||
- merge_requests
|
||||
- pushes
|
||||
except:
|
||||
- schedules
|
||||
|
||||
##########################################################################
|
||||
# Define a template for all the unit tests, since each one is run in a separate
|
||||
# job to make the display nicer.
|
||||
##########################################################################
|
||||
.unit_test:
|
||||
stage: test
|
||||
when: on_success
|
||||
variables:
|
||||
BOOST_TEST_LOGGER: 'JUNIT,warning,test_results.${TEST}.xml:HRF,message'
|
||||
CTEST_OUTPUT_ON_FAILURE: 1
|
||||
script:
|
||||
- cd build/linux/qa
|
||||
- ctest -R qa_${TEST}
|
||||
# GitLab supports displaying the results in the GUI through JUNIT artifacts
|
||||
# (https://docs.gitlab.com/ee/ci/junit_test_reports.html)
|
||||
# so we upload the JUNIT results.
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build/linux/qa/**/*.log
|
||||
- build/linux/qa/**/output/*
|
||||
- build/linux/qa/**/*.xml
|
||||
reports:
|
||||
junit:
|
||||
- build/linux/qa/**/*.xml
|
||||
+331
-173
@@ -2,8 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2022 CERN
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -25,40 +24,55 @@
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
|
||||
#include <mutex>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
#include <wx/datetime.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if BOOST_VERSION >= 106800
|
||||
#include <boost/uuid/detail/sha1.hpp>
|
||||
#else
|
||||
#include <boost/uuid/sha1.hpp>
|
||||
#endif
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
|
||||
#include "common.h"
|
||||
#include "3d_cache.h"
|
||||
#include "3d_info.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "sg/scenegraph.h"
|
||||
#include "filename_resolver.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <common.h> // For ExpandEnvVarSubstitutions
|
||||
#include <filename_resolver.h>
|
||||
#include <mmh3_hash.h>
|
||||
#include <paths.h>
|
||||
#include <pgm_base.h>
|
||||
#include <project.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <wx_filename.h>
|
||||
|
||||
|
||||
#define MASK_3D_CACHE "3D_CACHE"
|
||||
|
||||
static std::mutex mutex3D_cache;
|
||||
static wxCriticalSection lock3D_cache;
|
||||
|
||||
|
||||
static bool isSHA1Same( const unsigned char* shaA, const unsigned char* shaB )
|
||||
{
|
||||
for( int i = 0; i < 20; ++i )
|
||||
if( shaA[i] != shaB[i] )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool checkTag( const char* aTag, void* aPluginMgrPtr )
|
||||
{
|
||||
if( nullptr == aTag || nullptr == aPluginMgrPtr )
|
||||
if( NULL == aTag || NULL == aPluginMgrPtr )
|
||||
return false;
|
||||
|
||||
S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
|
||||
@@ -67,57 +81,101 @@ static bool checkTag( const char* aTag, void* aPluginMgrPtr )
|
||||
}
|
||||
|
||||
|
||||
static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
unsigned char uc;
|
||||
unsigned char tmp;
|
||||
char sha1[41];
|
||||
int j = 0;
|
||||
|
||||
for( int i = 0; i < 20; ++i )
|
||||
{
|
||||
uc = aSHA1Sum[i];
|
||||
tmp = uc / 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
sha1[j++] = tmp;
|
||||
tmp = uc % 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
sha1[j++] = tmp;
|
||||
}
|
||||
|
||||
sha1[j] = 0;
|
||||
|
||||
return wxString::FromUTF8Unchecked( sha1 );
|
||||
}
|
||||
|
||||
|
||||
class S3D_CACHE_ENTRY
|
||||
{
|
||||
public:
|
||||
S3D_CACHE_ENTRY();
|
||||
~S3D_CACHE_ENTRY();
|
||||
|
||||
void SetHash( const HASH_128& aHash );
|
||||
const wxString GetCacheBaseName();
|
||||
|
||||
wxDateTime modTime; // file modification time
|
||||
HASH_128 m_hash;
|
||||
std::string pluginInfo; // PluginName:Version string
|
||||
SCENEGRAPH* sceneData;
|
||||
S3DMODEL* renderData;
|
||||
|
||||
private:
|
||||
// prohibit assignment and default copy constructor
|
||||
S3D_CACHE_ENTRY( const S3D_CACHE_ENTRY& source );
|
||||
S3D_CACHE_ENTRY& operator=( const S3D_CACHE_ENTRY& source );
|
||||
|
||||
wxString m_CacheBaseName; // base name of cache file
|
||||
wxString m_CacheBaseName; // base name of cache file (a SHA1 digest)
|
||||
|
||||
public:
|
||||
S3D_CACHE_ENTRY();
|
||||
~S3D_CACHE_ENTRY();
|
||||
|
||||
void SetSHA1( const unsigned char* aSHA1Sum );
|
||||
const wxString GetCacheBaseName( void );
|
||||
|
||||
wxDateTime modTime; // file modification time
|
||||
unsigned char sha1sum[20];
|
||||
std::string pluginInfo; // PluginName:Version string
|
||||
SCENEGRAPH* sceneData;
|
||||
S3DMODEL* renderData;
|
||||
};
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
|
||||
{
|
||||
sceneData = nullptr;
|
||||
renderData = nullptr;
|
||||
m_hash.Clear();
|
||||
sceneData = NULL;
|
||||
renderData = NULL;
|
||||
memset( sha1sum, 0, 20 );
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
|
||||
{
|
||||
delete sceneData;
|
||||
if( NULL != sceneData )
|
||||
delete sceneData;
|
||||
|
||||
if( nullptr != renderData )
|
||||
if( NULL != renderData )
|
||||
S3D::Destroy3DModel( &renderData );
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE_ENTRY::SetHash( const HASH_128& aHash )
|
||||
void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
m_hash = aHash;
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] NULL passed for aSHA1Sum",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy( sha1sum, aSHA1Sum, 20 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const wxString S3D_CACHE_ENTRY::GetCacheBaseName()
|
||||
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
|
||||
{
|
||||
if( m_CacheBaseName.empty() )
|
||||
m_CacheBaseName = m_hash.ToString();
|
||||
m_CacheBaseName = sha1ToWXString( sha1sum );
|
||||
|
||||
return m_CacheBaseName;
|
||||
}
|
||||
@@ -125,9 +183,11 @@ const wxString S3D_CACHE_ENTRY::GetCacheBaseName()
|
||||
|
||||
S3D_CACHE::S3D_CACHE()
|
||||
{
|
||||
m_DirtyCache = false;
|
||||
m_FNResolver = new FILENAME_RESOLVER;
|
||||
m_project = nullptr;
|
||||
m_Plugins = new S3D_PLUGIN_MANAGER;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,30 +195,33 @@ S3D_CACHE::~S3D_CACHE()
|
||||
{
|
||||
FlushCache();
|
||||
|
||||
delete m_FNResolver;
|
||||
delete m_Plugins;
|
||||
if( m_FNResolver )
|
||||
delete m_FNResolver;
|
||||
|
||||
if( m_Plugins )
|
||||
delete m_Plugins;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
S3D_CACHE_ENTRY** aCachePtr, const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = nullptr;
|
||||
*aCachePtr = NULL;
|
||||
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, aEmbeddedFiles );
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
|
||||
|
||||
if( full3Dpath.empty() )
|
||||
{
|
||||
// the model cannot be found; we cannot proceed
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [3D model] could not find model '%s'\n" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [3D model] could not find model '%s'\n",
|
||||
__FILE__, __FUNCTION__, __LINE__, aModelFile );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check cache if file is already loaded
|
||||
std::lock_guard<std::mutex> lock( mutex3D_cache );
|
||||
|
||||
wxCriticalSectionLocker lock( lock3D_cache );
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
@@ -168,39 +231,38 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePa
|
||||
|
||||
if( fname.FileExists() ) // Only check if file exists. If not, it will
|
||||
{ // use the same model in cache.
|
||||
bool reload = ADVANCED_CFG::GetCfg().m_Skip3DModelMemoryCache;
|
||||
bool reload = false;
|
||||
wxDateTime fmdate = fname.GetModificationTime();
|
||||
|
||||
if( fmdate != mi->second->modTime )
|
||||
{
|
||||
HASH_128 hashSum;
|
||||
getHash( full3Dpath, hashSum );
|
||||
unsigned char hashSum[20];
|
||||
getSHA1( full3Dpath, hashSum );
|
||||
mi->second->modTime = fmdate;
|
||||
|
||||
if( hashSum != mi->second->m_hash )
|
||||
if( !isSHA1Same( hashSum, mi->second->sha1sum ) )
|
||||
{
|
||||
mi->second->SetHash( hashSum );
|
||||
mi->second->SetSHA1( hashSum );
|
||||
reload = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( reload )
|
||||
{
|
||||
if( nullptr != mi->second->sceneData )
|
||||
if( NULL != mi->second->sceneData )
|
||||
{
|
||||
S3D::DestroyNode( mi->second->sceneData );
|
||||
mi->second->sceneData = nullptr;
|
||||
mi->second->sceneData = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != mi->second->renderData )
|
||||
if( NULL != mi->second->renderData )
|
||||
S3D::Destroy3DModel( &mi->second->renderData );
|
||||
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath,
|
||||
mi->second->pluginInfo );
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath, mi->second->pluginInfo );
|
||||
}
|
||||
}
|
||||
|
||||
if( nullptr != aCachePtr )
|
||||
if( NULL != aCachePtr )
|
||||
*aCachePtr = mi->second;
|
||||
|
||||
return mi->second->sceneData;
|
||||
@@ -211,34 +273,33 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePa
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
|
||||
{
|
||||
return load( aModelFile, aBasePath, nullptr, aEmbeddedFiles );
|
||||
return load( aModelFile );
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = nullptr;
|
||||
*aCachePtr = NULL;
|
||||
|
||||
HASH_128 hashSum;
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
unsigned char sha1sum[20];
|
||||
|
||||
if( !getHash( aFileName, hashSum ) || m_CacheDir.empty() )
|
||||
if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() )
|
||||
{
|
||||
// just in case we can't get a hash digest (for example, on access issues)
|
||||
// or we do not have a configured cache file directory, we create an
|
||||
// entry to prevent further attempts at loading the file
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
|
||||
if( m_CacheMap.emplace( aFileName, ep ).second == false )
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
m_CacheList.pop_back();
|
||||
@@ -248,71 +309,100 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY**
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( m_CacheMap.emplace( aFileName, ep ).second == false )
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
ep->SetHash( hashSum );
|
||||
ep->SetSHA1( sha1sum );
|
||||
|
||||
wxString bname = ep->GetCacheBaseName();
|
||||
wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && wxFileName::FileExists( cachename )
|
||||
&& loadCacheData( ep ) )
|
||||
if( wxFileName::FileExists( cachename ) && loadCacheData( ep ) )
|
||||
return ep->sceneData;
|
||||
|
||||
ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
|
||||
|
||||
if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && nullptr != ep->sceneData )
|
||||
if( NULL != ep->sceneData )
|
||||
saveCacheData( ep );
|
||||
|
||||
return ep->sceneData;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::getHash( const wxString& aFileName, HASH_128& aHash )
|
||||
bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
|
||||
{
|
||||
if( aFileName.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] empty filename" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * [BUG] empty filename",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
|
||||
#else
|
||||
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||
#endif
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n * [BUG] NULL pointer passed for aMD5Sum",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
if( nullptr == fp )
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
|
||||
#else
|
||||
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||
#endif
|
||||
|
||||
if( NULL == fp )
|
||||
return false;
|
||||
|
||||
MMH3_HASH dblock( 0xA1B2C3D4 );
|
||||
std::vector<char> block( 4096 );
|
||||
boost::uuids::detail::sha1 dblock;
|
||||
unsigned char block[4096];
|
||||
size_t bsize = 0;
|
||||
|
||||
while( ( bsize = fread( block.data(), 1, 4096, fp ) ) > 0 )
|
||||
dblock.add( block );
|
||||
while( ( bsize = fread( &block, 1, 4096, fp ) ) > 0 )
|
||||
dblock.process_bytes( block, bsize );
|
||||
|
||||
fclose( fp );
|
||||
aHash = dblock.digest();
|
||||
unsigned int digest[5];
|
||||
dblock.get_digest( digest );
|
||||
|
||||
// ensure MSB order
|
||||
for( int i = 0; i < 5; ++i )
|
||||
{
|
||||
int idx = i << 2;
|
||||
unsigned int tmp = digest[i];
|
||||
aSHA1Sum[idx+3] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx+2] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx+1] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx] = tmp & 0xff;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -324,7 +414,7 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; no file hash available" ) );
|
||||
" * [3D model] cannot load cached model; no file hash available" );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -332,7 +422,7 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
|
||||
" * [3D model] cannot load cached model; config directory unknown" );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -341,16 +431,17 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( " * [3D model] cannot open file '%s'" ), fname.GetData() );
|
||||
wxString errmsg = "cannot open file";
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'", errmsg.GetData(), fname.GetData() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( nullptr != aCacheItem->sceneData )
|
||||
if( NULL != aCacheItem->sceneData )
|
||||
S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
|
||||
|
||||
aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
|
||||
|
||||
if( nullptr == aCacheItem->sceneData )
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -359,17 +450,17 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
|
||||
bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( nullptr == aCacheItem )
|
||||
if( NULL == aCacheItem )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * NULL passed for aCacheItem" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * NULL passed for aCacheItem",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( nullptr == aCacheItem->sceneData )
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * aCacheItem has no valid scene data" ),
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * aCacheItem has no valid scene data",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return false;
|
||||
@@ -380,7 +471,7 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; no file hash available" ) );
|
||||
" * [3D model] cannot load cached model; no file hash available" );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -388,7 +479,7 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
|
||||
" * [3D model] cannot load cached model; config directory unknown" );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -399,15 +490,15 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] path exists but is not a regular file '%s'" ), fname );
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] path exists but is not a regular file '%s'",
|
||||
fname );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
|
||||
aCacheItem->pluginInfo.c_str() );
|
||||
aCacheItem->pluginInfo.c_str() );
|
||||
}
|
||||
|
||||
|
||||
@@ -416,9 +507,14 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
if( !m_ConfigDir.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), wxEmptyString );
|
||||
wxFileName cfgdir;
|
||||
|
||||
cfgdir.Normalize( FN_NORMALIZE_FLAGS );
|
||||
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
|
||||
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
|
||||
else
|
||||
cfgdir.Assign( aConfigDir, "" );
|
||||
|
||||
cfgdir.Normalize();
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
@@ -427,7 +523,7 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * failed to create 3D configuration directory '%s'" ),
|
||||
"%s:%s:%d\n * failed to create 3D configuration directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
|
||||
return false;
|
||||
@@ -440,8 +536,8 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
|
||||
" * config directory: '%s'" ),
|
||||
"%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
|
||||
" * config directory: '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
|
||||
}
|
||||
|
||||
@@ -452,36 +548,104 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
// 1. OSX: ~/Library/Caches/kicad/3d/
|
||||
// 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
|
||||
// 3. MSWin: AppData\Local\kicad\3d
|
||||
wxFileName cacheDir;
|
||||
cacheDir.AssignDir( PATHS::GetUserCachePath() );
|
||||
cacheDir.AppendDir( wxT( "3d" ) );
|
||||
wxString cacheDir;
|
||||
|
||||
if( !cacheDir.DirExists() )
|
||||
#if defined(_WIN32)
|
||||
wxStandardPaths::Get().UseAppInfo( wxStandardPaths::AppInfo_None );
|
||||
cacheDir = wxStandardPaths::Get().GetUserLocalDataDir();
|
||||
cacheDir.append( "\\kicad\\3d" );
|
||||
#elif defined(__APPLE)
|
||||
cacheDir = "${HOME}/Library/Caches/kicad/3d";
|
||||
#else // assume Linux
|
||||
cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}" );
|
||||
|
||||
if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" )
|
||||
cacheDir = "${HOME}/.cache";
|
||||
|
||||
cacheDir.append( "/kicad/3d" );
|
||||
#endif
|
||||
|
||||
cacheDir = ExpandEnvVarSubstitutions( cacheDir );
|
||||
cfgdir.Assign( cacheDir, "" );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
if( !cacheDir.DirExists() )
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * failed to create 3D cache directory '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D cache directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_CacheDir = cacheDir.GetPathWithSep();
|
||||
m_CacheDir = cfgdir.GetPathWithSep();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::SetProject( PROJECT* aProject )
|
||||
wxString S3D_CACHE::Get3DConfigDir( bool createDefault )
|
||||
{
|
||||
m_project = aProject;
|
||||
if( !m_ConfigDir.empty() || !createDefault )
|
||||
return m_ConfigDir;
|
||||
|
||||
// note: duplicated from common/common.cpp GetKicadConfigPath() to avoid
|
||||
// code coupling; ideally the instantiating code should call
|
||||
// Set3DConfigDir() to set the directory rather than relying on this
|
||||
// directory remaining the same in future KiCad releases.
|
||||
wxFileName cfgpath;
|
||||
|
||||
// From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
|
||||
// Unix: ~ (the home directory)
|
||||
// Windows: "C:\Documents and Settings\username\Application Data"
|
||||
// Mac: ~/Library/Preferences
|
||||
cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
|
||||
|
||||
#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
|
||||
wxString envstr = ExpandEnvVarSubstitutions( "${XDG_CONFIG_HOME}" );
|
||||
|
||||
if( envstr.IsEmpty() || envstr == "${XDG_CONFIG_HOME}" )
|
||||
{
|
||||
// XDG_CONFIG_HOME is not set, so use the fallback
|
||||
cfgpath.AppendDir( wxT( ".config" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Override the assignment above with XDG_CONFIG_HOME
|
||||
cfgpath.AssignDir( envstr );
|
||||
}
|
||||
#endif
|
||||
|
||||
cfgpath.AppendDir( wxT( "kicad" ) );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
}
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, "%s:%s:%d\n * failed to create 3D configuration directory '%s'",
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgpath.GetPath() );
|
||||
|
||||
return wxT( "" );
|
||||
}
|
||||
|
||||
if( Set3DConfigDir( cfgpath.GetPath() ) )
|
||||
return m_ConfigDir;
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
|
||||
{
|
||||
bool hasChanged = false;
|
||||
|
||||
if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
|
||||
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged )
|
||||
{
|
||||
m_CacheMap.clear();
|
||||
|
||||
@@ -506,16 +670,23 @@ bool S3D_CACHE::SetProject( PROJECT* aProject )
|
||||
void S3D_CACHE::SetProgramBase( PGM_BASE* aBase )
|
||||
{
|
||||
m_FNResolver->SetProgramBase( aBase );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FILENAME_RESOLVER* S3D_CACHE::GetResolver() noexcept
|
||||
wxString S3D_CACHE::GetProjectDir( void )
|
||||
{
|
||||
return m_FNResolver->GetProjectDir();
|
||||
}
|
||||
|
||||
|
||||
FILENAME_RESOLVER* S3D_CACHE::GetResolver( void )
|
||||
{
|
||||
return m_FNResolver;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_CACHE::GetFileFilters() const
|
||||
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const
|
||||
{
|
||||
return m_Plugins->GetFileFilters();
|
||||
}
|
||||
@@ -537,32 +708,35 @@ void S3D_CACHE::FlushCache( bool closePlugins )
|
||||
|
||||
if( closePlugins )
|
||||
ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::ClosePlugins()
|
||||
void S3D_CACHE::ClosePlugins( void )
|
||||
{
|
||||
if( m_Plugins )
|
||||
if( NULL != m_Plugins )
|
||||
m_Plugins->ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
|
||||
{
|
||||
S3D_CACHE_ENTRY* cp = nullptr;
|
||||
SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, aEmbeddedFiles );
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
SCENEGRAPH* sp = load( aModelFileName, &cp );
|
||||
|
||||
if( !sp )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
if( !cp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY" ),
|
||||
"%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY",
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( cp->renderData )
|
||||
@@ -574,43 +748,27 @@ S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& a
|
||||
return mp;
|
||||
}
|
||||
|
||||
void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
|
||||
|
||||
wxString S3D_CACHE::GetModelHash( const wxString& aModelFileName )
|
||||
{
|
||||
wxDir dir;
|
||||
wxString fileSpec = wxT( "*.3dc" );
|
||||
wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
|
||||
size_t numFilesFound = 0;
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFileName );
|
||||
|
||||
wxFileName thisFile;
|
||||
wxDateTime lastAccess, thresholdDate;
|
||||
wxDateSpan durationInDays;
|
||||
if( full3Dpath.empty() || !wxFileName::FileExists( full3Dpath ) )
|
||||
return wxEmptyString;
|
||||
|
||||
// Calc the threshold date above which we delete cache files
|
||||
durationInDays.SetDays( aNumDaysOld );
|
||||
thresholdDate = wxDateTime::Now() - durationInDays;
|
||||
// check cache if file is already loaded
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
// If the cache directory can be found and opened, then we'll try and clean it up
|
||||
if( dir.Open( m_CacheDir ) )
|
||||
{
|
||||
thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
|
||||
if( mi != m_CacheMap.end() )
|
||||
return mi->second->GetCacheBaseName();
|
||||
|
||||
// Get a list of all the ".3dc" files in the cache directory
|
||||
numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
|
||||
// a cache item does not exist; search the Filename->Cachename map
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
checkCache( full3Dpath, &cp );
|
||||
|
||||
for( unsigned int i = 0; i < numFilesFound; i++ )
|
||||
{
|
||||
// Completes path to specific file so we can get its "last access" date
|
||||
thisFile.SetFullName( fileList[i] );
|
||||
if( NULL != cp )
|
||||
return cp->GetCacheBaseName();
|
||||
|
||||
// Only get "last access" time to compare against. Don't need the other 2 timestamps.
|
||||
if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
|
||||
{
|
||||
if( lastAccess.IsEarlierThan( thresholdDate ) )
|
||||
{
|
||||
// This file is older than the threshold so delete it
|
||||
wxRemoveFile( thisFile.GetFullPath() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
+140
-128
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,146 +23,79 @@
|
||||
|
||||
/**
|
||||
* @file 3d_cache.h
|
||||
* defines the display data cache manager for 3D models
|
||||
*/
|
||||
|
||||
#ifndef CACHE_3D_H
|
||||
#define CACHE_3D_H
|
||||
|
||||
#include "3d_info.h"
|
||||
#include <core/typeinfo.h>
|
||||
#include "string_utils.h"
|
||||
#include <hash_128.h>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
#include <project.h>
|
||||
#include <wx/string.h>
|
||||
#include "kicad_string.h"
|
||||
#include "filename_resolver.h"
|
||||
#include "3d_info.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
|
||||
class EMBEDDED_FILES;
|
||||
class PGM_BASE;
|
||||
class S3D_CACHE;
|
||||
class S3D_CACHE_ENTRY;
|
||||
class SCENEGRAPH;
|
||||
class FILENAME_RESOLVER;
|
||||
class S3D_PLUGIN_MANAGER;
|
||||
|
||||
|
||||
/**
|
||||
* Cache for storing the 3D shapes. This cache is able to be stored as a project
|
||||
* element (since it inherits from PROJECT::_ELEM).
|
||||
*/
|
||||
class S3D_CACHE : public PROJECT::_ELEM
|
||||
class S3D_CACHE
|
||||
{
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
PROJECT::ELEM ProjectElementType() noexcept override
|
||||
{
|
||||
return PROJECT::ELEM::S3DCACHE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration directory to be used by the model manager for storing 3D
|
||||
* model manager configuration data and the model cache.
|
||||
*
|
||||
* The config directory may only be set once in the lifetime of the object.
|
||||
*
|
||||
* @param aConfigDir is the configuration directory to use for 3D model manager data
|
||||
* @return true on success
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Set the current project's working directory; this affects the model search path.
|
||||
*/
|
||||
bool SetProject( PROJECT* aProject );
|
||||
|
||||
/**
|
||||
* Set the filename resolver's pointer to the application's PGM_BASE instance.
|
||||
*
|
||||
* The pointer is used to extract the local environment variables.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
/**
|
||||
* Attempt to load the scene data for a model.
|
||||
*
|
||||
* It will consult the internal cache list and load from cache if possible before invoking
|
||||
* the load() function of the available plugins. The model may fail to load if, for example,
|
||||
* the plugin does not support rendering of the 3D model.
|
||||
|
||||
*
|
||||
* @param aModelFile is the partial or full path to the model to be loaded.
|
||||
* @param aBasePath is the path to search for any relative files
|
||||
* @param aEmbeddedFiles is a pointer to the embedded files list.
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles );
|
||||
|
||||
FILENAME_RESOLVER* GetResolver() noexcept;
|
||||
|
||||
/**
|
||||
* Return the list of file filters retrieved from the plugins.
|
||||
*
|
||||
* This will contain at least the default "All Files (*.*)|*.*"
|
||||
*
|
||||
* @return a pointer to the filter list.
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters() const;
|
||||
|
||||
/**
|
||||
* Free all data in the cache and by default closes all plugins.
|
||||
*/
|
||||
void FlushCache( bool closePlugins = true );
|
||||
|
||||
/**
|
||||
* Unload plugins to free memory.
|
||||
*/
|
||||
void ClosePlugins();
|
||||
|
||||
/**
|
||||
* Attempt to load the scene data for a model and to translate it into an S3D_MODEL
|
||||
* structure for display by a renderer.
|
||||
*
|
||||
* @param aModelFileName is the full path to the model to be loaded.
|
||||
* @param aBasePath is the path to search for any relative files.
|
||||
* @param aEmbeddedFiles is a pointer to the embedded files list.
|
||||
* @return is a pointer to the render data or NULL if not available.
|
||||
*/
|
||||
S3DMODEL* GetModel( const wxString& aModelFileName, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles );
|
||||
|
||||
/**
|
||||
* Delete up old cache files in cache directory.
|
||||
*
|
||||
* Deletes ".3dc" files in the cache directory that are older than \a aNumDaysOld.
|
||||
*
|
||||
* @param aNumDaysOld is age threshold to delete ".3dc" cache files.
|
||||
*/
|
||||
void CleanCacheDir( int aNumDaysOld );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Find or create cache entry for file name
|
||||
/// cache entries
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
|
||||
/// mapping of file names to cache names and data
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString > m_CacheMap;
|
||||
|
||||
/// object to resolve file names
|
||||
FILENAME_RESOLVER* m_FNResolver;
|
||||
|
||||
/// plugin manager
|
||||
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||
|
||||
/// set true if the cache needs to be updated
|
||||
bool m_DirtyCache;
|
||||
|
||||
/// 3D cache directory
|
||||
wxString m_CacheDir;
|
||||
|
||||
/// base configuration path for 3D items
|
||||
wxString m_ConfigDir;
|
||||
|
||||
/// current KiCad project dir
|
||||
wxString m_ProjDir;
|
||||
|
||||
/** Find or create cache entry for file name
|
||||
*
|
||||
* Searches the cache list for the given filename and retrieves the cache data; a cache
|
||||
* entry is created if one does not already exist.
|
||||
* Searches the cache list for the given filename and retrieves
|
||||
* the cache data; a cache entry is created if one does not
|
||||
* already exist.
|
||||
*
|
||||
* @param aFileName is the file name (full or partial path).
|
||||
* @param aCachePtr is an optional return address for cache entry pointer.
|
||||
* @return SCENEGRAPH object associated with file name or NULL on error.
|
||||
* @param[in] aFileName file name (full or partial path)
|
||||
* @param[out] aCachePtr optional return address for cache entry pointer
|
||||
* @return SCENEGRAPH object associated with file name
|
||||
* @retval NULL on error
|
||||
*/
|
||||
SCENEGRAPH* checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr = nullptr );
|
||||
SCENEGRAPH* checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
/**
|
||||
* Calculate the SHA1 hash of the given file.
|
||||
* Function getSHA1
|
||||
* calculates the SHA1 hash of the given file
|
||||
*
|
||||
* @param aFileName file name (full path).
|
||||
* @param aHash a 128 bit hash to hold the hash.
|
||||
* @return true on success, otherwise false.
|
||||
* @param[in] aFileName file name (full path)
|
||||
* @param[out] aSHA1Sum a 20 byte character array to hold the SHA1 hash
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
*/
|
||||
bool getHash( const wxString& aFileName, HASH_128& aHash );
|
||||
bool getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum );
|
||||
|
||||
// load scene data from a cache file
|
||||
bool loadCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
@@ -172,23 +104,103 @@ private:
|
||||
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
// the real load function (can supply a cache entry pointer to member functions)
|
||||
SCENEGRAPH* load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
S3D_CACHE_ENTRY** aCachePtr = nullptr,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles = nullptr );
|
||||
SCENEGRAPH* load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
/// Cache entries.
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
/// Mapping of file names to cache names and data.
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString > m_CacheMap;
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* Sets the configuration directory to be used by the
|
||||
* model manager for storing 3D model manager configuration
|
||||
* data and the model cache. The config directory may only be
|
||||
* set once in the lifetime of the object.
|
||||
*
|
||||
* @param aConfigDir is the configuration directory to use
|
||||
* for 3D model manager data
|
||||
* @return true on success
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
FILENAME_RESOLVER* m_FNResolver;
|
||||
/**
|
||||
* Function Get3DConfigDir
|
||||
* returns the current 3D configuration directory on
|
||||
* success, otherwise it returns wxEmptyString. If the
|
||||
* directory was not previously set via Set3DConfigDir()
|
||||
* then a default is used which is based on kicad's
|
||||
* configuration directory code as of September 2015.
|
||||
*/
|
||||
wxString Get3DConfigDir( bool createDefault = false );
|
||||
|
||||
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current project's working directory; this
|
||||
* affects the model search path
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir );
|
||||
|
||||
PROJECT* m_project;
|
||||
wxString m_CacheDir;
|
||||
wxString m_ConfigDir; ///< base configuration path for 3D items.
|
||||
/**
|
||||
* Function SetProgramBase
|
||||
* sets the filename resolver's pointer to the application's
|
||||
* PGM_BASE instance; the pointer is used to extract the
|
||||
* local env vars.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
/**
|
||||
* Function GetProjectDir
|
||||
* returns the current project's working directory
|
||||
*/
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function Load
|
||||
* attempts to load the scene data for a model; it will consult the
|
||||
* internal cache list and load from cache if possible before invoking
|
||||
* the load() function of the available plugins.
|
||||
*
|
||||
* @param aModelFile [in] is the partial or full path to the model to be loaded
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
* The model may fail to load if, for example, the plugin does not
|
||||
* support rendering of the 3D model.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile );
|
||||
|
||||
FILENAME_RESOLVER* GetResolver( void );
|
||||
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters retrieved from the plugins;
|
||||
* this will contain at least the default "All Files (*.*)|*.*"
|
||||
*
|
||||
* @return a pointer to the filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
/**
|
||||
* Function FlushCache
|
||||
* frees all data in the cache and by default closes all plugins
|
||||
*/
|
||||
void FlushCache( bool closePlugins = true );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* unloads plugins to free memory
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function GetModel
|
||||
* attempts to load the scene data for a model and to translate it
|
||||
* into an S3D_MODEL structure for display by a renderer
|
||||
*
|
||||
* @param aModelFileName is the full path to the model to be loaded
|
||||
* @return is a pointer to the render data or NULL if not available
|
||||
*/
|
||||
S3DMODEL* GetModel( const wxString& aModelFileName );
|
||||
|
||||
wxString GetModelHash( const wxString& aModelFileName );
|
||||
};
|
||||
|
||||
#endif // CACHE_3D_H
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <common.h>
|
||||
#include <pgm_base.h>
|
||||
#include "3d_cache_wrapper.h"
|
||||
|
||||
static wxCriticalSection lock3D_wrapper;
|
||||
|
||||
CACHE_WRAPPER::CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CACHE_WRAPPER::~CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE* PROJECT::Get3DCacheManager( bool updateProjDir )
|
||||
{
|
||||
wxCriticalSectionLocker lock( lock3D_wrapper );
|
||||
CACHE_WRAPPER* cw = (CACHE_WRAPPER*) GetElem( ELEM_3DCACHE );
|
||||
S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
// check that we get the expected type of object or NULL
|
||||
wxASSERT( !cw || cache );
|
||||
|
||||
if( !cw )
|
||||
{
|
||||
cw = new CACHE_WRAPPER;
|
||||
cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
wxFileName cfgpath;
|
||||
cfgpath.AssignDir( GetKicadConfigPath() );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
cache->SetProgramBase( &Pgm() );
|
||||
cache->Set3DConfigDir( cfgpath.GetFullPath() );
|
||||
SetElem( ELEM_3DCACHE, cw );
|
||||
updateProjDir = true;
|
||||
}
|
||||
|
||||
if( updateProjDir )
|
||||
cache->SetProjectDir( GetProjectPath() );
|
||||
|
||||
return cache;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_WRAPPER_3D_H
|
||||
#define CACHE_WRAPPER_3D_H
|
||||
|
||||
#include <project.h>
|
||||
#include "3d_cache.h"
|
||||
|
||||
class CACHE_WRAPPER : public S3D_CACHE, public PROJECT::_ELEM
|
||||
{
|
||||
public:
|
||||
KICAD_T Type() override { return CACHE_WRAPPER_T; }
|
||||
|
||||
CACHE_WRAPPER();
|
||||
virtual ~CACHE_WRAPPER();
|
||||
};
|
||||
|
||||
#endif // CACHE_WRAPPER_3D_H
|
||||
@@ -5,7 +5,7 @@
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -36,12 +36,12 @@
|
||||
#include <wx/string.h>
|
||||
#include <plugins/3dapi/sg_base.h>
|
||||
|
||||
class FP_3DMODEL;
|
||||
class MODULE_3D_SETTINGS;
|
||||
|
||||
struct S3D_INFO
|
||||
{
|
||||
S3D_INFO();
|
||||
S3D_INFO( const FP_3DMODEL& aModel );
|
||||
S3D_INFO( const MODULE_3D_SETTINGS& aModel );
|
||||
|
||||
SGPOINT m_Scale; ///< scaling factors for the 3D footprint shape
|
||||
SGPOINT m_Rotation; ///< an X,Y,Z rotation (unit = degrees) for the 3D shape
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -27,35 +26,29 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <wx/config.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <paths.h>
|
||||
#include <wx_filename.h>
|
||||
#include "common.h"
|
||||
#include "pgm_base.h"
|
||||
#include "3d_plugin_dir.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3d/3d_plugin.h"
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
#include "plugins/ldr/3d/pluginldr3D.h"
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable 3D plugin manager debug tracing.
|
||||
*
|
||||
* Use "KI_TRACE_EDA_3D_VIEWER" to enable.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
#define MASK_3D_PLUGINMGR "3D_PLUGIN_MANAGER"
|
||||
|
||||
|
||||
S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
// create the initial file filter list entry
|
||||
m_FileFilters.emplace_back( _( "All Files" ) + wxT( " (*.*)|*.*" ) );
|
||||
m_FileFilters.push_back( _( "All Files (*.*)|*.*" ) );
|
||||
|
||||
// discover and load plugins
|
||||
loadPlugins();
|
||||
@@ -65,19 +58,19 @@ S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::const_iterator sM = m_ExtMap.begin();
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::const_iterator eM = m_ExtMap.end();
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * Extension [plugin name]:\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * Extension [plugin name]:\n" );
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " + '%s' [%s]\n" ), sM->first.GetData(),
|
||||
sM->second->GetKicadPluginName() );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s' [%s]\n", sM->first.GetData(),
|
||||
sM->second->GetKicadPluginName() );
|
||||
++sM;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * No plugins available\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No plugins available\n" );
|
||||
}
|
||||
|
||||
|
||||
@@ -86,19 +79,21 @@ S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
/// list of file filters
|
||||
std::list< wxString >::const_iterator sFF = m_FileFilters.begin();
|
||||
std::list< wxString >::const_iterator eFF = m_FileFilters.end();
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * File filters:\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * File filters:\n" );
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " + '%s'\n" ), (*sFF).GetData() );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s'\n", (*sFF).GetData() );
|
||||
++sFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * No file filters available\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No file filters available\n" );
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,87 +110,89 @@ S3D_PLUGIN_MANAGER::~S3D_PLUGIN_MANAGER()
|
||||
}
|
||||
|
||||
m_Plugins.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
{
|
||||
std::list<wxString> searchpaths;
|
||||
std::list<wxString> pluginlist;
|
||||
wxFileName fn;
|
||||
std::list< wxString > searchpaths;
|
||||
std::list< wxString > pluginlist;
|
||||
wxFileName fn;
|
||||
|
||||
#ifndef __WXMAC__
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
|
||||
#ifdef DEBUG
|
||||
// set up to work from the build directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.AppendDir( wxT("..") );
|
||||
fn.AppendDir( wxT("plugins") );
|
||||
fn.AppendDir( wxT("3d") );
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
|
||||
// add subdirectories too
|
||||
wxDir debugPluginDir;
|
||||
wxString subdir;
|
||||
|
||||
debugPluginDir.Open( testpath );
|
||||
|
||||
if( debugPluginDir.IsOpened() &&
|
||||
debugPluginDir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
|
||||
{
|
||||
// set up to work from the build directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.AppendDir( wxT( ".." ) );
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
|
||||
// add subdirectories too
|
||||
wxDir debugPluginDir;
|
||||
wxString subdir;
|
||||
|
||||
debugPluginDir.Open( testpath );
|
||||
|
||||
if( debugPluginDir.IsOpened()
|
||||
&& debugPluginDir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
|
||||
{
|
||||
while( debugPluginDir.GetNext( &subdir ) )
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
|
||||
while( debugPluginDir.GetNext( &subdir ) )
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fn.AssignDir( PATHS::GetStockPlugins3DPath() );
|
||||
#ifndef _WIN32
|
||||
// PLUGINDIR = CMAKE_INSTALL_FULL_LIBDIR path is the absolute path
|
||||
// corresponding to the install path used for constructing KICAD_USER_PLUGIN
|
||||
|
||||
wxString tfname = wxString::FromUTF8Unchecked( PLUGINDIR );
|
||||
fn.Assign( tfname, "");
|
||||
fn.AppendDir( "kicad" );
|
||||
#else
|
||||
// on windows the plugins directory is within the executable's directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
#endif
|
||||
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
|
||||
// checks plugin directory relative to executable path
|
||||
checkPluginPath( std::string( fn.GetPathWithSep().ToUTF8() ), searchpaths );
|
||||
|
||||
// check for per-user third party plugins
|
||||
// note: GetUserDataDir() gives '.pcbnew' rather than '.kicad' since it uses the exe name;
|
||||
fn.Assign( wxStandardPaths::Get().GetUserDataDir(), "" );
|
||||
fn.RemoveLastDir();
|
||||
#ifdef _WIN32
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
#else
|
||||
fn.AppendDir( wxT( ".kicad" ) );
|
||||
#endif
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
#else
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
// Exe will be at <build_dir>/pcbnew/pcbnew.app/Contents/MacOS/pcbnew for standalone
|
||||
// Plugin will be at <build_dir>/kicad/KiCad.app/Contents/PlugIns/3d
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
|
||||
if( fn.GetName() == wxT( "kicad" ) )
|
||||
{
|
||||
fn.AppendDir( wxT( ".." ) ); // Contents
|
||||
}
|
||||
else
|
||||
{
|
||||
fn.AppendDir( wxT( ".." ) ); // Contents
|
||||
fn.AppendDir( wxT( ".." ) ); // pcbnew.app
|
||||
fn.AppendDir( wxT( ".." ) ); // pcbnew
|
||||
fn.AppendDir( wxT( ".." ) ); // Build root
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
fn.AppendDir( wxT( "KiCad.app" ) );
|
||||
fn.AppendDir( wxT( "Contents" ) );
|
||||
}
|
||||
// Search path on OS X is
|
||||
// (1) User ~/Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( GetOSXKicadUserDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (2) Machine /Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( GetOSXKicadMachineDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (3) Bundle kicad.app/Contents/PlugIns/3d
|
||||
fn.Assign( Pgm().GetExecutablePath() );
|
||||
fn.AppendDir( wxT( "Contents" ) );
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
fn.MakeAbsolute();
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
|
||||
// Also check when running KiCad manager from build dir
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search path on OS X is
|
||||
// (1) Machine /Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( PATHS::GetOSXKicadMachineDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
|
||||
// (2) Bundle kicad.app/Contents/PlugIns/3d
|
||||
fn.AssignDir( PATHS::GetStockPlugins3DPath() );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
}
|
||||
#endif
|
||||
|
||||
std::list< wxString >::iterator sPL = searchpaths.begin();
|
||||
@@ -203,9 +200,14 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] searching path: '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, (*sPL).ToUTF8() );
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << " * [DEBUG] searching path: '" << (*sPL).ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
listPlugins( *sPL, pluginlist );
|
||||
++sPL;
|
||||
}
|
||||
@@ -222,21 +224,32 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
|
||||
if( pp->Open( sPL->ToUTF8() ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] adding plugin" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] adding plugin";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
m_Plugins.push_back( pp );
|
||||
int nf = pp->GetNFilters();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] adding %d filters" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, nf );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] adding " << nf << " filters";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nf; ++i )
|
||||
{
|
||||
char const* cp = pp->GetFileFilter( i );
|
||||
|
||||
if( cp )
|
||||
addFilterString( cp );
|
||||
addFilterString( wxString::FromUTF8Unchecked( cp ) );
|
||||
}
|
||||
|
||||
addExtensionMap( pp );
|
||||
@@ -246,24 +259,39 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] deleting plugin" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] deleting plugin";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
delete pp;
|
||||
}
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] plugins loaded" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] plugins loaded";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath, std::list< wxString >& aPluginList )
|
||||
void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// list potential plugins given a search path
|
||||
wxString nameFilter; // filter for user-loadable libraries (aka footprints)
|
||||
|
||||
wxString nameFilter; // filter for user-loadable libraries (aka modules)
|
||||
wxString lName; // stores name of enumerated files
|
||||
wxString fName; // full name of file
|
||||
wxDir wd;
|
||||
@@ -282,7 +310,7 @@ void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath, std::list< wxString
|
||||
// Per definition a loadable "xxx.bundle" is similar to an "xxx.app" app
|
||||
// bundle being a folder with some special content in it. We obviously don't
|
||||
// want to have that here for our loadable module, so just use ".so".
|
||||
nameFilter.Append( wxS( ".so" ) );
|
||||
nameFilter.Append( ".so" );
|
||||
#endif
|
||||
|
||||
wxString lp = wd.GetNameWithSep();
|
||||
@@ -300,20 +328,27 @@ void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath, std::list< wxString
|
||||
}
|
||||
|
||||
wd.Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// check the existence of a plugin name and add it to the list
|
||||
|
||||
if( aPath.empty() || !wxFileName::FileExists( aPath ) )
|
||||
return;
|
||||
|
||||
wxFileName path( ExpandEnvVarSubstitutions( aPath, nullptr ) );
|
||||
wxFileName path;
|
||||
|
||||
path.Normalize( FN_NORMALIZE_FLAGS );
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ) );
|
||||
else
|
||||
path.Assign( aPath );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
// determine if the path is already in the list
|
||||
wxString wxpath = path.GetFullPath();
|
||||
@@ -328,34 +363,37 @@ void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
++bl;
|
||||
}
|
||||
|
||||
// prevent loading non-plugin dlls
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
if( !path.GetName().StartsWith( "s3d_plugin" )
|
||||
&& !path.GetName().StartsWith( "libs3d_plugin" ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
aPluginList.push_back( wxpath );
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * [INFO] found 3D plugin '%s'\n" ), wxpath.GetData() );
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] found 3D plugin '%s'\n",
|
||||
wxpath.GetData() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||
std::list< wxString >& aSearchList )
|
||||
std::list< wxString >& aSearchList )
|
||||
{
|
||||
// check the existence of a path and add it to the path search list
|
||||
if( aPath.empty() )
|
||||
return;
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * [INFO] checking if valid plugin directory '%s'\n" ),
|
||||
aPath.GetData() );
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] checking for 3D plugins in '%s'\n",
|
||||
aPath.GetData() );
|
||||
#endif
|
||||
|
||||
wxFileName path;
|
||||
path.AssignDir( aPath );
|
||||
path.Normalize( FN_NORMALIZE_FLAGS );
|
||||
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ), "" );
|
||||
else
|
||||
path.Assign( aPath, "" );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
if( !wxFileName::DirExists( path.GetFullPath() ) )
|
||||
return;
|
||||
@@ -374,6 +412,8 @@ void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||
}
|
||||
|
||||
aSearchList.push_back( wxpath );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -402,13 +442,19 @@ void S3D_PLUGIN_MANAGER::addFilterString( const wxString& aFilterString )
|
||||
void S3D_PLUGIN_MANAGER::addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin )
|
||||
{
|
||||
// add entries to the extension map
|
||||
if( nullptr == aPlugin )
|
||||
if( NULL == aPlugin )
|
||||
return;
|
||||
|
||||
int nExt = aPlugin->GetNExtensions();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [INFO] adding %d extensions" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, nExt );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] adding " << nExt << " extensions";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nExt; ++i )
|
||||
{
|
||||
@@ -416,18 +462,20 @@ void S3D_PLUGIN_MANAGER::addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin )
|
||||
wxString ws;
|
||||
|
||||
if( cp )
|
||||
ws = wxString( cp );
|
||||
ws = wxString::FromUTF8Unchecked( cp );
|
||||
|
||||
if( !ws.empty() )
|
||||
{
|
||||
m_ExtMap.emplace( ws, aPlugin );
|
||||
m_ExtMap.insert( std::pair< const wxString, KICAD_PLUGIN_LDR_3D* >( ws, aPlugin ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const noexcept
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const
|
||||
{
|
||||
return &m_FileFilters;
|
||||
}
|
||||
@@ -436,26 +484,18 @@ std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const no
|
||||
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::string& aPluginInfo )
|
||||
{
|
||||
wxFileName raw( aFileName );
|
||||
wxString ext_to_find = raw.GetExt();
|
||||
wxString ext = raw.GetExt();
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _WIN32
|
||||
// note: plugins only have a lowercase filter within Windows; including an uppercase
|
||||
// filter will result in duplicate file entries and should be avoided.
|
||||
ext_to_find.MakeLower();
|
||||
#endif
|
||||
|
||||
// .gz files are compressed versions that may have additional information in the previous
|
||||
// extension.
|
||||
if( ext_to_find == wxT( "gz" ) )
|
||||
{
|
||||
wxFileName second( raw.GetName() );
|
||||
ext_to_find = second.GetExt() + wxT( ".gz" );
|
||||
}
|
||||
ext.LowerCase();
|
||||
#endif
|
||||
|
||||
std::pair < std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator,
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator > items;
|
||||
|
||||
items = m_ExtMap.equal_range( ext_to_find );
|
||||
items = m_ExtMap.equal_range( ext );
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator sL = items.first;
|
||||
|
||||
while( sL != items.second )
|
||||
@@ -464,7 +504,7 @@ SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::str
|
||||
{
|
||||
SCENEGRAPH* sp = sL->second->Load( aFileName.ToUTF8() );
|
||||
|
||||
if( nullptr != sp )
|
||||
if( NULL != sp )
|
||||
{
|
||||
sL->second->GetPluginInfo( aPluginInfo );
|
||||
return sp;
|
||||
@@ -474,7 +514,7 @@ SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::str
|
||||
++sL;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -483,20 +523,28 @@ void S3D_PLUGIN_MANAGER::ClosePlugins( void )
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator sP = m_Plugins.begin();
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator eP = m_Plugins.end();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [INFO] closing %d extensions" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, static_cast<int>( m_Plugins.size() ) );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] closing " << m_Plugins.size() << " plugins";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
while( sP != eP )
|
||||
{
|
||||
(*sP)->Close();
|
||||
++sP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_PLUGIN_MANAGER::CheckTag( const char* aTag )
|
||||
{
|
||||
if( nullptr == aTag || aTag[0] == 0 || m_Plugins.empty() )
|
||||
if( NULL == aTag || aTag[0] == 0 || m_Plugins.empty() )
|
||||
return false;
|
||||
|
||||
std::string tname = aTag;
|
||||
@@ -519,7 +567,8 @@ bool S3D_PLUGIN_MANAGER::CheckTag( const char* aTag )
|
||||
ptag.clear();
|
||||
(*pS)->GetPluginInfo( ptag );
|
||||
|
||||
// if the plugin name matches then the version must also match
|
||||
// if the plugin name matches then the version
|
||||
// must also match
|
||||
if( !ptag.compare( 0, pname.size(), pname ) )
|
||||
{
|
||||
if( ptag.compare( tname ) )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -41,35 +40,16 @@ class SCENEGRAPH;
|
||||
|
||||
class S3D_PLUGIN_MANAGER
|
||||
{
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/**
|
||||
* Return the list of file filters; this will contain at least the default
|
||||
* "All Files (*.*)|*.*" and the file filters supported by any available plugins.
|
||||
*
|
||||
* @return a pointer to the internal filter list.
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const noexcept;
|
||||
|
||||
SCENEGRAPH* Load3DModel( const wxString& aFileName, std::string& aPluginInfo );
|
||||
|
||||
/**
|
||||
* Iterate through all discovered plugins and closes them to reclaim memory.
|
||||
*
|
||||
* The individual plugins will be automatically reloaded as calls are made to load
|
||||
* specific models.
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Check the given tag and returns true if the plugin named in the tag is not loaded
|
||||
* or the plugin is loaded and the version matches.
|
||||
*/
|
||||
bool CheckTag( const char* aTag );
|
||||
|
||||
private:
|
||||
/// list of discovered plugins
|
||||
std::list< KICAD_PLUGIN_LDR_3D* > m_Plugins;
|
||||
|
||||
/// mapping of extensions to available plugins
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* > m_ExtMap;
|
||||
|
||||
/// list of file filters
|
||||
std::list< wxString > m_FileFilters;
|
||||
|
||||
/// load plugins
|
||||
void loadPlugins( void );
|
||||
|
||||
@@ -88,14 +68,36 @@ private:
|
||||
/// add entries to the extension map
|
||||
void addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin );
|
||||
|
||||
/// list of discovered plugins
|
||||
std::list< KICAD_PLUGIN_LDR_3D* > m_Plugins;
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/// mapping of extensions to available plugins
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* > m_ExtMap;
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters; this will contain at least
|
||||
* the default "All Files (*.*)|*.*" and the file filters supported
|
||||
* by any available plugins
|
||||
*
|
||||
* @return a pointer to the internal filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
/// list of file filters
|
||||
std::list< wxString > m_FileFilters;
|
||||
SCENEGRAPH* Load3DModel( const wxString& aFileName, std::string& aPluginInfo );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* iterates through all discovered plugins and closes them to
|
||||
* reclaim memory. The individual plugins will be automatically
|
||||
* reloaded as calls are made to load specific models.
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function CheckTag
|
||||
* checks the given tag and returns true if the plugin named in the tag
|
||||
* is not loaded or the plugin is loaded and the version matches
|
||||
*/
|
||||
bool CheckTag( const char* aTag );
|
||||
};
|
||||
|
||||
#endif // PLUGIN_MANAGER_3D_H
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <wx/filename.h>
|
||||
|
||||
#include "3d_info.h"
|
||||
#include "3d_cache.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include "dialog_configure_paths.h"
|
||||
#include "dlg_select_3dmodel.h"
|
||||
|
||||
|
||||
bool S3D::Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel )
|
||||
{
|
||||
if( NULL == aModel )
|
||||
return false;
|
||||
|
||||
DLG_SELECT_3DMODEL* dm = new DLG_SELECT_3DMODEL( aParent, aCache, aModel,
|
||||
prevModelSelectDir, prevModelWildcard );
|
||||
|
||||
if( wxID_OK == dm->ShowModal() )
|
||||
{
|
||||
delete dm;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete dm;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::Configure3DPaths( wxWindow* aParent, FILENAME_RESOLVER* aResolver )
|
||||
{
|
||||
DIALOG_CONFIGURE_PATHS dlg( aParent, aResolver );
|
||||
|
||||
return( dlg.ShowModal() == wxID_OK );
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_DIALOGS_3D_H
|
||||
#define CACHE_DIALOGS_3D_H
|
||||
|
||||
#include <wx/window.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class FILENAME_RESOLVER;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel );
|
||||
|
||||
bool Configure3DPaths( wxWindow* aParent, FILENAME_RESOLVER* aResolver );
|
||||
}
|
||||
|
||||
#endif // CACHE_DIALOGS_3D_H
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <set>
|
||||
#include "dlg_select_3dmodel.h"
|
||||
#include "project.h"
|
||||
#include "3d_cache/3d_info.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include <3d_model_viewer/c3d_model_viewer.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
#include <pcbnew/class_module.h>
|
||||
|
||||
#define ID_FILE_TREE ( wxID_LAST + 1 )
|
||||
#define ID_SET_DIR ( ID_FILE_TREE + 1 )
|
||||
#define ID_CFG_PATHS ( ID_SET_DIR + 1 )
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( DLG_SELECT_3DMODEL, DIALOG_SHIM )
|
||||
EVT_DIRCTRL_SELECTIONCHANGED( ID_FILE_TREE, DLG_SELECT_3DMODEL::OnSelectionChanged )
|
||||
EVT_DIRCTRL_FILEACTIVATED( ID_FILE_TREE, DLG_SELECT_3DMODEL::OnFileActivated )
|
||||
EVT_CHOICE( ID_SET_DIR, DLG_SELECT_3DMODEL::SetRootDir )
|
||||
EVT_BUTTON( ID_CFG_PATHS, DLG_SELECT_3DMODEL::Cfg3DPaths )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheManager,
|
||||
MODULE_3D_SETTINGS* aModelItem, wxString& prevModelSelectDir, int& prevModelWildcard ) :
|
||||
DIALOG_SHIM( aParent, wxID_ANY, _( "Select 3D Model" ), wxDefaultPosition,
|
||||
wxSize( 500,200 ), wxCAPTION | wxRESIZE_BORDER | wxCLOSE_BOX
|
||||
| wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxSYSTEM_MENU ),
|
||||
m_model( aModelItem ), m_cache( aCacheManager ), m_previousDir( prevModelSelectDir ),
|
||||
m_previousFilterIndex( prevModelWildcard )
|
||||
{
|
||||
SetSizeHints( wxSize( 500,200 ), wxDefaultSize );
|
||||
|
||||
if( NULL != m_cache )
|
||||
m_resolver = m_cache->GetResolver();
|
||||
else
|
||||
m_resolver = NULL;
|
||||
|
||||
wxBoxSizer* bSizer0 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizer2 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
// set to NULL to avoid segfaults when m_FileTree is instantiated
|
||||
// and wxGenericDirCtrl events are posted
|
||||
m_modelViewer = NULL;
|
||||
dirChoices = NULL;
|
||||
|
||||
m_FileTree = new wxGenericDirCtrl( this, ID_FILE_TREE, prevModelSelectDir, wxDefaultPosition,
|
||||
wxSize( 300,100 ), wxDIRCTRL_3D_INTERNAL | wxDIRCTRL_EDIT_LABELS
|
||||
| wxDIRCTRL_SELECT_FIRST | wxDIRCTRL_SHOW_FILTERS | wxBORDER_SIMPLE, wxEmptyString, 0 );
|
||||
|
||||
|
||||
m_FileTree->ShowHidden( false );
|
||||
m_FileTree->SetMinSize( wxSize( 300, 400 ) );
|
||||
m_FileTree->SetLabel( wxT( "3D_MODEL_SELECTOR" ) );
|
||||
|
||||
bSizer2->Add( m_FileTree, 1, wxEXPAND | wxALL, 5 );
|
||||
bSizer1->Add( bSizer2, 3, wxEXPAND, 5 );
|
||||
|
||||
m_modelViewer = new C3D_MODEL_VIEWER( this, COGL_ATT_LIST::GetAttributesList( true ), m_cache );
|
||||
m_modelViewer->SetMinSize( wxSize( 500, 400 ) );
|
||||
|
||||
bSizer1->Add( m_modelViewer, 5, wxEXPAND | wxALL | wxCENTER, 5 );
|
||||
|
||||
// create the filter list
|
||||
if( NULL != m_cache )
|
||||
{
|
||||
std::list< wxString > const* fl = m_cache->GetFileFilters();
|
||||
std::list< wxString >::const_iterator sL = fl->begin();
|
||||
std::list< wxString >::const_iterator eL = fl->end();
|
||||
wxString filter;
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
filter.Append( *sL );
|
||||
|
||||
++sL;
|
||||
|
||||
if( sL != eL )
|
||||
filter.Append( wxT( "|" ) );
|
||||
}
|
||||
|
||||
if( !filter.empty() )
|
||||
m_FileTree->SetFilter( filter );
|
||||
else
|
||||
m_FileTree->SetFilter( wxFileSelectorDefaultWildcardStr );
|
||||
|
||||
if( prevModelWildcard >= 0 && prevModelWildcard < (int)fl->size() )
|
||||
m_FileTree->SetFilterIndex( prevModelWildcard );
|
||||
else
|
||||
{
|
||||
prevModelWildcard = 0;
|
||||
m_FileTree->SetFilterIndex( 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_FileTree->SetFilter( wxFileSelectorDefaultWildcardStr );
|
||||
prevModelWildcard = 0;
|
||||
m_FileTree->SetFilterIndex( 0 );
|
||||
}
|
||||
|
||||
// Add the path choice box and config button
|
||||
wxBoxSizer* hboxDirChoice = new wxBoxSizer( wxHORIZONTAL );
|
||||
dirChoices = new wxChoice( this, ID_SET_DIR, wxDefaultPosition, wxSize( 320, 20 ) );
|
||||
dirChoices->SetMinSize( wxSize( 320, 12 ) );
|
||||
|
||||
wxStaticText* stDirChoice = new wxStaticText( this, -1, _( "Paths:" ) );
|
||||
wxButton* cfgPaths = new wxButton( this, ID_CFG_PATHS, _( "Configure Paths" ) );
|
||||
hboxDirChoice->Add( stDirChoice, 0, wxALL | wxCENTER, 5 );
|
||||
hboxDirChoice->Add( dirChoices, 1, wxEXPAND | wxALL, 5 );
|
||||
hboxDirChoice->Add( cfgPaths, 0, wxALL, 5 );
|
||||
|
||||
wxButton* btn_OK = new wxButton( this, wxID_OK, _( "OK" ) );
|
||||
wxButton* btn_Cancel = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
|
||||
|
||||
wxStdDialogButtonSizer* hSizer1 = new wxStdDialogButtonSizer();
|
||||
hSizer1->AddButton( btn_OK );
|
||||
hSizer1->AddButton( btn_Cancel );
|
||||
hSizer1->Realize();
|
||||
|
||||
bSizer0->Add( bSizer1, 1, wxALL | wxEXPAND, 5 );
|
||||
bSizer0->Add( hboxDirChoice, 0, wxALL | wxEXPAND, 5 );
|
||||
bSizer0->Add( hSizer1, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
updateDirChoiceList();
|
||||
|
||||
SetSizerAndFit( bSizer0 );
|
||||
Layout();
|
||||
Centre( wxBOTH );
|
||||
|
||||
m_modelViewer->Refresh();
|
||||
m_modelViewer->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
bool DLG_SELECT_3DMODEL::TransferDataFromWindow()
|
||||
{
|
||||
if( NULL == m_model || NULL == m_FileTree )
|
||||
return true;
|
||||
|
||||
m_model->m_Scale.x = 1.0;
|
||||
m_model->m_Scale.y = 1.0;
|
||||
m_model->m_Scale.z = 1.0;
|
||||
|
||||
m_model->m_Rotation.x = 0.0;
|
||||
m_model->m_Rotation.y = 0.0;
|
||||
m_model->m_Rotation.z = 0.0;
|
||||
|
||||
m_model->m_Offset = m_model->m_Rotation;
|
||||
m_model->m_Filename.clear();
|
||||
|
||||
wxString name = m_FileTree->GetFilePath();
|
||||
|
||||
if( name.empty() )
|
||||
return true;
|
||||
|
||||
m_previousDir = m_FileTree->GetPath();
|
||||
m_previousFilterIndex = m_FileTree->GetFilterIndex();
|
||||
|
||||
// file selection mode: retrieve the filename and specify a
|
||||
// path relative to one of the config paths
|
||||
wxFileName fname = m_FileTree->GetFilePath();
|
||||
fname.Normalize();
|
||||
m_model->m_Filename = m_resolver->ShortenPath( fname.GetFullPath() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::OnSelectionChanged( wxTreeEvent& event )
|
||||
{
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::OnFileActivated( wxTreeEvent& event )
|
||||
{
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
SetEscapeId( wxID_OK );
|
||||
Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::SetRootDir( wxCommandEvent& event )
|
||||
{
|
||||
if( m_FileTree && dirChoices->GetSelection() > 0 )
|
||||
m_FileTree->SetPath( dirChoices->GetString( dirChoices->GetSelection() ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::Cfg3DPaths( wxCommandEvent& event )
|
||||
{
|
||||
if( S3D::Configure3DPaths( this, m_resolver ) )
|
||||
updateDirChoiceList();
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::updateDirChoiceList( void )
|
||||
{
|
||||
if( NULL == m_FileTree || NULL == m_resolver || NULL == dirChoices )
|
||||
return;
|
||||
|
||||
std::list< SEARCH_PATH > const* md = m_resolver->GetPaths();
|
||||
std::list< SEARCH_PATH >::const_iterator sL = md->begin();
|
||||
std::list< SEARCH_PATH >::const_iterator eL = md->end();
|
||||
std::set< wxString > cl;
|
||||
wxString prjDir;
|
||||
|
||||
// extract the current project dir
|
||||
if( sL != eL )
|
||||
{
|
||||
prjDir = sL->m_pathexp;
|
||||
++sL;
|
||||
}
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
if( !sL->m_pathexp.empty() && sL->m_pathexp.compare( prjDir ) )
|
||||
cl.insert( sL->m_pathexp );
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
if( !cl.empty() )
|
||||
{
|
||||
unsigned int choice = 0;
|
||||
dirChoices->Clear();
|
||||
dirChoices->Append( "" ); //Insert a blank string at the beginning to allow selection
|
||||
|
||||
if( !prjDir.empty() )
|
||||
{
|
||||
dirChoices->Append( prjDir );
|
||||
|
||||
if( prjDir == m_FileTree->GetPath() )
|
||||
choice = 1;
|
||||
}
|
||||
|
||||
std::set< wxString >::const_iterator sI = cl.begin();
|
||||
std::set< wxString >::const_iterator eI = cl.end();
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
if( *sI == m_FileTree->GetPath() )
|
||||
choice = dirChoices->GetCount();
|
||||
|
||||
dirChoices->Append( *sI );
|
||||
++sI;
|
||||
}
|
||||
|
||||
dirChoices->Select( choice );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file dlg_select_3dmodel.h
|
||||
* creates a dialog to select 3D model files
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DLG_SELECT_3DMODEL_H
|
||||
#define DLG_SELECT_3DMODEL_H
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/dirctrl.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/frame.h>
|
||||
|
||||
#include <dialog_shim.h>
|
||||
|
||||
class MODULE_3D_SETTINGS;
|
||||
class S3D_CACHE;
|
||||
class FILENAME_RESOLVER;
|
||||
class C3D_MODEL_VIEWER;
|
||||
|
||||
class DLG_SELECT_3DMODEL : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
MODULE_3D_SETTINGS* m_model; // data for the selected model
|
||||
S3D_CACHE* m_cache; // cache manager
|
||||
FILENAME_RESOLVER* m_resolver; // 3D filename resolver
|
||||
|
||||
wxString& m_previousDir;
|
||||
int& m_previousFilterIndex;
|
||||
|
||||
wxGenericDirCtrl* m_FileTree;
|
||||
C3D_MODEL_VIEWER* m_modelViewer;
|
||||
wxChoice* dirChoices;
|
||||
|
||||
void updateDirChoiceList( void );
|
||||
|
||||
public:
|
||||
DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheManager, MODULE_3D_SETTINGS* aModelItem,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard );
|
||||
|
||||
bool TransferDataFromWindow() override;
|
||||
void OnSelectionChanged( wxTreeEvent& event );
|
||||
void OnFileActivated( wxTreeEvent& event );
|
||||
void SetRootDir( wxCommandEvent& event );
|
||||
void Cfg3DPaths( wxCommandEvent& event );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
#endif // DLG_SELECT_3DMODEL_H
|
||||
@@ -0,0 +1,310 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.9.0 Nov 1 2020)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "panel_prev_3d_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_PREV_3D_BASE::PANEL_PREV_3D_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
wxBoxSizer* bSizermain;
|
||||
bSizermain = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizerLeft;
|
||||
bSizerLeft = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticBoxSizer* sbSizerScale;
|
||||
sbSizerScale = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Scale") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerScale;
|
||||
fgSizerScale = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerScale->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerScale->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText1 = new wxStaticText( sbSizerScale->GetStaticBox(), wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText1->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText1, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xscale = new wxTextCtrl( sbSizerScale->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( xscale, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXscale = new wxSpinButton( sbSizerScale->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinXscale, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText2 = new wxStaticText( sbSizerScale->GetStaticBox(), wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yscale = new wxTextCtrl( sbSizerScale->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( yscale, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinYscale = new wxSpinButton( sbSizerScale->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinYscale, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText3 = new wxStaticText( sbSizerScale->GetStaticBox(), wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText3->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText3, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
zscale = new wxTextCtrl( sbSizerScale->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( zscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZscale = new wxSpinButton( sbSizerScale->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinZscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
sbSizerScale->Add( fgSizerScale, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( sbSizerScale, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizerRotation;
|
||||
sbSizerRotation = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Rotation") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerRotate;
|
||||
fgSizerRotate = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerRotate->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerRotate->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText11 = new wxStaticText( sbSizerRotation->GetStaticBox(), wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText11->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xrot = new wxTextCtrl( sbSizerRotation->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerRotate->Add( xrot, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXrot = new wxSpinButton( sbSizerRotation->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinXrot, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText21 = new wxStaticText( sbSizerRotation->GetStaticBox(), wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText21->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText21, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yrot = new wxTextCtrl( sbSizerRotation->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerRotate->Add( yrot, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinYrot = new wxSpinButton( sbSizerRotation->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinYrot, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText31 = new wxStaticText( sbSizerRotation->GetStaticBox(), wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText31->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
zrot = new wxTextCtrl( sbSizerRotation->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerRotate->Add( zrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZrot = new wxSpinButton( sbSizerRotation->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinZrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
sbSizerRotation->Add( fgSizerRotate, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( sbSizerRotation, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizerOffset;
|
||||
sbSizerOffset = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Offset") ), wxVERTICAL );
|
||||
|
||||
wxFlexGridSizer* fgSizerOffset;
|
||||
fgSizerOffset = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerOffset->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerOffset->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText12 = new wxStaticText( sbSizerOffset->GetStaticBox(), wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText12->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xoff = new wxTextCtrl( sbSizerOffset->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( xoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXoffset = new wxSpinButton( sbSizerOffset->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinXoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText22 = new wxStaticText( sbSizerOffset->GetStaticBox(), wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText22->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText22, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yoff = new wxTextCtrl( sbSizerOffset->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( yoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinYoffset = new wxSpinButton( sbSizerOffset->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinYoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText32 = new wxStaticText( sbSizerOffset->GetStaticBox(), wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText32->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText32, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
zoff = new wxTextCtrl( sbSizerOffset->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( zoff, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZoffset = new wxSpinButton( sbSizerOffset->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinZoffset, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
sbSizerOffset->Add( fgSizerOffset, 0, wxEXPAND|wxLEFT|wxRIGHT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( sbSizerOffset, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerLeft, 0, 0, 5 );
|
||||
|
||||
wxBoxSizer* bSizerRight;
|
||||
bSizerRight = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticText* staticPreviewLabel;
|
||||
staticPreviewLabel = new wxStaticText( this, wxID_ANY, _("Preview"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
staticPreviewLabel->Wrap( -1 );
|
||||
staticPreviewLabel->SetFont( wxFont( 11, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
|
||||
|
||||
bSizerRight->Add( staticPreviewLabel, 0, wxALL, 5 );
|
||||
|
||||
m_SizerPanelView = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizerRight->Add( m_SizerPanelView, 1, wxEXPAND|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerRight, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 4 );
|
||||
|
||||
wxBoxSizer* bSizer3DButtons;
|
||||
bSizer3DButtons = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( 0, 0, 0, wxEXPAND|wxTOP, 4 );
|
||||
|
||||
m_bpvISO = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
m_bpvISO->SetToolTip( _("Change to isometric perspective") );
|
||||
|
||||
bSizer3DButtons->Add( m_bpvISO, 0, wxTOP|wxBOTTOM, 5 );
|
||||
|
||||
m_bpvLeft = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvLeft, 0, 0, 5 );
|
||||
|
||||
m_bpvRight = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvRight, 0, wxTOP, 5 );
|
||||
|
||||
m_bpvFront = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvFront, 0, wxTOP, 5 );
|
||||
|
||||
m_bpvBack = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvBack, 0, wxTOP, 5 );
|
||||
|
||||
m_bpvTop = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvTop, 0, wxTOP, 5 );
|
||||
|
||||
m_bpvBottom = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
bSizer3DButtons->Add( m_bpvBottom, 0, wxTOP, 5 );
|
||||
|
||||
m_bpUpdate = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
m_bpUpdate->SetToolTip( _("Reload board and 3D models") );
|
||||
|
||||
bSizer3DButtons->Add( m_bpUpdate, 0, wxTOP, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizer3DButtons, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizermain );
|
||||
this->Layout();
|
||||
bSizermain->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
xscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
xscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinXscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
yscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
yscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinYscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
zscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
zscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinZscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
xrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
xrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinXrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
yrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
yrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinYrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
zrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
zrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinZrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
xoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
xoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinXoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
yoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
yoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinYoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
zoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
zoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
m_bpvISO->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DRight ), NULL, this );
|
||||
m_bpvFront->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DFront ), NULL, this );
|
||||
m_bpvBack->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBack ), NULL, this );
|
||||
m_bpvTop->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DTop ), NULL, this );
|
||||
m_bpvBottom->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBottom ), NULL, this );
|
||||
m_bpUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DUpdate ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_PREV_3D_BASE::~PANEL_PREV_3D_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
xscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
xscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinXscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
yscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
yscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinYscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
zscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
zscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinZscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
xrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
xrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinXrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
yrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
yrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinYrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
zrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
zrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinZrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
xoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
xoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinXoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
yoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
yoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinYoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
zoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
zoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
m_bpvISO->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DRight ), NULL, this );
|
||||
m_bpvFront->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DFront ), NULL, this );
|
||||
m_bpvBack->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBack ), NULL, this );
|
||||
m_bpvTop->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DTop ), NULL, this );
|
||||
m_bpvBottom->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBottom ), NULL, this );
|
||||
m_bpUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DUpdate ), NULL, this );
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,105 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.9.0 Nov 1 2020)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/spinbutt.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_PREV_3D_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_PREV_3D_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_staticText1;
|
||||
wxTextCtrl* xscale;
|
||||
wxSpinButton* m_spinXscale;
|
||||
wxStaticText* m_staticText2;
|
||||
wxTextCtrl* yscale;
|
||||
wxSpinButton* m_spinYscale;
|
||||
wxStaticText* m_staticText3;
|
||||
wxTextCtrl* zscale;
|
||||
wxSpinButton* m_spinZscale;
|
||||
wxStaticText* m_staticText11;
|
||||
wxTextCtrl* xrot;
|
||||
wxSpinButton* m_spinXrot;
|
||||
wxStaticText* m_staticText21;
|
||||
wxTextCtrl* yrot;
|
||||
wxSpinButton* m_spinYrot;
|
||||
wxStaticText* m_staticText31;
|
||||
wxTextCtrl* zrot;
|
||||
wxSpinButton* m_spinZrot;
|
||||
wxStaticText* m_staticText12;
|
||||
wxTextCtrl* xoff;
|
||||
wxSpinButton* m_spinXoffset;
|
||||
wxStaticText* m_staticText22;
|
||||
wxSpinButton* m_spinYoffset;
|
||||
wxStaticText* m_staticText32;
|
||||
wxTextCtrl* zoff;
|
||||
wxSpinButton* m_spinZoffset;
|
||||
wxBoxSizer* m_SizerPanelView;
|
||||
wxBitmapButton* m_bpvISO;
|
||||
wxBitmapButton* m_bpvLeft;
|
||||
wxBitmapButton* m_bpvRight;
|
||||
wxBitmapButton* m_bpvFront;
|
||||
wxBitmapButton* m_bpvBack;
|
||||
wxBitmapButton* m_bpvTop;
|
||||
wxBitmapButton* m_bpvBottom;
|
||||
wxBitmapButton* m_bpUpdate;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void onMouseWheelScale( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void updateOrientation( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementScale( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementScale( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelRot( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementRot( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementRot( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelOffset( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void View3DISO( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DLeft( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DRight( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DFront( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBack( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DTop( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBottom( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DUpdate( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
wxTextCtrl* yoff;
|
||||
|
||||
PANEL_PREV_3D_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
~PANEL_PREV_3D_BASE();
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2015-2018 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file panel_prev_model.cpp
|
||||
*/
|
||||
|
||||
#include "panel_prev_model.h"
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
|
||||
#include <class_board.h>
|
||||
|
||||
#include <base_units.h>
|
||||
#include <bitmaps.h>
|
||||
#include <class_drawpanel.h>
|
||||
#include <dpi_scaling.h>
|
||||
#include <pgm_base.h>
|
||||
#include <project.h>
|
||||
|
||||
|
||||
PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, PCB_BASE_FRAME* aFrame, MODULE* aModule,
|
||||
std::vector<MODULE_3D_SETTINGS> *aParentModelList ) :
|
||||
PANEL_PREV_3D_BASE( aParent, wxID_ANY )
|
||||
{
|
||||
m_userUnits = aFrame->GetUserUnits();
|
||||
|
||||
initPanel();
|
||||
|
||||
// Initialize the color settings to draw the board and the footprint
|
||||
m_dummyBoard->SetColorsSettings( &aFrame->Settings().Colors() );
|
||||
|
||||
m_parentModelList = aParentModelList;
|
||||
|
||||
m_dummyModule = new MODULE( *aModule );
|
||||
m_dummyBoard->Add( m_dummyModule );
|
||||
|
||||
// Set 3d viewer configuration for preview
|
||||
m_settings3Dviewer = new CINFO3D_VISU();
|
||||
|
||||
// Create the 3D canvas
|
||||
m_previewPane = new EDA_3D_CANVAS( this, COGL_ATT_LIST::GetAttributesList( true ),
|
||||
m_dummyBoard, *m_settings3Dviewer,
|
||||
aFrame->Prj().Get3DCacheManager() );
|
||||
|
||||
loadCommonSettings();
|
||||
|
||||
m_SizerPanelView->Add( m_previewPane, 1, wxEXPAND, 5 );
|
||||
}
|
||||
|
||||
|
||||
PANEL_PREV_3D::~PANEL_PREV_3D()
|
||||
{
|
||||
delete m_settings3Dviewer;
|
||||
delete m_dummyBoard;
|
||||
delete m_previewPane;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::initPanel()
|
||||
{
|
||||
m_dummyBoard = new BOARD();
|
||||
m_selected = -1;
|
||||
|
||||
// Set the bitmap of 3D view buttons:
|
||||
m_bpvTop->SetBitmap( KiBitmap( axis3d_top_xpm ) );
|
||||
m_bpvFront->SetBitmap( KiBitmap( axis3d_front_xpm ) );
|
||||
m_bpvBack->SetBitmap( KiBitmap( axis3d_back_xpm ) );
|
||||
m_bpvLeft->SetBitmap( KiBitmap( axis3d_left_xpm ) );
|
||||
m_bpvRight->SetBitmap( KiBitmap( axis3d_right_xpm ) );
|
||||
m_bpvBottom->SetBitmap( KiBitmap( axis3d_bottom_xpm ) );
|
||||
m_bpvISO->SetBitmap( KiBitmap( ortho_xpm ) );
|
||||
m_bpUpdate->SetBitmap( KiBitmap( reload_xpm ) );
|
||||
|
||||
// Set the min and max values of spin buttons (mandatory on Linux)
|
||||
// They are not used, so they are set to min and max 32 bits int values
|
||||
// (the min and max values supported by a wxSpinButton)
|
||||
// It avoids blocking the up or down arrows when reaching this limit after
|
||||
// a few clicks.
|
||||
wxSpinButton* spinButtonList[] =
|
||||
{
|
||||
m_spinXscale, m_spinYscale, m_spinZscale,
|
||||
m_spinXrot, m_spinYrot, m_spinZrot,
|
||||
m_spinXoffset,m_spinYoffset, m_spinZoffset
|
||||
};
|
||||
|
||||
for( int ii = 0; ii < 9; ii++ )
|
||||
spinButtonList[ii]->SetRange( INT_MIN, INT_MAX );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::loadCommonSettings()
|
||||
{
|
||||
wxCHECK_RET( m_previewPane, "Cannot load settings to null canvas" );
|
||||
|
||||
wxConfigBase& cmnCfg = *Pgm().CommonSettings();
|
||||
|
||||
{
|
||||
const DPI_SCALING dpi{ &cmnCfg, this };
|
||||
m_previewPane->SetScaleFactor( dpi.GetScaleFactor() );
|
||||
}
|
||||
|
||||
{
|
||||
bool option;
|
||||
cmnCfg.Read( ENBL_MOUSEWHEEL_PAN_KEY, &option, false );
|
||||
m_settings3Dviewer->SetFlag( FL_MOUSEWHEEL_PANNING, option );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief rotationFromString
|
||||
* Ensure -MAX_ROTATION <= rotation <= MAX_ROTATION
|
||||
* aRotation will be normalized between -MAX_ROTATION and MAX_ROTATION
|
||||
*/
|
||||
static double rotationFromString( const wxString& aValue )
|
||||
{
|
||||
double rotation = DoubleValueFromString( DEGREES, aValue ) / 10.0;
|
||||
|
||||
if( rotation > MAX_ROTATION )
|
||||
{
|
||||
int n = rotation / MAX_ROTATION;
|
||||
rotation -= MAX_ROTATION * n;
|
||||
}
|
||||
else if( rotation < -MAX_ROTATION )
|
||||
{
|
||||
int n = -rotation / MAX_ROTATION;
|
||||
rotation += MAX_ROTATION * n;
|
||||
}
|
||||
|
||||
return rotation;
|
||||
}
|
||||
|
||||
|
||||
wxString PANEL_PREV_3D::formatScaleValue( double aValue )
|
||||
{
|
||||
return wxString::Format( "%.4f", aValue );
|
||||
}
|
||||
|
||||
|
||||
wxString PANEL_PREV_3D::formatRotationValue( double aValue )
|
||||
{
|
||||
return wxString::Format( "%.2f %s", aValue, GetAbbreviatedUnitsLabel( DEGREES ) );
|
||||
}
|
||||
|
||||
|
||||
wxString PANEL_PREV_3D::formatOffsetValue( double aValue )
|
||||
{
|
||||
// Convert from internal units (mm) to user units
|
||||
if( m_userUnits == INCHES )
|
||||
aValue /= 25.4f;
|
||||
|
||||
return wxString::Format( "%.4f %s", aValue, GetAbbreviatedUnitsLabel( m_userUnits ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetSelectedModel( int idx )
|
||||
{
|
||||
if( m_parentModelList && idx >= 0 && idx < (int) m_parentModelList->size() )
|
||||
{
|
||||
m_selected = idx;
|
||||
const MODULE_3D_SETTINGS& modelInfo = m_parentModelList->at( (unsigned) m_selected );
|
||||
|
||||
// Use ChangeValue() instead of SetValue(). It's not the user making the change, so we
|
||||
// don't want to generate wxEVT_GRID_CELL_CHANGED events.
|
||||
|
||||
xscale->ChangeValue( formatScaleValue( modelInfo.m_Scale.x ) );
|
||||
yscale->ChangeValue( formatScaleValue( modelInfo.m_Scale.y ) );
|
||||
zscale->ChangeValue( formatScaleValue( modelInfo.m_Scale.z ) );
|
||||
|
||||
xrot->ChangeValue( formatRotationValue( modelInfo.m_Rotation.x ) );
|
||||
yrot->ChangeValue( formatRotationValue( modelInfo.m_Rotation.y ) );
|
||||
zrot->ChangeValue( formatRotationValue( modelInfo.m_Rotation.z ) );
|
||||
|
||||
xoff->ChangeValue( formatOffsetValue( modelInfo.m_Offset.x ) );
|
||||
yoff->ChangeValue( formatOffsetValue( modelInfo.m_Offset.y ) );
|
||||
zoff->ChangeValue( formatOffsetValue( modelInfo.m_Offset.z ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_selected = -1;
|
||||
|
||||
xscale->ChangeValue( wxEmptyString );
|
||||
yscale->ChangeValue( wxEmptyString );
|
||||
zscale->ChangeValue( wxEmptyString );
|
||||
|
||||
xrot->ChangeValue( wxEmptyString );
|
||||
yrot->ChangeValue( wxEmptyString );
|
||||
zrot->ChangeValue( wxEmptyString );
|
||||
|
||||
xoff->ChangeValue( wxEmptyString );
|
||||
yoff->ChangeValue( wxEmptyString );
|
||||
zoff->ChangeValue( wxEmptyString );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::updateOrientation( wxCommandEvent &event )
|
||||
{
|
||||
if( m_parentModelList && m_selected >= 0 && m_selected < (int) m_parentModelList->size() )
|
||||
{
|
||||
// Write settings back to the parent
|
||||
MODULE_3D_SETTINGS* modelInfo = &m_parentModelList->at( (unsigned) m_selected );
|
||||
|
||||
modelInfo->m_Scale.x = DoubleValueFromString( UNSCALED_UNITS, xscale->GetValue() );
|
||||
modelInfo->m_Scale.y = DoubleValueFromString( UNSCALED_UNITS, yscale->GetValue() );
|
||||
modelInfo->m_Scale.z = DoubleValueFromString( UNSCALED_UNITS, zscale->GetValue() );
|
||||
|
||||
modelInfo->m_Rotation.x = rotationFromString( xrot->GetValue() );
|
||||
modelInfo->m_Rotation.y = rotationFromString( yrot->GetValue() );
|
||||
modelInfo->m_Rotation.z = rotationFromString( zrot->GetValue() );
|
||||
|
||||
modelInfo->m_Offset.x = DoubleValueFromString( m_userUnits, xoff->GetValue() ) / IU_PER_MM;
|
||||
modelInfo->m_Offset.y = DoubleValueFromString( m_userUnits, yoff->GetValue() ) / IU_PER_MM;
|
||||
modelInfo->m_Offset.z = DoubleValueFromString( m_userUnits, zoff->GetValue() ) / IU_PER_MM;
|
||||
|
||||
// Update the dummy module for the preview
|
||||
UpdateDummyModule( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::doIncrementScale( wxSpinEvent& event, double aSign )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xscale;
|
||||
|
||||
if( spinCtrl == m_spinYscale )
|
||||
textCtrl = yscale;
|
||||
else if( spinCtrl == m_spinZscale )
|
||||
textCtrl = zscale;
|
||||
|
||||
double curr_value = DoubleValueFromString( UNSCALED_UNITS, textCtrl->GetValue() );
|
||||
|
||||
curr_value += ( SCALE_INCREMENT * aSign );
|
||||
curr_value = std::max( 1/MAX_SCALE, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_SCALE );
|
||||
|
||||
textCtrl->SetValue( formatScaleValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::doIncrementRotation( wxSpinEvent& aEvent, double aSign )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) aEvent.GetEventObject();
|
||||
wxTextCtrl* textCtrl = xrot;
|
||||
|
||||
if( spinCtrl == m_spinYrot )
|
||||
textCtrl = yrot;
|
||||
else if( spinCtrl == m_spinZrot )
|
||||
textCtrl = zrot;
|
||||
|
||||
double curr_value = DoubleValueFromString( DEGREES, textCtrl->GetValue() ) / 10.0;
|
||||
|
||||
curr_value += ( ROTATION_INCREMENT * aSign );
|
||||
curr_value = std::max( -MAX_ROTATION, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_ROTATION );
|
||||
|
||||
textCtrl->SetValue( formatRotationValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::doIncrementOffset( wxSpinEvent& event, double aSign )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xoff;
|
||||
|
||||
if( spinCtrl == m_spinYoffset )
|
||||
textCtrl = yoff;
|
||||
else if( spinCtrl == m_spinZoffset )
|
||||
textCtrl = zoff;
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( m_userUnits == INCHES )
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
|
||||
double curr_value = DoubleValueFromString( m_userUnits, textCtrl->GetValue() ) / IU_PER_MM;
|
||||
|
||||
curr_value += ( step * aSign );
|
||||
curr_value = std::max( -MAX_OFFSET, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_OFFSET );
|
||||
|
||||
textCtrl->SetValue( formatOffsetValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelScale( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = SCALE_INCREMENT;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = SCALE_INCREMENT_FINE;
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
double curr_value = DoubleValueFromString( UNSCALED_UNITS, textCtrl->GetValue() );
|
||||
|
||||
curr_value += step;
|
||||
curr_value = std::max( 1/MAX_SCALE, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_SCALE );
|
||||
|
||||
textCtrl->SetValue( formatScaleValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelRot( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = ROTATION_INCREMENT_WHEEL;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = ROTATION_INCREMENT_WHEEL_FINE;
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
double curr_value = DoubleValueFromString( DEGREES, textCtrl->GetValue() ) / 10.0;
|
||||
|
||||
curr_value += step;
|
||||
curr_value = std::max( -MAX_ROTATION, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_ROTATION );
|
||||
|
||||
textCtrl->SetValue( formatRotationValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelOffset( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = OFFSET_INCREMENT_MM_FINE;
|
||||
|
||||
if( m_userUnits == INCHES )
|
||||
{
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
if( event.ShiftDown( ) )
|
||||
step = OFFSET_INCREMENT_MIL_FINE/1000.0;
|
||||
}
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
double curr_value = DoubleValueFromString( m_userUnits, textCtrl->GetValue() ) / IU_PER_MM;
|
||||
|
||||
curr_value += step;
|
||||
curr_value = std::max( -MAX_OFFSET, curr_value );
|
||||
curr_value = std::min( curr_value, MAX_OFFSET );
|
||||
|
||||
textCtrl->SetValue( formatOffsetValue( curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::UpdateDummyModule( bool aReloadRequired )
|
||||
{
|
||||
m_dummyModule->Models().clear();
|
||||
|
||||
for( size_t i = 0; i < m_parentModelList->size(); ++i )
|
||||
{
|
||||
if( m_parentModelList->at( i ).m_Preview )
|
||||
{
|
||||
m_dummyModule->Models().insert( m_dummyModule->Models().end(),
|
||||
m_parentModelList->at( i ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( aReloadRequired )
|
||||
m_previewPane->ReloadRequest();
|
||||
|
||||
m_previewPane->Request_refresh();
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2015-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file panel_prev_model.h
|
||||
* @brief Defines a panel which is to be added to a wxFileDialog via
|
||||
* SetExtraControl();
|
||||
* The panel shows a preview of the module being edited and provides controls
|
||||
* to set the offset/rotation/scale of each model 3d shape as per KiCad's
|
||||
* current behavior. The panel may also be used in the 3D configuration dialog
|
||||
* to tune the positioning of the models without invoking a file selector dialog.
|
||||
*/
|
||||
|
||||
#ifndef PANEL_PREV_MODEL_H
|
||||
#define PANEL_PREV_MODEL_H
|
||||
|
||||
#include "panel_prev_3d_base.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
|
||||
// Define min and max parameter values
|
||||
#define MAX_SCALE 10000.0
|
||||
#define MAX_ROTATION 180.0
|
||||
#define MAX_OFFSET 1000.0
|
||||
|
||||
#define SCALE_INCREMENT_FINE 0.02
|
||||
#define SCALE_INCREMENT 0.1
|
||||
|
||||
#define ROTATION_INCREMENT 5 // in degrees, for spin button command
|
||||
#define ROTATION_INCREMENT_WHEEL 15 // in degrees, for mouse wheel command
|
||||
#define ROTATION_INCREMENT_WHEEL_FINE 1 // in degrees, for mouse wheel command
|
||||
|
||||
#define OFFSET_INCREMENT_MM 0.5
|
||||
#define OFFSET_INCREMENT_MM_FINE 0.1
|
||||
|
||||
#define OFFSET_INCREMENT_MIL 25.0
|
||||
#define OFFSET_INCREMENT_MIL_FINE 5.0
|
||||
|
||||
|
||||
// Declared classes to create pointers
|
||||
class S3D_CACHE;
|
||||
class FILENAME_RESOLVER;
|
||||
class BOARD;
|
||||
class CINFO3D_VISU;
|
||||
class MODULE;
|
||||
class COLORS_DESIGN_SETTINGS;
|
||||
|
||||
class PANEL_PREV_3D: public PANEL_PREV_3D_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_PREV_3D( wxWindow* aParent, PCB_BASE_FRAME* aFrame, MODULE* aModule,
|
||||
std::vector<MODULE_3D_SETTINGS> *aParentModelList );
|
||||
|
||||
~PANEL_PREV_3D();
|
||||
|
||||
private:
|
||||
EDA_3D_CANVAS* m_previewPane;
|
||||
CINFO3D_VISU* m_settings3Dviewer;
|
||||
|
||||
BOARD* m_dummyBoard;
|
||||
MODULE* m_dummyModule;
|
||||
|
||||
std::vector<MODULE_3D_SETTINGS>* m_parentModelList;
|
||||
int m_selected; /// Index into m_parentInfoList
|
||||
|
||||
EDA_UNITS_T m_userUnits;
|
||||
|
||||
// Methods of the class
|
||||
private:
|
||||
void initPanel();
|
||||
|
||||
/**
|
||||
* Load 3D relevant settings from the user configuration
|
||||
*/
|
||||
void loadCommonSettings();
|
||||
|
||||
/**
|
||||
* @brief updateOrientation - it will receive the events from editing the fields
|
||||
* @param event
|
||||
*/
|
||||
void updateOrientation( wxCommandEvent &event ) override;
|
||||
|
||||
void onMouseWheelScale( wxMouseEvent& event ) override;
|
||||
void onMouseWheelRot( wxMouseEvent& event ) override;
|
||||
void onMouseWheelOffset( wxMouseEvent& event ) override;
|
||||
|
||||
void onIncrementRot( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementRotation( event, 1.0 );
|
||||
}
|
||||
void onDecrementRot( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementRotation( event, -1.0 );
|
||||
}
|
||||
void onIncrementScale( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementScale( event, 1.0 );
|
||||
}
|
||||
void onDecrementScale( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementScale( event, -1.0 );
|
||||
}
|
||||
void onIncrementOffset( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementOffset( event, 1.0 );
|
||||
}
|
||||
void onDecrementOffset( wxSpinEvent& event ) override
|
||||
{
|
||||
doIncrementOffset( event, -1.0 );
|
||||
}
|
||||
|
||||
void doIncrementScale( wxSpinEvent& aEvent, double aSign );
|
||||
void doIncrementRotation( wxSpinEvent& aEvent, double aSign );
|
||||
void doIncrementOffset( wxSpinEvent& aEvent, double aSign );
|
||||
|
||||
wxString formatScaleValue( double aValue );
|
||||
wxString formatRotationValue( double aValue );
|
||||
wxString formatOffsetValue( double aValue );
|
||||
|
||||
void View3DISO( wxCommandEvent& event ) override
|
||||
{
|
||||
m_settings3Dviewer->CameraGet().ToggleProjection();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DLeft( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'X' );
|
||||
}
|
||||
|
||||
void View3DFront( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'Y' );
|
||||
}
|
||||
|
||||
void View3DTop( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'Z' );
|
||||
}
|
||||
|
||||
void View3DUpdate( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DRight( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'X' );
|
||||
}
|
||||
|
||||
void View3DBack( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'Y' );
|
||||
}
|
||||
|
||||
void View3DBottom( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'Z' );
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief SetModelDataIdx - Sets the currently selected index in the model list so that
|
||||
* the scale/rotation/offset controls can be updated.
|
||||
*/
|
||||
void SetSelectedModel( int idx );
|
||||
|
||||
/**
|
||||
* @brief UpdateModelInfoList - copy shapes from the current shape list which are flagged
|
||||
* for preview to the copy of module that is on the preview dummy board
|
||||
*/
|
||||
void UpdateDummyModule( bool aRelaodRequired = true );
|
||||
};
|
||||
|
||||
#endif // PANEL_PREV_MODEL_H
|
||||
@@ -91,7 +91,7 @@ endif()
|
||||
unset( S3DSG_VERSION_FILE CACHE )
|
||||
|
||||
# Define a flag to expose the appropriate EXPORT macro at build time
|
||||
target_compile_definitions( kicad_3dsg PRIVATE COMPILE_SGLIB )
|
||||
target_compile_definitions( kicad_3dsg PRIVATE -DCOMPILE_SGLIB )
|
||||
|
||||
target_link_libraries( kicad_3dsg ${wxWidgets_LIBRARIES} )
|
||||
|
||||
@@ -104,8 +104,3 @@ install( TARGETS
|
||||
LIBRARY DESTINATION ${KICAD_LIB}
|
||||
COMPONENT binary
|
||||
)
|
||||
|
||||
if( KICAD_WIN32_INSTALL_PDBS )
|
||||
# Get the PDBs to copy over for MSVC
|
||||
install(FILES $<TARGET_PDB_FILE:kicad_3dsg> DESTINATION ${KICAD_BIN})
|
||||
endif()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -25,7 +24,6 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
@@ -38,6 +36,10 @@
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static char BadNode[] = " * [BUG] NULL pointer passed for aNode\n";
|
||||
#endif
|
||||
|
||||
// version format of the cache file
|
||||
#define SG_VERSION_TAG "VERSION:2"
|
||||
|
||||
@@ -71,13 +73,15 @@ static void formatMaterial( SMATERIAL& mat, SGAPPEARANCE const* app )
|
||||
|
||||
mat.m_Shininess = app->shininess;
|
||||
mat.m_Transparency = app->transparency;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
bool reuse, bool renameNodes )
|
||||
bool reuse, bool renameNodes )
|
||||
{
|
||||
if( nullptr == filename || filename[0] == 0 )
|
||||
if( NULL == filename || filename[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( filename );
|
||||
@@ -92,19 +96,46 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( aTopNode && aTopNode->GetNodeType() == S3D::SGTYPE_TRANSFORM, false );
|
||||
if( NULL == aTopNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aTopNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != aTopNode->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] aTopNode is not a SCENEGRAPH object";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OPEN_OSTREAM( op, filename );
|
||||
|
||||
if( op.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, filename );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "failed to open file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
op.imbue( std::locale::classic() );
|
||||
op.imbue( std::locale( "C" ) );
|
||||
op << "#VRML V2.0 utf8\n";
|
||||
|
||||
if( renameNodes )
|
||||
@@ -123,8 +154,10 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
|
||||
CLOSE_STREAM( op );
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] problems encountered writing file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, filename );
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "problems encountered writing file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -132,44 +165,102 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
|
||||
void S3D::ResetNodeIndex( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aNode->ResetNodeIndex();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::RenameNodes( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aNode->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::DestroyNode( SGNODE* aNode ) noexcept
|
||||
void S3D::DestroyNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
delete aNode;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
const char* aPluginInfo )
|
||||
const char* aPluginInfo )
|
||||
{
|
||||
if( nullptr == aFileName || aFileName[0] == 0 )
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
wxCHECK( aNode, false );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if( wxFileName::Exists( ofile ) )
|
||||
{
|
||||
if( !overwrite )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] file exists not overwriting '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "file exists; not overwriting" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -177,9 +268,11 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
// make sure we make no attempt to write a directory
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] specified path is a directory '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "specified path is a directory" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -188,27 +281,34 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
|
||||
if( output.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "failed to open file" << " '" << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
output << "(" << SG_VERSION_TAG << ")";
|
||||
|
||||
if( nullptr != aPluginInfo && aPluginInfo[0] != 0 )
|
||||
if( NULL != aPluginInfo && aPluginInfo[0] != 0 )
|
||||
output << "(" << aPluginInfo << ")";
|
||||
else
|
||||
output << "(INTERNAL:0.0.0.0)";
|
||||
|
||||
bool rval = aNode->WriteCache( output, nullptr );
|
||||
bool rval = aNode->WriteCache( output, NULL );
|
||||
CLOSE_STREAM( output );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] problems encountered writing cache file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] problems encountered writing cache file '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
// delete the defective file
|
||||
wxRemoveFile( ofile );
|
||||
@@ -219,31 +319,53 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
|
||||
|
||||
SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
bool (*aTagCheck)( const char*, void* ) )
|
||||
bool (*aTagCheck)( const char*, void* ) )
|
||||
{
|
||||
if( nullptr == aFileName || aFileName[0] == 0 )
|
||||
return nullptr;
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return NULL;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] no such file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "no such file" );
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::unique_ptr<SGNODE> np = std::make_unique<SCENEGRAPH>( nullptr );
|
||||
SGNODE* np = new SCENEGRAPH( NULL );
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] failed to instantiate SCENEGRAPH";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPEN_ISTREAM( file, aFileName );
|
||||
|
||||
if( file.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
return nullptr;
|
||||
delete np;
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "failed to open file" );
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// from SG_VERSION_TAG 1, read the version tag; if it's not the expected tag
|
||||
@@ -256,13 +378,18 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left parenthesis"
|
||||
" at position '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( file.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left parenthesis at position ";
|
||||
ostr << file.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
@@ -276,7 +403,7 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
if( name.compare( SG_VERSION_TAG ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
@@ -291,13 +418,18 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left parenthesis"
|
||||
" at position '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( file.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left parenthesis at position ";
|
||||
ostr << file.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
@@ -309,39 +441,40 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
}
|
||||
|
||||
// check the plugin tag
|
||||
if( nullptr != aTagCheck && nullptr != aPluginMgr
|
||||
&& !aTagCheck( name.c_str(), aPluginMgr ) )
|
||||
if( NULL != aTagCheck && NULL != aPluginMgr && !aTagCheck( name.c_str(), aPluginMgr ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
bool rval = np->ReadCache( file, nullptr );
|
||||
bool rval = np->ReadCache( file, NULL );
|
||||
CLOSE_STREAM( file );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] problems encountered reading cache file "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aFileName );
|
||||
|
||||
return nullptr;
|
||||
delete np;
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "problems encountered reading cache file";
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return np.release();
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
return nullptr;
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
if( aNode->GetNodeType() != S3D::SGTYPE_TRANSFORM )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
S3D::MATLIST materials;
|
||||
std::vector< SMESH > meshes;
|
||||
@@ -351,20 +484,20 @@ S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
// gray in hopes that it may help highlight faulty models; this color is
|
||||
// also typical of MCAD applications. When a model has no associated
|
||||
// material color it shall be assigned the index 0.
|
||||
SGAPPEARANCE app( nullptr );
|
||||
app.ambient = SGCOLOR( 0.6f, 0.6f, 0.6f );
|
||||
app.diffuse = SGCOLOR( 0.6f, 0.6f, 0.6f );
|
||||
SGAPPEARANCE app( NULL );
|
||||
app.ambient = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||
app.diffuse = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||
app.specular = app.diffuse;
|
||||
app.shininess = 0.05f;
|
||||
app.transparency = 0.0f;
|
||||
app.shininess = 0.05;
|
||||
app.transparency = 0.0;
|
||||
|
||||
materials.matorder.push_back( &app );
|
||||
materials.matmap.emplace( &app, 0 );
|
||||
materials.matmap.insert( std::pair< SGAPPEARANCE const*, int >( &app, 0 ) );
|
||||
|
||||
if( aNode->Prepare( nullptr, materials, meshes ) )
|
||||
if( aNode->Prepare( NULL, materials, meshes ) )
|
||||
{
|
||||
if( meshes.empty() )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
S3DMODEL* model = S3D::New3DModel();
|
||||
|
||||
@@ -396,31 +529,35 @@ S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
S3D::Free3DMesh( meshes[i] );
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Destroy3DModel( S3DMODEL** aModel )
|
||||
{
|
||||
if( nullptr == aModel || nullptr == *aModel )
|
||||
if( NULL == aModel || NULL == *aModel )
|
||||
return;
|
||||
|
||||
S3DMODEL* m = *aModel;
|
||||
S3D::FREE_S3DMODEL( *m );
|
||||
delete m;
|
||||
*aModel = nullptr;
|
||||
*aModel = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Free3DModel( S3DMODEL& aModel )
|
||||
{
|
||||
S3D::FREE_S3DMODEL( aModel );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Free3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::FREE_SMESH( aMesh );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -435,17 +572,20 @@ S3DMODEL* S3D::New3DModel( void )
|
||||
void S3D::Init3DMaterial( SMATERIAL& aMat )
|
||||
{
|
||||
S3D::INIT_SMATERIAL( aMat );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Init3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::INIT_SMESH( aMesh );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor, unsigned char* Patch,
|
||||
unsigned char* Revision ) noexcept
|
||||
void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor,
|
||||
unsigned char* Patch, unsigned char* Revision )
|
||||
{
|
||||
if( Major )
|
||||
*Major = KICADSG_VERSION_MAJOR;
|
||||
@@ -458,6 +598,8 @@ void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor, unsigned ch
|
||||
|
||||
if( Patch )
|
||||
*Patch = KICADSG_VERSION_PATCH;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -476,7 +618,7 @@ SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT&
|
||||
|
||||
// normal
|
||||
tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
(void)glm::normalize( tri );
|
||||
glm::normalize( tri );
|
||||
|
||||
return SGVECTOR( tri.x, tri.y, tri.z );
|
||||
}
|
||||
@@ -484,7 +626,7 @@ SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT&
|
||||
|
||||
S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return SGTYPE_END;
|
||||
|
||||
return aNode->GetNodeType();
|
||||
@@ -493,8 +635,8 @@ S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode )
|
||||
|
||||
SGNODE* S3D::GetSGNodeParent( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
return nullptr;
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
return aNode->GetParent();
|
||||
}
|
||||
@@ -502,7 +644,7 @@ SGNODE* S3D::GetSGNodeParent( SGNODE* aNode )
|
||||
|
||||
bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( nullptr == aParent || nullptr == aChild )
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddRefNode( aChild );
|
||||
@@ -511,7 +653,7 @@ bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||
|
||||
bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( nullptr == aParent || nullptr == aChild )
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddChildNode( aChild );
|
||||
@@ -520,8 +662,10 @@ bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||
|
||||
void S3D::AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr )
|
||||
{
|
||||
if( nullptr == aObject || nullptr == aRefPtr || aObject != *aRefPtr )
|
||||
if( NULL == aObject || NULL == aRefPtr || aObject != *aRefPtr )
|
||||
return;
|
||||
|
||||
aObject->AssociateWrapper( aRefPtr );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -30,39 +29,55 @@
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,28 +85,39 @@ IFSG_APPEARANCE::IFSG_APPEARANCE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +126,7 @@ bool IFSG_APPEARANCE::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,13 +152,17 @@ bool IFSG_APPEARANCE::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGAPPEARANCE" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGAPPEARANCE";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +176,17 @@ bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -154,131 +194,279 @@ bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetEmissive( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetEmissive( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetEmissive( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetSpecular( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetSpecular( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetSpecular( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetAmbient( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetAmbient( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetAmbient( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetShininess( float aShininess ) noexcept
|
||||
bool IFSG_APPEARANCE::SetShininess( float aShininess )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aShininess < 0 || aShininess > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] shininess out of range [0..1]" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] shininess out of range [0..1]";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
( (SGAPPEARANCE*) m_node )->shininess = aShininess;
|
||||
((SGAPPEARANCE*)m_node)->shininess = aShininess;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetTransparency( float aTransparency ) noexcept
|
||||
bool IFSG_APPEARANCE::SetTransparency( float aTransparency )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aTransparency < 0 || aTransparency > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] transparency out of range [0..1]" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] transparency out of range [0..1]";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
( (SGAPPEARANCE*) m_node )->transparency = aTransparency;
|
||||
((SGAPPEARANCE*)m_node)->transparency = aTransparency;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -30,38 +29,52 @@
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
return ;
|
||||
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d" ), __FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,29 +82,39 @@ IFSG_COLORS::IFSG_COLORS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Braces needed due to dangling else warning from wxLogTrace macro
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +123,7 @@ bool IFSG_COLORS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,12 +149,17 @@ bool IFSG_COLORS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOLORS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOLORS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,7 +173,17 @@ bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -153,17 +191,37 @@ bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_COLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGCOLORS*) m_node )->GetColorList( aListSize, aColorList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOLORS*)m_node)->GetColorList( aListSize, aColorList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOLORS*) m_node )->SetColorList( aListSize, aColorList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->SetColorList( aListSize, aColorList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -171,9 +229,19 @@ bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
|
||||
bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOLORS*) m_node )->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -181,9 +249,19 @@ bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueVa
|
||||
|
||||
bool IFSG_COLORS::AddColor( const SGCOLOR& aColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOLORS*) m_node )->AddColor( aColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aColor );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,39 +30,50 @@
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGCOORDINDEX( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDINDEX( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,25 +83,35 @@ IFSG_COORDINDEX::IFSG_COORDINDEX( IFSG_NODE& aParent )
|
||||
|
||||
if( !pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node = new SGCOORDINDEX( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +120,7 @@ bool IFSG_COORDINDEX::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,13 +146,17 @@ bool IFSG_COORDINDEX::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOORDINDEX" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOORDINDEX";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +170,17 @@ bool IFSG_COORDINDEX::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -30,39 +29,52 @@
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,28 +82,39 @@ IFSG_COORDS::IFSG_COORDS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +123,7 @@ bool IFSG_COORDS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,12 +149,17 @@ bool IFSG_COORDS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOORDS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOORDS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,7 +173,17 @@ bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -153,17 +191,37 @@ bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_COORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGCOORDS*) m_node )->GetCoordsList( aListSize, aCoordsList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOORDS*)m_node)->GetCoordsList( aListSize, aCoordsList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOORDS*) m_node )->SetCoordsList( aListSize, aCoordsList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->SetCoordsList( aListSize, aCoordsList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -171,9 +229,19 @@ bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
|
||||
bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOORDS*) m_node )->AddCoord( aXValue, aYValue, aZValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aXValue, aYValue, aZValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -181,9 +249,19 @@ bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
|
||||
bool IFSG_COORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOORDS*) m_node )->AddCoord( aPoint );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aPoint );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,39 +30,52 @@
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +83,39 @@ IFSG_FACESET::IFSG_FACESET( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +124,7 @@ bool IFSG_FACESET::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +150,17 @@ bool IFSG_FACESET::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGFACESET" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGFACESET";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +174,17 @@ bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -155,7 +193,7 @@ bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||
bool IFSG_FACESET::CalcNormals( SGNODE** aPtr )
|
||||
{
|
||||
if( m_node )
|
||||
return ( (SGFACESET*) m_node )->CalcNormals( aPtr );
|
||||
return ((SGFACESET*)m_node)->CalcNormals( aPtr );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,24 +30,51 @@
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_INDEX::IFSG_INDEX() : IFSG_NODE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGINDEX*) m_node )->GetIndices( nIndices, aIndexList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGINDEX*)m_node)->GetIndices( nIndices, aIndexList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGINDEX*) m_node )->SetIndices( nIndices, aIndexList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->SetIndices( nIndices, aIndexList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -56,9 +82,19 @@ bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
|
||||
bool IFSG_INDEX::AddIndex( int aIndex )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGINDEX*) m_node )->AddIndex( aIndex );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->AddIndex( aIndex );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,17 +30,15 @@
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
|
||||
// collection of common error strings used by the wrappers
|
||||
char BadObject[] = " * [BUG] operating on an invalid wrapper (object may have been deleted)";
|
||||
char BadOperand[] = " * [BUG] parameter aNode is an invalid wrapper; its data may have been deleted";
|
||||
char BadParent[] = " * [BUG] invalid parent node (data may have been deleted)";
|
||||
char WrongParent[] = " * [BUG] parent node type is incompatible";
|
||||
|
||||
|
||||
IFSG_NODE::IFSG_NODE()
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +46,8 @@ IFSG_NODE::~IFSG_NODE()
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,11 +57,13 @@ void IFSG_NODE::Destroy( void )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::GetRawPtr( void ) noexcept
|
||||
SGNODE* IFSG_NODE::GetRawPtr( void )
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
@@ -70,7 +71,17 @@ SGNODE* IFSG_NODE::GetRawPtr( void ) noexcept
|
||||
|
||||
S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||
{
|
||||
wxCHECK( m_node, S3D::SGTYPE_END );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
return m_node->GetNodeType();
|
||||
}
|
||||
@@ -78,7 +89,17 @@ S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||
|
||||
SGNODE* IFSG_NODE::GetParent( void ) const
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetParent();
|
||||
}
|
||||
@@ -86,7 +107,17 @@ SGNODE* IFSG_NODE::GetParent( void ) const
|
||||
|
||||
bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->SetParent( aParent );
|
||||
}
|
||||
@@ -94,40 +125,90 @@ bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||
|
||||
const char* IFSG_NODE::GetName( void )
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetName();
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::SetName( const char* aName )
|
||||
bool IFSG_NODE::SetName( const char *aName )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->SetName( aName );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char* IFSG_NODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
const char * IFSG_NODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetNodeTypeName( aNodeType );
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::FindNode( const char* aNodeName )
|
||||
SGNODE* IFSG_NODE::FindNode( const char *aNodeName )
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return m_node->FindNode( aNodeName, nullptr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->FindNode( aNodeName, NULL );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddRefNode( aNode );
|
||||
}
|
||||
@@ -135,11 +216,31 @@ bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||
|
||||
bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = aNode.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadOperand;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddRefNode( np );
|
||||
}
|
||||
@@ -147,7 +248,17 @@ bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||
|
||||
bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddChildNode( aNode );
|
||||
}
|
||||
@@ -155,11 +266,31 @@ bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||
|
||||
bool IFSG_NODE::AddChildNode( IFSG_NODE& aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = aNode.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadOperand;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddChildNode( np );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,39 +30,53 @@
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +84,39 @@ IFSG_NORMALS::IFSG_NORMALS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +125,7 @@ bool IFSG_NORMALS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +151,17 @@ bool IFSG_NORMALS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGNORMALS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGNORMALS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +175,17 @@ bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -154,34 +193,74 @@ bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_NORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGNORMALS*) m_node )->GetNormalList( aListSize, aNormalList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGNORMALS*)m_node)->GetNormalList( aListSize, aNormalList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGNORMALS*) m_node )->SetNormalList( aListSize, aNormalList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->SetNormalList( aListSize, aNormalList );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGNORMALS*) m_node )->AddNormal( aXValue, aYValue, aZValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aXValue, aYValue, aZValue );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGNORMALS*) m_node )->AddNormal( aNormal );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aNormal );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,39 +30,53 @@
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +84,39 @@ IFSG_SHAPE::IFSG_SHAPE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +125,7 @@ bool IFSG_SHAPE::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +151,17 @@ bool IFSG_SHAPE::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGSHAPE" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGSHAPE";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +175,17 @@ bool IFSG_SHAPE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,38 +30,52 @@
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SCENEGRAPH( nullptr );
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SCENEGRAPH( nullptr );
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +84,7 @@ bool IFSG_TRANSFORM::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -97,12 +110,17 @@ bool IFSG_TRANSFORM::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SCENEGRAPH" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SCENEGRAPH";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,7 +134,17 @@ bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -124,20 +152,40 @@ bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_TRANSFORM::SetRotation( const SGVECTOR& aRotationAxis, double aAngle )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->rotation_axis = aRotationAxis;
|
||||
( (SCENEGRAPH*) m_node )->rotation_angle = aAngle;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->rotation_axis = aRotationAxis;
|
||||
((SCENEGRAPH*)m_node)->rotation_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale ) noexcept
|
||||
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->scale = aScale;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = aScale;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -145,27 +193,51 @@ bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale ) noexcept
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( double aScale )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
|
||||
if( aScale < 1e-8 && aScale > -1e-8 )
|
||||
if( NULL == m_node )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] |scale| is < 1e-8 - this seems strange" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
( (SCENEGRAPH*) m_node )->scale = SGPOINT( aScale, aScale, aScale );
|
||||
if( aScale < 1e-8 && aScale > -1e-8 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] |scale| is < 1e-8 - this seems strange";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = SGPOINT( aScale, aScale, aScale );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation ) noexcept
|
||||
bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->translation = aTranslation;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->translation = aTranslation;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -173,20 +245,40 @@ bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation ) noexcept
|
||||
|
||||
bool IFSG_TRANSFORM::SetScaleOrientation( const SGVECTOR& aScaleAxis, double aAngle )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->scale_axis = aScaleAxis;
|
||||
( (SCENEGRAPH*) m_node )->scale_angle = aAngle;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale_axis = aScaleAxis;
|
||||
((SCENEGRAPH*)m_node)->scale_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter ) noexcept
|
||||
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->center = aCenter;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->center = aCenter;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -45,19 +44,24 @@ SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
|
||||
scale.y = 1.0;
|
||||
scale.z = 1.0;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SCENEGRAPH (type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SCENEGRAPH (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,12 +74,14 @@ SCENEGRAPH::~SCENEGRAPH()
|
||||
// delete owned objects
|
||||
DEL_OBJS( SCENEGRAPH, m_Transforms );
|
||||
DEL_OBJS( SGSHAPE, m_Shape );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -84,14 +90,14 @@ bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a transform may be parent to a transform
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -105,8 +111,8 @@ bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
|
||||
SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
@@ -115,8 +121,8 @@ SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
FIND_NODE( SGSHAPE, aNodeName, m_Shape, aCaller );
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -124,26 +130,33 @@ SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
|
||||
void SCENEGRAPH::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
switch( aNode->GetNodeType() )
|
||||
{
|
||||
case S3D::SGTYPE_TRANSFORM:
|
||||
UNLINK_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms,
|
||||
isChild );
|
||||
break;
|
||||
case S3D::SGTYPE_TRANSFORM:
|
||||
UNLINK_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||
break;
|
||||
|
||||
case S3D::SGTYPE_SHAPE:
|
||||
UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
break;
|
||||
case S3D::SGTYPE_SHAPE:
|
||||
UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,16 +176,30 @@ void SCENEGRAPH::unlinkRefNode( const SGNODE* aNode )
|
||||
|
||||
bool SCENEGRAPH::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ADD_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||
ADD_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] object '%s' is not a valid type for this object (%d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aNode->GetName(),
|
||||
aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -210,7 +237,7 @@ void SCENEGRAPH::ReNameNodes( void )
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
// rename all transforms
|
||||
do
|
||||
@@ -224,13 +251,16 @@ void SCENEGRAPH::ReNameNodes( void )
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( m_Transforms.empty() && m_RTransforms.empty() && m_Shape.empty() && m_RShape.empty() )
|
||||
if( m_Transforms.empty() && m_RTransforms.empty()
|
||||
&& m_Shape.empty() && m_RShape.empty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -336,14 +366,14 @@ bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode && nullptr != m_Parent )
|
||||
if( NULL == parentNode && NULL != m_Parent )
|
||||
{
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -352,9 +382,19 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
if( nullptr == m_Parent )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
// ensure unique node names
|
||||
ResetNodeIndex();
|
||||
@@ -363,8 +403,12 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( aFile.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -420,9 +464,12 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !m_Transforms[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] bad stream while writing child transforms" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream while writing child transforms";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -430,20 +477,21 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RTransforms.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RTransforms[i]->GetName() << "]";
|
||||
|
||||
// write child shapes
|
||||
asize = m_Shape.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_Shape[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] bad stream while writing child shapes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream while writing child shapes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -451,7 +499,6 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RShape.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RShape[i]->GetName() << "]";
|
||||
|
||||
@@ -465,20 +512,33 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( m_Transforms.empty() && m_RTransforms.empty() && m_Shape.empty() && m_RShape.empty(),
|
||||
false );
|
||||
if( !m_Transforms.empty() || !m_RTransforms.empty()
|
||||
|| !m_Shape.empty() || !m_RShape.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name; // name of the node
|
||||
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
// we need to read the tag and verify its type
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; tag mismatch at position "
|
||||
"%ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; tag mismatch at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -512,10 +572,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child transform tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child transform tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -525,10 +588,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading transform "
|
||||
"%ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading transform '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -539,10 +605,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref transform tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref transform tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -551,20 +620,26 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref "
|
||||
"transform at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref transform '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != sp->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not TRANSFORM "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not TRANSFORM '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -577,10 +652,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child shape tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child shape tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -590,10 +668,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; corrupt data while "
|
||||
"reading shape at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading shape '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -604,10 +685,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref shape tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref shape tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -616,20 +700,26 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref shape "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref shape '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_SHAPE != sp->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGSHAPE at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGSHAPE '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -644,27 +734,21 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes )
|
||||
bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
// calculate the accumulated transform
|
||||
double rX, rY, rZ;
|
||||
|
||||
// rotation
|
||||
rotation_axis.GetVector( rX, rY, rZ );
|
||||
glm::dmat4 rM = glm::rotate( glm::dmat4( 1.0 ), rotation_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
|
||||
// translation
|
||||
glm::dmat4 tM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( translation.x, translation.y,
|
||||
translation.z ) );
|
||||
glm::dmat4 tM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( translation.x, translation.y, translation.z ) );
|
||||
// center
|
||||
glm::dmat4 cM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( center.x, center.y, center.z ) );
|
||||
glm::dmat4 ncM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( -center.x, -center.y,
|
||||
-center.z ) );
|
||||
|
||||
glm::dmat4 ncM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( -center.x, -center.y, -center.z ) );
|
||||
// scale
|
||||
glm::dmat4 sM = glm::scale( glm::dmat4( 1.0 ), glm::dvec3( scale.x, scale.y, scale.z ) );
|
||||
|
||||
// scaleOrientation
|
||||
scale_axis.GetVector( rX, rY, rZ );
|
||||
glm::dmat4 srM = glm::rotate( glm::dmat4( 1.0 ), scale_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
@@ -676,7 +760,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
// tx0 = tM * cM * rM * srM * sM * nsrM * ncM
|
||||
glm::dmat4 tx0;
|
||||
|
||||
if( nullptr != aTransform )
|
||||
if( NULL != aTransform )
|
||||
tx0 = (*aTransform) * tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
else
|
||||
tx0 = tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
@@ -704,7 +788,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
// prepare all transforms
|
||||
do
|
||||
@@ -727,7 +811,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,10 @@
|
||||
|
||||
/**
|
||||
* @file scenegraph.h
|
||||
* defines the basic data set required to represent a 3D model;
|
||||
* this model must remain compatible with VRML2.0 in order to
|
||||
* facilitate VRML export of scene graph data created by available
|
||||
* 3D plugins.
|
||||
*/
|
||||
|
||||
|
||||
@@ -35,18 +38,38 @@
|
||||
|
||||
class SGSHAPE;
|
||||
|
||||
/**
|
||||
* Define the basic data set required to represent a 3D model.
|
||||
*
|
||||
* This model must remain compatible with VRML2.0 in order to facilitate VRML export of
|
||||
* scene graph data created by available 3D plugins.
|
||||
*/
|
||||
class SCENEGRAPH : public SGNODE
|
||||
{
|
||||
private:
|
||||
// The following are items which may be defined for reuse
|
||||
// in a VRML output file. They do not necessarily correspond
|
||||
// to the use of DEF within a VRML input file; it is the
|
||||
// responsibility of the plugin to perform any necessary
|
||||
// conversions to comply with the restrictions imposed by
|
||||
// this scene graph structure
|
||||
std::vector< SCENEGRAPH* > m_Transforms; // local Transform nodes
|
||||
std::vector< SGSHAPE* > m_Shape; // local Shape nodes
|
||||
|
||||
std::vector< SCENEGRAPH* > m_RTransforms; // referenced Transform nodes
|
||||
std::vector< SGSHAPE* > m_RShape; // referenced Shape nodes
|
||||
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
// note: order of transformation is Translate, Rotate, Offset
|
||||
SGPOINT center;
|
||||
SGPOINT translation;
|
||||
SGVECTOR rotation_axis;
|
||||
double rotation_angle; // radians
|
||||
SGPOINT scale;
|
||||
SGVECTOR scale_axis;
|
||||
double scale_angle; // radians
|
||||
|
||||
SCENEGRAPH( SGNODE* aParent );
|
||||
virtual ~SCENEGRAPH();
|
||||
|
||||
@@ -61,35 +84,8 @@ public:
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes );
|
||||
|
||||
private:
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
// note: order of transformation is Translate, Rotate, Offset
|
||||
SGPOINT center;
|
||||
SGPOINT translation;
|
||||
SGVECTOR rotation_axis;
|
||||
double rotation_angle; // radians
|
||||
SGPOINT scale;
|
||||
SGVECTOR scale_axis;
|
||||
double scale_angle; // radians
|
||||
|
||||
private:
|
||||
// The following are items which may be defined for reuse
|
||||
// in a VRML output file. They do not necessarily correspond
|
||||
// to the use of DEF within a VRML input file; it is the
|
||||
// responsibility of the plugin to perform any necessary
|
||||
// conversions to comply with the restrictions imposed by
|
||||
// this scene graph structure
|
||||
std::vector< SCENEGRAPH* > m_Transforms; // local Transform nodes
|
||||
std::vector< SGSHAPE* > m_Shape; // local Shape nodes
|
||||
|
||||
std::vector< SCENEGRAPH* > m_RTransforms; // referenced Transform nodes
|
||||
std::vector< SGSHAPE* > m_RShape; // referenced Shape nodes
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -30,40 +29,46 @@
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent )
|
||||
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent)
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_APPEARANCE;
|
||||
|
||||
// defaults in accord with VRML2.0 spec
|
||||
ambient.SetColor( 0.05317f, 0.17879f, 0.01804f );
|
||||
shininess = 0.2f;
|
||||
transparency = 0.0f;
|
||||
diffuse.SetColor( 0.8f, 0.8f, 0.8f );
|
||||
ambient.SetColor( 0.05317, 0.17879, 0.01804 );
|
||||
shininess = 0.2;
|
||||
transparency = 0.0;
|
||||
diffuse.SetColor( 0.8, 0.8, 0.8 );
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGAPPEARANCE (type %s )" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGAPPEARANCE (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGAPPEARANCE::~SGAPPEARANCE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -72,14 +77,14 @@ bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGSHAPE may be parent to a SGAPPEARANCE
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -99,7 +104,17 @@ bool SGAPPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return emissive.SetColor( aRGBColor );
|
||||
}
|
||||
@@ -119,7 +134,17 @@ bool SGAPPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return diffuse.SetColor( aRGBColor );
|
||||
}
|
||||
@@ -139,7 +164,17 @@ bool SGAPPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return specular.SetColor( aRGBColor );
|
||||
}
|
||||
@@ -158,7 +193,17 @@ bool SGAPPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ambient.SetColor( aRGBColor );
|
||||
}
|
||||
@@ -170,46 +215,66 @@ bool SGAPPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGAPPEARANCE::FindNode( const char* aNodeName, const SGNODE* aCaller) noexcept
|
||||
SGNODE* SGAPPEARANCE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK_MSG( aCaller, /* void */,
|
||||
wxT( "unexpected code branch; node should have no children or refs" ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK_MSG( aCaller, /* void */,
|
||||
wxT( "unexpected code branch; node should have no children or refs" ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGAPPEARANCE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK_MSG( aNode, false, wxT( "this node does not accept children or refs" ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
// This is redundant but it keeps gcc from generating a warning on debug builds.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK_MSG( aNode, false, wxT( "this node does not accept children or refs" ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
// This is redundant but it keeps gcc from generating a warning on debug builds.
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -253,13 +318,13 @@ bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
diffuse.GetColor( ambr, ambg, ambb );
|
||||
float den = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
|
||||
|
||||
if( den < 0.004f )
|
||||
den = 0.004f;
|
||||
if( den < 0.004 )
|
||||
den = 0.004;
|
||||
|
||||
amb /= den;
|
||||
|
||||
if( amb > 1.0f )
|
||||
amb = 1.0f;
|
||||
if( amb > 1.0 )
|
||||
amb = 1.0;
|
||||
|
||||
S3D::FormatFloat( tmp, amb );
|
||||
aFile << " ambientIntensity " << tmp << "\n";
|
||||
@@ -303,16 +368,26 @@ bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK_MSG( m_Parent, false, wxT( "corrupt data; m_aParent is NULL" ) );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -321,20 +396,34 @@ bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK_MSG( parentNode == m_Parent, false, wxT( "corrupt data; parentNode != m_aParent" ) );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
S3D::WriteColor( aFile, ambient );
|
||||
aFile.write( (char*) &shininess, sizeof( shininess ) );
|
||||
aFile.write( (char*) &transparency, sizeof( transparency ) );
|
||||
aFile.write( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.write( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::WriteColor( aFile, diffuse );
|
||||
S3D::WriteColor( aFile, emissive );
|
||||
S3D::WriteColor( aFile, specular );
|
||||
@@ -350,8 +439,8 @@ bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
bool SGAPPEARANCE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
S3D::ReadColor( aFile, ambient );
|
||||
aFile.read( (char*) &shininess, sizeof( shininess ) );
|
||||
aFile.read( (char*) &transparency, sizeof( transparency ) );
|
||||
aFile.read( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.read( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::ReadColor( aFile, diffuse );
|
||||
S3D::ReadColor( aFile, emissive );
|
||||
S3D::ReadColor( aFile, specular );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_appearance.h
|
||||
* defines the generic material appearance of a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_APPEARANCE_H
|
||||
@@ -31,15 +31,20 @@
|
||||
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Defines the generic material appearance of a scenegraph object.
|
||||
*/
|
||||
class SGAPPEARANCE : public SGNODE
|
||||
{
|
||||
public:
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
float shininess; // default 0.2
|
||||
float transparency; // default 0.0
|
||||
SGCOLOR ambient; // default 0.05317 0.17879 0.01804
|
||||
SGCOLOR diffuse; // default 0.8 0.8 0.8
|
||||
SGCOLOR emissive; // default 0.0 0.0 0.0
|
||||
SGCOLOR specular; // default 0.0 0.0 0.0
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGAPPEARANCE( SGNODE* aParent );
|
||||
virtual ~SGAPPEARANCE();
|
||||
|
||||
@@ -61,23 +66,15 @@ public:
|
||||
bool SetAmbient( const SGCOLOR* aRGBColor );
|
||||
bool SetAmbient( const SGCOLOR& aRGBColor );
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
float shininess; // default 0.2
|
||||
float transparency; // default 0.0
|
||||
SGCOLOR ambient; // default 0.05317 0.17879 0.01804
|
||||
SGCOLOR diffuse; // default 0.8 0.8 0.8
|
||||
SGCOLOR emissive; // default 0.0 0.0 0.0
|
||||
SGCOLOR specular; // default 0.0 0.0 0.0
|
||||
|
||||
};
|
||||
|
||||
#endif // SG_APPEARANCE_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -36,14 +35,20 @@ SGCOLOR::SGCOLOR()
|
||||
red = 0.0;
|
||||
green = 0.0;
|
||||
blue = 0.0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SGCOLOR::SGCOLOR( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( !checkRange( aRVal, aGVal, aBVal ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid value passed to constructor" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid value passed to constructor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
red = 0.0;
|
||||
green = 0.0;
|
||||
blue = 0.0;
|
||||
@@ -53,32 +58,46 @@ SGCOLOR::SGCOLOR( float aRVal, float aGVal, float aBVal )
|
||||
red = aRVal;
|
||||
green = aGVal;
|
||||
blue = aBVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const noexcept
|
||||
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const
|
||||
{
|
||||
aRedVal = red;
|
||||
aGreenVal = green;
|
||||
aBlueVal = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR& aColor ) const noexcept
|
||||
void SGCOLOR::GetColor( SGCOLOR& aColor ) const
|
||||
{
|
||||
aColor.red = red;
|
||||
aColor.green = green;
|
||||
aColor.blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR* aColor ) const noexcept
|
||||
void SGCOLOR::GetColor( SGCOLOR* aColor ) const
|
||||
{
|
||||
wxCHECK_MSG( aColor, /* void */, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aColor->red = red;
|
||||
aColor->green = green;
|
||||
aColor->blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +114,7 @@ bool SGCOLOR::SetColor( float aRedVal, float aGreenVal, float aBlueVal )
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR& aColor ) noexcept
|
||||
bool SGCOLOR::SetColor( const SGCOLOR& aColor )
|
||||
{
|
||||
red = aColor.red;
|
||||
green = aColor.green;
|
||||
@@ -104,9 +123,19 @@ bool SGCOLOR::SetColor( const SGCOLOR& aColor ) noexcept
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR* aColor ) noexcept
|
||||
bool SGCOLOR::SetColor( const SGCOLOR* aColor )
|
||||
{
|
||||
wxCHECK_MSG( aColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
red = aColor->red;
|
||||
green = aColor->green;
|
||||
@@ -115,31 +144,42 @@ bool SGCOLOR::SetColor( const SGCOLOR* aColor ) noexcept
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const noexcept
|
||||
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if( aRedVal < 0.0 || aRedVal > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid RED value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aRedVal );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid RED value: " << aRedVal;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( aGreenVal < 0.0 || aGreenVal > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid GREEN value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aGreenVal );
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ok )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__ );
|
||||
}
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] invalid GREEN value: %f\n", aGreenVal );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( aBlueVal < 0.0 || aBlueVal > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid BLUE value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aBlueVal );
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ok )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__ );
|
||||
}
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] invalid BLUE value: %f\n", aBlueVal );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
@@ -152,10 +192,11 @@ SGPOINT::SGPOINT()
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal ) noexcept
|
||||
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
@@ -163,45 +204,60 @@ SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal ) noexcept
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const double& aXVal, const double& aYVal, const double& aZVal ) noexcept
|
||||
void SGPOINT::GetPoint( double& aXVal, double& aYVal, double& aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const SGPOINT& aPoint ) noexcept
|
||||
void SGPOINT::GetPoint( SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const SGPOINT* aPoint ) noexcept
|
||||
void SGPOINT::GetPoint( SGPOINT* aPoint )
|
||||
{
|
||||
wxCHECK_MSG( aPoint, /* void */, wxT( "NULL pointer passed for aPoint" ) );
|
||||
if( NULL == aPoint )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aPoint";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
x = aPoint->x;
|
||||
y = aPoint->y;
|
||||
z = aPoint->z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( double aXVal, double aYVal, double aZVal ) noexcept
|
||||
void SGPOINT::SetPoint( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( const SGPOINT& aPoint ) noexcept
|
||||
void SGPOINT::SetPoint( const SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +266,7 @@ SGVECTOR::SGVECTOR()
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,14 +276,16 @@ SGVECTOR::SGVECTOR( double aXVal, double aYVal, double aZVal )
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const noexcept
|
||||
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const
|
||||
{
|
||||
aXVal = vx;
|
||||
aYVal = vy;
|
||||
aZVal = vz;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,25 +295,28 @@ void SGVECTOR::SetVector( double aXVal, double aYVal, double aZVal )
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::SetVector( const SGVECTOR& aVector )
|
||||
{
|
||||
aVector.GetVector( vx, vy, vz );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::normalize( void ) noexcept
|
||||
void SGVECTOR::normalize( void )
|
||||
{
|
||||
double dx = vx * vx;
|
||||
double dy = vy * vy;
|
||||
double dz = vz * vz;
|
||||
double dv2 = sqrt( dx + dy + dz );
|
||||
|
||||
if( ( dx + dy + dz ) < 1e-8 )
|
||||
if( (dx + dy + dz) < 1e-8 )
|
||||
{
|
||||
// use the default; the numbers are too small to be believable
|
||||
// use the default; the numbers are too small
|
||||
// to be believable
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
@@ -264,10 +326,12 @@ void SGVECTOR::normalize( void ) noexcept
|
||||
vx /= dv2;
|
||||
vy /= dv2;
|
||||
vz /= dv2;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source ) noexcept
|
||||
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source )
|
||||
{
|
||||
vx = source.vx;
|
||||
vy = source.vy;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -29,35 +28,41 @@
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGCOLORS::SGCOLORS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COLORS;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGCOLORS (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGCOLORS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOLORS::~SGCOLORS()
|
||||
{
|
||||
colors.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -66,14 +71,14 @@ bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOLORS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -85,41 +90,65 @@ bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOLORS::FindNode(const char* aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGCOLORS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOLORS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGCOLORS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGCOLORS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -130,7 +159,7 @@ bool SGCOLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
if( colors.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aColorList = nullptr;
|
||||
aColorList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -144,7 +173,7 @@ void SGCOLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
colors.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aColorList )
|
||||
if( 0 == aListSize || NULL == aColorList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
@@ -156,7 +185,7 @@ void SGCOLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
|
||||
void SGCOLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
colors.emplace_back( aRedValue, aGreenValue, aBlueValue );
|
||||
colors.push_back( SGCOLOR( aRedValue, aGreenValue, aBlueValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -238,16 +267,26 @@ bool SGCOLORS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -256,12 +295,26 @@ bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -283,10 +336,20 @@ bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGCOLORS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( colors.empty(), false );
|
||||
if( !colors.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ncolors;
|
||||
aFile.read( (char*) &ncolors, sizeof( size_t ) );
|
||||
aFile.read( (char*)&ncolors, sizeof(size_t) );
|
||||
SGCOLOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_colors.h
|
||||
* defines an RGB color set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COLORS_H
|
||||
@@ -32,23 +32,23 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define an RGB color set for a scenegraph object.
|
||||
*/
|
||||
class SGCOLORS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGCOLOR > colors;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGCOLORS( SGNODE* aParent );
|
||||
virtual ~SGCOLORS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList );
|
||||
void SetColorList( size_t aListSize, const SGCOLOR* aColorList );
|
||||
@@ -60,8 +60,6 @@ public:
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
std::vector< SGCOLOR > colors;
|
||||
};
|
||||
|
||||
#endif // SG_COLORS_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -29,15 +28,18 @@ SGCOORDINDEX::SGCOORDINDEX( SGNODE* aParent ) : SGINDEX( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDINDEX;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDINDEX::~SGCOORDINDEX()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,4 +49,6 @@ void SGCOORDINDEX::GatherCoordIndices( std::vector< int >& aIndexList )
|
||||
return;
|
||||
|
||||
aIndexList.insert( aIndexList.end(), index.begin(), index.end() );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_coordindex.h
|
||||
* defines an coordinate index set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDINDEX_H
|
||||
@@ -32,12 +32,14 @@
|
||||
#include "3d_cache/sg/sg_index.h"
|
||||
|
||||
/**
|
||||
* An object to maintain a coordinate index list.
|
||||
*
|
||||
* Users must ensure that coordinate indices are specified as triplets (triangular faces)
|
||||
* since no checking is performed. In instances where it is not possible to determine which
|
||||
* side of the triangle is to be rendered (for example IGES entities) then the user must
|
||||
* supply each triplet in both point orders.
|
||||
* Class SGCOORDINDEX
|
||||
* is a class which maintains a coordinate index list. Users
|
||||
* must ensure that coordinate indices are specified as
|
||||
* triplets (triangular faces) since no checking is performed.
|
||||
* In instances where it is not possible to determine which
|
||||
* side of the triangle is to be rendered (for example IGES
|
||||
* entities) then the user must supply each triplet in both
|
||||
* point orders.
|
||||
*/
|
||||
class SGCOORDINDEX : public SGINDEX
|
||||
{
|
||||
@@ -46,7 +48,9 @@ public:
|
||||
virtual ~SGCOORDINDEX();
|
||||
|
||||
/**
|
||||
* Add all coordinate indices to the given list in preparation for a normals calculation.
|
||||
* Function GatherCoordIndices
|
||||
* adds all coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -36,30 +35,37 @@ SGCOORDS::SGCOORDS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDS;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGCOORDS (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGCOORDS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDS::~SGCOORDS()
|
||||
{
|
||||
coords.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -68,14 +74,14 @@ bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOORDS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -87,41 +93,65 @@ bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOORDS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGCOORDS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGCOORDS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -132,7 +162,7 @@ bool SGCOORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
if( coords.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aCoordsList = nullptr;
|
||||
aCoordsList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,23 +176,27 @@ void SGCOORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
coords.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aCoordsList )
|
||||
if( 0 == aListSize || NULL == aCoordsList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
coords.push_back( aCoordsList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
coords.emplace_back( aXValue, aYValue, aZValue );
|
||||
coords.push_back( SGPOINT( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
coords.push_back( aPoint );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -240,16 +274,26 @@ bool SGCOORDS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -258,12 +302,26 @@ bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -285,10 +343,20 @@ bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( coords.empty(), false );
|
||||
if( !coords.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*) &npts, sizeof( size_t ) );
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGPOINT tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
@@ -309,15 +377,15 @@ bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
|
||||
{
|
||||
if( aPtr )
|
||||
*aPtr = nullptr;
|
||||
*aPtr = NULL;
|
||||
|
||||
if( nullptr == m_Parent || nullptr == callingNode )
|
||||
if( NULL == m_Parent || NULL == callingNode )
|
||||
return false;
|
||||
|
||||
// the parent and all references must have indices; collect all
|
||||
// indices into one std::vector<>
|
||||
std::vector< int > ilist;
|
||||
SGNORMALS* np = nullptr;
|
||||
SGNORMALS* np = NULL;
|
||||
|
||||
if( callingNode == m_Parent )
|
||||
{
|
||||
@@ -333,7 +401,7 @@ bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
|
||||
++sB;
|
||||
}
|
||||
|
||||
np = ( (SGFACESET*) m_Parent )->m_Normals;
|
||||
np = ((SGFACESET*)m_Parent)->m_Normals;
|
||||
|
||||
if( !np )
|
||||
np = new SGNORMALS( m_Parent );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_coords.h
|
||||
* defines a vertex coordinate set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDS_H
|
||||
@@ -34,23 +34,23 @@
|
||||
|
||||
class SGFACESET;
|
||||
|
||||
/**
|
||||
* Define a vertex coordinate set for a scenegraph object.
|
||||
*/
|
||||
class SGCOORDS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGPOINT > coords;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGCOORDS( SGNODE* aParent );
|
||||
virtual ~SGCOORDS();
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList );
|
||||
void SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList );
|
||||
@@ -58,18 +58,17 @@ public:
|
||||
void AddCoord( const SGPOINT& aPoint );
|
||||
|
||||
/**
|
||||
* Calculate normals for this coordinate list and sets the normals list in the
|
||||
* parent #SGFACESET.
|
||||
* Function CalcNormals
|
||||
* calculates normals for this coordinate list and sets the
|
||||
* normals list in the parent SGFACESET
|
||||
*/
|
||||
bool CalcNormals( SGFACESET* callingNode, SGNODE** aPtr = nullptr );
|
||||
bool CalcNormals( SGFACESET* callingNode, SGNODE** aPtr = NULL );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
std::vector< SGPOINT > coords;
|
||||
};
|
||||
|
||||
#endif // SG_COORDS_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -34,33 +33,37 @@
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGFACESET::SGFACESET( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_FACESET;
|
||||
m_Colors = nullptr;
|
||||
m_Coords = nullptr;
|
||||
m_CoordIndices = nullptr;
|
||||
m_Normals = nullptr;
|
||||
m_RColors = nullptr;
|
||||
m_RCoords = nullptr;
|
||||
m_RNormals = nullptr;
|
||||
m_Colors = NULL;
|
||||
m_Coords = NULL;
|
||||
m_CoordIndices = NULL;
|
||||
m_Normals = NULL;
|
||||
m_RColors = NULL;
|
||||
m_RCoords = NULL;
|
||||
m_RNormals = NULL;
|
||||
valid = false;
|
||||
validated = false;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGFACESET (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGFACESET (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,55 +73,57 @@ SGFACESET::~SGFACESET()
|
||||
if( m_RColors )
|
||||
{
|
||||
m_RColors->delNodeRef( this );
|
||||
m_RColors = nullptr;
|
||||
m_RColors = NULL;
|
||||
}
|
||||
|
||||
if( m_RCoords )
|
||||
{
|
||||
m_RCoords->delNodeRef( this );
|
||||
m_RCoords = nullptr;
|
||||
m_RCoords = NULL;
|
||||
}
|
||||
|
||||
if( m_RNormals )
|
||||
{
|
||||
m_RNormals->delNodeRef( this );
|
||||
m_RNormals = nullptr;
|
||||
m_RNormals = NULL;
|
||||
}
|
||||
|
||||
// delete owned objects
|
||||
if( m_Colors )
|
||||
{
|
||||
m_Colors->SetParent( nullptr, false );
|
||||
m_Colors->SetParent( NULL, false );
|
||||
delete m_Colors;
|
||||
m_Colors = nullptr;
|
||||
m_Colors = NULL;
|
||||
}
|
||||
|
||||
if( m_Coords )
|
||||
{
|
||||
m_Coords->SetParent( nullptr, false );
|
||||
m_Coords->SetParent( NULL, false );
|
||||
delete m_Coords;
|
||||
m_Coords = nullptr;
|
||||
m_Coords = NULL;
|
||||
}
|
||||
|
||||
if( m_Normals )
|
||||
{
|
||||
m_Normals->SetParent( nullptr, false );
|
||||
m_Normals->SetParent( NULL, false );
|
||||
delete m_Normals;
|
||||
m_Normals = nullptr;
|
||||
m_Normals = NULL;
|
||||
}
|
||||
|
||||
if( m_CoordIndices )
|
||||
{
|
||||
m_CoordIndices->SetParent( nullptr, false );
|
||||
m_CoordIndices->SetParent( NULL, false );
|
||||
delete m_CoordIndices;
|
||||
m_CoordIndices = nullptr;
|
||||
m_CoordIndices = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -127,14 +132,14 @@ bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGSHAPE may be parent to a SGFACESET
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -148,13 +153,13 @@ bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
|
||||
SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
SGNODE* np = nullptr;
|
||||
SGNODE* np = NULL;
|
||||
|
||||
if( m_Colors )
|
||||
{
|
||||
@@ -189,8 +194,8 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
}
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -198,7 +203,7 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
|
||||
void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
valid = false;
|
||||
@@ -208,25 +213,25 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode == m_Colors )
|
||||
{
|
||||
m_Colors = nullptr;
|
||||
m_Colors = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_Coords )
|
||||
{
|
||||
m_Coords = nullptr;
|
||||
m_Coords = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_Normals )
|
||||
{
|
||||
m_Normals = nullptr;
|
||||
m_Normals = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_CoordIndices )
|
||||
{
|
||||
m_CoordIndices = nullptr;
|
||||
m_CoordIndices = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -235,46 +240,66 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
if( aNode == m_RColors )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RColors = nullptr;
|
||||
m_RColors = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RCoords )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RCoords = nullptr;
|
||||
m_RCoords = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RNormals )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RNormals = nullptr;
|
||||
m_RNormals = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGFACESET::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGFACESET::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
valid = false;
|
||||
validated = false;
|
||||
@@ -285,8 +310,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Colors && aNode != m_RColors )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Colors nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Colors nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -314,8 +343,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Coords && aNode != m_RCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Colors nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Coords nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -343,8 +376,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Normals && aNode != m_RNormals )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Normals nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Normals nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -372,9 +409,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_CoordIndices )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] assigning multiple CoordIndex nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple CoordIndex nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -388,11 +428,16 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
return true;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] object type '%s' is not a valid type for "
|
||||
"this object '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aNode->GetName(),
|
||||
aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' (type " << aNode->GetNodeType();
|
||||
ostr << ") is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -432,12 +477,15 @@ void SGFACESET::ReNameNodes( void )
|
||||
// rename all Normals and Indices
|
||||
if( m_Normals )
|
||||
m_Normals->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGFACESET::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( ( nullptr == m_Coords && nullptr == m_RCoords ) || ( nullptr == m_CoordIndices ) )
|
||||
if( ( NULL == m_Coords && NULL == m_RCoords )
|
||||
|| ( NULL == m_CoordIndices ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -492,16 +540,26 @@ bool SGFACESET::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -510,24 +568,38 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if any references are unwritten and swap parents if so
|
||||
if( nullptr != m_RCoords && !m_RCoords->isWritten() )
|
||||
if( NULL != m_RCoords && !m_RCoords->isWritten() )
|
||||
m_RCoords->SwapParent( this );
|
||||
|
||||
if( nullptr != m_RNormals && !m_RNormals->isWritten() )
|
||||
if( NULL != m_RNormals && !m_RNormals->isWritten() )
|
||||
m_RNormals->SwapParent( this );
|
||||
|
||||
if( nullptr != m_RColors && !m_RColors->isWritten() )
|
||||
if( NULL != m_RColors && !m_RColors->isWritten() )
|
||||
m_RColors->SwapParent( this );
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
@@ -539,35 +611,35 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
items[i] = 0;
|
||||
|
||||
i = 0;
|
||||
if( nullptr != m_Coords )
|
||||
if( NULL != m_Coords )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RCoords )
|
||||
if( NULL != m_RCoords )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_CoordIndices )
|
||||
if( NULL != m_CoordIndices )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_Normals )
|
||||
if( NULL != m_Normals )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RNormals )
|
||||
if( NULL != m_RNormals )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_Colors )
|
||||
if( NULL != m_Colors )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RColors )
|
||||
if( NULL != m_RColors )
|
||||
items[i] = true;
|
||||
|
||||
for( int jj = 0; jj < NITEMS; ++jj )
|
||||
aFile.write( (char*) &items[jj], sizeof( bool ) );
|
||||
aFile.write( (char*)&items[jj], sizeof(bool) );
|
||||
|
||||
if( items[0] )
|
||||
m_Coords->WriteCache( aFile, this );
|
||||
@@ -600,11 +672,16 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( m_Coords || m_RCoords || m_CoordIndices || m_Colors || m_RColors || m_Normals
|
||||
|| m_RNormals )
|
||||
if( m_Coords || m_RCoords || m_CoordIndices
|
||||
|| m_Colors || m_RColors
|
||||
|| m_Normals || m_RNormals )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] non-empty node" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -613,14 +690,18 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
bool items[NITEMS];
|
||||
|
||||
for( int i = 0; i < NITEMS; ++i )
|
||||
aFile.read( (char*) &items[i], sizeof( bool ) );
|
||||
aFile.read( (char*)&items[i], sizeof(bool) );
|
||||
|
||||
if( ( items[0] && items[1] ) || ( items[3] && items[4] ) || ( items[5] && items[6] ) )
|
||||
if( ( items[0] && items[1] ) || ( items[3] && items[4] )
|
||||
|| ( items[5] && items[6] ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; multiple item definitions "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; multiple item definitions at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -631,10 +712,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child coords tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child coords tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -644,10 +728,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Coords->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; corrupt data while "
|
||||
"reading coords '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading coords '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -657,10 +744,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref coords tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref coords tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -669,20 +759,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; cannot find ref "
|
||||
"coords '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref coords '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_COORDS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; type is not SGCOORDS "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGCOORDS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -695,10 +791,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDINDEX != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad coord index tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad coord index tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -708,10 +807,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_CoordIndices->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading coord "
|
||||
"index '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading coord index '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -721,10 +823,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_NORMALS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child normals tag "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child normals tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -734,10 +839,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Normals->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading normals "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading normals '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -747,10 +855,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_NORMALS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref normals tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref normals tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -759,19 +870,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt: cannot find ref normals "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref normals '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_NORMALS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt: type is not SGNORMALS '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGNORMALS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -784,10 +902,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COLORS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child colors tag "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child colors tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -797,10 +918,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Colors->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading colors "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading colors '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -810,10 +934,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COLORS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref colors tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref colors tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -822,20 +949,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref colors "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref colors '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_COLORS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGCOLORS "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGCOLORS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -858,14 +991,16 @@ bool SGFACESET::validate( void )
|
||||
return valid;
|
||||
|
||||
// ensure we have at least coordinates and their normals
|
||||
if( ( nullptr == m_Coords && nullptr == m_RCoords )
|
||||
|| ( nullptr == m_Normals && nullptr == m_RNormals )
|
||||
|| ( nullptr == m_CoordIndices ) )
|
||||
if( (NULL == m_Coords && NULL == m_RCoords)
|
||||
|| (NULL == m_Normals && NULL == m_RNormals)
|
||||
|| (NULL == m_CoordIndices) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; no vertices, vertex indices, "
|
||||
"or normals" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; no vertices, vertex indices, or normals";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -874,18 +1009,21 @@ bool SGFACESET::validate( void )
|
||||
// check that there are >3 vertices
|
||||
SGCOORDS* coords = m_Coords;
|
||||
|
||||
if( nullptr == coords )
|
||||
if( NULL == coords )
|
||||
coords = m_RCoords;
|
||||
|
||||
size_t nCoords = 0;
|
||||
SGPOINT* lCoords = nullptr;
|
||||
SGPOINT* lCoords = NULL;
|
||||
coords->GetCoordsList( nCoords, lCoords );
|
||||
|
||||
if( nCoords < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; fewer than 3 vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; fewer than 3 vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -893,15 +1031,17 @@ bool SGFACESET::validate( void )
|
||||
|
||||
// check that nVertices is divisible by 3 (facets are triangles)
|
||||
size_t nCIdx = 0;
|
||||
int* lCIdx = nullptr;
|
||||
int* lCIdx = NULL;
|
||||
m_CoordIndices->GetIndices( nCIdx, lCIdx );
|
||||
|
||||
if( nCIdx < 3 || ( nCIdx % 3 > 0 ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; no vertex indices or not "
|
||||
"multiple of 3" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; no vertex indices or not multiple of 3";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -912,10 +1052,12 @@ bool SGFACESET::validate( void )
|
||||
{
|
||||
if( lCIdx[i] < 0 || lCIdx[i] >= (int)nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; vertex index out of "
|
||||
"bounds" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; vertex index out of bounds";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -924,22 +1066,23 @@ bool SGFACESET::validate( void )
|
||||
|
||||
// check that there are as many normals as vertices
|
||||
size_t nNorms = 0;
|
||||
SGVECTOR* lNorms = nullptr;
|
||||
SGVECTOR* lNorms = NULL;
|
||||
SGNORMALS* pNorms = m_Normals;
|
||||
|
||||
if( nullptr == pNorms )
|
||||
if( NULL == pNorms )
|
||||
pNorms = m_RNormals;
|
||||
|
||||
pNorms->GetNormalList( nNorms, lNorms );
|
||||
|
||||
if( nNorms != nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; number of normals (%ul) does "
|
||||
"not match number of vertices (%ul)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( nNorms ),
|
||||
static_cast<unsigned long>( nCoords ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; number of normals (" << nNorms;
|
||||
ostr << ") does not match number of vertices (" << nCoords << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -948,14 +1091,14 @@ bool SGFACESET::validate( void )
|
||||
// if there are colors then ensure there are as many colors as vertices
|
||||
SGCOLORS* pColors = m_Colors;
|
||||
|
||||
if( nullptr == pColors )
|
||||
if( NULL == pColors )
|
||||
pColors = m_RColors;
|
||||
|
||||
if( nullptr != pColors )
|
||||
if( NULL != pColors )
|
||||
{
|
||||
// we must have at least as many colors as vertices
|
||||
size_t nColor = 0;
|
||||
SGCOLOR* pColor = nullptr;
|
||||
SGCOLOR* pColor = NULL;
|
||||
pColors->GetColorList( nColor, pColor );
|
||||
}
|
||||
|
||||
@@ -969,6 +1112,8 @@ void SGFACESET::GatherCoordIndices( std::vector< int >& aIndexList )
|
||||
{
|
||||
if( m_CoordIndices )
|
||||
m_CoordIndices->GatherCoordIndices( aIndexList );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -979,7 +1124,7 @@ bool SGFACESET::CalcNormals( SGNODE** aPtr )
|
||||
if( m_RCoords )
|
||||
coords = m_RCoords;
|
||||
|
||||
if( nullptr == coords || coords->coords.empty() )
|
||||
if( NULL == coords || coords->coords.empty() )
|
||||
return false;
|
||||
|
||||
if( m_Normals && !m_Normals->norms.empty( ) )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_faceset.h
|
||||
* defines an indexed face set for a scenegraph
|
||||
*/
|
||||
|
||||
|
||||
@@ -40,18 +40,38 @@ class SGNORMALS;
|
||||
class SGCOLORINDEX;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
/**
|
||||
* Define an indexed face set for a scenegraph.
|
||||
*/
|
||||
class SGFACESET : public SGNODE
|
||||
{
|
||||
private:
|
||||
bool valid;
|
||||
bool validated;
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
// owned objects
|
||||
SGCOLORS* m_Colors;
|
||||
SGCOORDS* m_Coords;
|
||||
SGCOORDINDEX* m_CoordIndices;
|
||||
SGNORMALS* m_Normals;
|
||||
|
||||
// referenced objects
|
||||
SGCOLORS* m_RColors;
|
||||
SGCOORDS* m_RCoords;
|
||||
SGNORMALS* m_RNormals;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
// validate the data held by this face set
|
||||
bool validate( void );
|
||||
|
||||
public:
|
||||
SGFACESET( SGNODE* aParent );
|
||||
virtual ~SGFACESET();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode( const char* aNodeName, const SGNODE* aCaller ) override;
|
||||
SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
@@ -64,34 +84,11 @@ public:
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
/**
|
||||
* Add all internal coordinate indices to the given list in preparation for a normals
|
||||
* calculation.
|
||||
* Function GatherCoordIndices
|
||||
* adds all internal coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
// validate the data held by this face set
|
||||
bool validate( void );
|
||||
|
||||
// owned objects
|
||||
SGCOLORS* m_Colors;
|
||||
SGCOORDS* m_Coords;
|
||||
SGCOORDINDEX* m_CoordIndices;
|
||||
SGNORMALS* m_Normals;
|
||||
|
||||
// referenced objects
|
||||
SGCOLORS* m_RColors;
|
||||
SGCOORDS* m_RCoords;
|
||||
SGNORMALS* m_RNormals;
|
||||
|
||||
private:
|
||||
bool valid;
|
||||
bool validated;
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -34,6 +33,7 @@
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
|
||||
// formats a floating point number for text output to a VRML file
|
||||
void S3D::FormatFloat( std::string& result, double value )
|
||||
{
|
||||
if( value < 1e-8 && value > -1e-8 )
|
||||
@@ -49,9 +49,10 @@ void S3D::FormatFloat( std::string& result, double value )
|
||||
|
||||
result = out.str();
|
||||
|
||||
size_t p = result.find( '.' );
|
||||
size_t p = result.find( "." );
|
||||
|
||||
// trim trailing 0 if appropriate
|
||||
|
||||
if( std::string::npos == p )
|
||||
return;
|
||||
|
||||
@@ -59,26 +60,28 @@ void S3D::FormatFloat( std::string& result, double value )
|
||||
|
||||
if( std::string::npos == p )
|
||||
{
|
||||
while( '0' == *( result.rbegin() ) )
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( '0' != result.at( p - 1 ) )
|
||||
if( '0' != result.at( p -1 ) )
|
||||
return;
|
||||
|
||||
// trim all 0 to the left of 'p'
|
||||
std::string tmp = result.substr( p );
|
||||
result = result.substr( 0, p );
|
||||
|
||||
while( '0' == *( result.rbegin() ) )
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format orientation data for VRML output
|
||||
void S3D::FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation )
|
||||
{
|
||||
double aX;
|
||||
@@ -97,9 +100,11 @@ void S3D::FormatOrientation( std::string& result, const SGVECTOR& axis, double r
|
||||
FormatFloat( tmp, rotation );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format point data for VRML output
|
||||
void S3D::FormatPoint( std::string& result, const SGPOINT& point )
|
||||
{
|
||||
FormatFloat( result, point.x );
|
||||
@@ -112,9 +117,12 @@ void S3D::FormatPoint( std::string& result, const SGPOINT& point )
|
||||
FormatFloat( tmp, point.z );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format vector data for VRML output
|
||||
void S3D::FormatVector( std::string& result, const SGVECTOR& aVector )
|
||||
{
|
||||
double X, Y, Z;
|
||||
@@ -129,9 +137,12 @@ void S3D::FormatVector( std::string& result, const SGVECTOR& aVector )
|
||||
FormatFloat( tmp, Z );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format Color data for VRML output
|
||||
void S3D::FormatColor( std::string& result, const SGCOLOR& aColor )
|
||||
{
|
||||
float R, G, B;
|
||||
@@ -146,14 +157,16 @@ void S3D::FormatColor( std::string& result, const SGCOLOR& aColor )
|
||||
FormatFloat( tmp, B );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WritePoint( std::ostream& aFile, const SGPOINT& aPoint )
|
||||
{
|
||||
aFile.write( (char*) &aPoint.x, sizeof( aPoint.x ) );
|
||||
aFile.write( (char*) &aPoint.y, sizeof( aPoint.y ) );
|
||||
aFile.write( (char*) &aPoint.z, sizeof( aPoint.z ) );
|
||||
aFile.write( (char*)&aPoint.x, sizeof(aPoint.x) );
|
||||
aFile.write( (char*)&aPoint.y, sizeof(aPoint.y) );
|
||||
aFile.write( (char*)&aPoint.z, sizeof(aPoint.z) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -166,9 +179,9 @@ bool S3D::WriteVector( std::ostream& aFile, const SGVECTOR& aVector )
|
||||
{
|
||||
double x, y, z;
|
||||
aVector.GetVector( x, y, z );
|
||||
aFile.write( (char*) &x, sizeof( double ) );
|
||||
aFile.write( (char*) &y, sizeof( double ) );
|
||||
aFile.write( (char*) &z, sizeof( double ) );
|
||||
aFile.write( (char*)&x, sizeof(double) );
|
||||
aFile.write( (char*)&y, sizeof(double) );
|
||||
aFile.write( (char*)&z, sizeof(double) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -181,9 +194,9 @@ bool S3D::WriteColor( std::ostream& aFile, const SGCOLOR& aColor )
|
||||
{
|
||||
float r, g, b;
|
||||
aColor.GetColor( r, g, b );
|
||||
aFile.write( (char*) &r, sizeof( float ) );
|
||||
aFile.write( (char*) &g, sizeof( float ) );
|
||||
aFile.write( (char*) &b, sizeof( float ) );
|
||||
aFile.write( (char*)&r, sizeof(float) );
|
||||
aFile.write( (char*)&g, sizeof(float) );
|
||||
aFile.write( (char*)&b, sizeof(float) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -199,10 +212,13 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( '[' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left bracket at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left bracket at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
@@ -218,9 +234,12 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( schar != ']' )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; could not find right "
|
||||
"bracket" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; could not find right bracket";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
@@ -230,9 +249,13 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( std::string::npos == upos )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; no underscore in name '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; no underscore in name '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
@@ -256,9 +279,15 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
return types[i];
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; no node type matching '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; no node type matching '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
@@ -266,9 +295,9 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
bool S3D::ReadPoint( std::istream& aFile, SGPOINT& aPoint )
|
||||
{
|
||||
aFile.read( (char*) &aPoint.x, sizeof( aPoint.x ) );
|
||||
aFile.read( (char*) &aPoint.y, sizeof( aPoint.y ) );
|
||||
aFile.read( (char*) &aPoint.z, sizeof( aPoint.z ) );
|
||||
aFile.read( (char*)&aPoint.x, sizeof( aPoint.x ) );
|
||||
aFile.read( (char*)&aPoint.y, sizeof( aPoint.y ) );
|
||||
aFile.read( (char*)&aPoint.z, sizeof( aPoint.z ) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -280,9 +309,9 @@ bool S3D::ReadPoint( std::istream& aFile, SGPOINT& aPoint )
|
||||
bool S3D::ReadVector( std::istream& aFile, SGVECTOR& aVector )
|
||||
{
|
||||
double x, y, z;
|
||||
aFile.read( (char*) &x, sizeof( double ) );
|
||||
aFile.read( (char*) &y, sizeof( double ) );
|
||||
aFile.read( (char*) &z, sizeof( double ) );
|
||||
aFile.read( (char*)&x, sizeof(double) );
|
||||
aFile.read( (char*)&y, sizeof(double) );
|
||||
aFile.read( (char*)&z, sizeof(double) );
|
||||
aVector.SetVector( x, y, z );
|
||||
|
||||
if( aFile.fail() )
|
||||
@@ -295,9 +324,9 @@ bool S3D::ReadVector( std::istream& aFile, SGVECTOR& aVector )
|
||||
bool S3D::ReadColor( std::istream& aFile, SGCOLOR& aColor )
|
||||
{
|
||||
float r, g, b;
|
||||
aFile.read( (char*) &r, sizeof( float ) );
|
||||
aFile.read( (char*) &g, sizeof( float ) );
|
||||
aFile.read( (char*) &b, sizeof( float ) );
|
||||
aFile.read( (char*)&r, sizeof(float) );
|
||||
aFile.read( (char*)&g, sizeof(float) );
|
||||
aFile.read( (char*)&b, sizeof(float) );
|
||||
aColor.SetColor( r, g, b );
|
||||
|
||||
if( aFile.fail() )
|
||||
@@ -307,7 +336,7 @@ bool S3D::ReadColor( std::istream& aFile, SGCOLOR& aColor )
|
||||
}
|
||||
|
||||
|
||||
bool S3D::degenerate( glm::dvec3* pts ) noexcept
|
||||
bool S3D::degenerate( glm::dvec3* pts )
|
||||
{
|
||||
double dx, dy, dz;
|
||||
|
||||
@@ -347,19 +376,24 @@ static void calcTriad( glm::dvec3* pts, glm::dvec3& tri )
|
||||
|
||||
// normal * 2 * area
|
||||
tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >& index,
|
||||
std::vector< SGVECTOR >& norms )
|
||||
bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords,
|
||||
std::vector< int >& index, std::vector< SGVECTOR >& norms )
|
||||
{
|
||||
size_t vsize = coords.size();
|
||||
|
||||
if( vsize < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] invalid vertex set (fewer than 3 "
|
||||
"vertices)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid vertex set (fewer than 3 vertices)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -368,16 +402,24 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
|
||||
if( 0 != isize % 3 || index.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] invalid index set (not multiple of 3)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set (not multiple of 3)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !norms.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] normals set is not empty" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] normals set is not empty";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -393,14 +435,15 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
p2 = index[i++];
|
||||
p3 = index[i++];
|
||||
|
||||
if( p1 < 0 || p1 >= (int)vsize || p2 < 0 || p2 >= (int)vsize || p3 < 0 || p3 >= (int)vsize )
|
||||
if( p1 < 0 || p1 >= (int)vsize || p2 < 0 || p2 >= (int)vsize ||
|
||||
p3 < 0 || p3 >= (int)vsize )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set; index out of bounds";
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s\n" ), ostr.str().c_str() );
|
||||
#endif
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -420,7 +463,8 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.emplace( p1, std::list < glm::dvec3 >( 1, tri ) );
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p1, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
|
||||
ip = vmap.find( p2 );
|
||||
@@ -431,7 +475,8 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.emplace( p2, std::list < glm::dvec3 >( 1, tri ) );
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p2, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
|
||||
ip = vmap.find( p3 );
|
||||
@@ -442,7 +487,8 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.emplace( p3, std::list < glm::dvec3 >( 1, tri ) );
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p3, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +503,7 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
// assign any skipped coordinates a normal of (0,0,1)
|
||||
while( item > idx )
|
||||
{
|
||||
norms.emplace_back( 0, 0, 1 );
|
||||
norms.push_back( SGVECTOR( 0, 0, 1 ) );
|
||||
++idx;
|
||||
}
|
||||
|
||||
@@ -471,7 +517,7 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
++sT;
|
||||
}
|
||||
|
||||
norms.emplace_back( norm.x, norm.y, norm.z );
|
||||
norms.push_back( SGVECTOR( norm.x, norm.y, norm.z ) );
|
||||
|
||||
++idx;
|
||||
++sM;
|
||||
@@ -479,9 +525,12 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
|
||||
if( norms.size() != coords.size() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] number of normals does not equal number "
|
||||
"of vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] number of normals does not equal number of vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+121
-147
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,10 +23,10 @@
|
||||
|
||||
/**
|
||||
* @file sg_helpers.h
|
||||
*
|
||||
* Define a number of macros to aid in repetitious code which is probably best expressed
|
||||
* as a preprocessor macro rather than as a template. This header also declares a number
|
||||
* of functions which are only of use within the sg_* classes.
|
||||
* defines a number of macro functions to aid in repetitious code which
|
||||
* is probably best expressed as a preprocessor macro rather than as
|
||||
* a template. This header also declares a number of functions which are
|
||||
* only of use within the sg_* classes.
|
||||
*/
|
||||
|
||||
#ifndef SG_HELPERS_H
|
||||
@@ -45,182 +44,151 @@ class SGNORMALS;
|
||||
class SGCOORDS;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
|
||||
// Function to drop references within an SGNODE
|
||||
// The node being destroyed must remove itself from the object reference's
|
||||
// backpointer list in order to avoid a segfault.
|
||||
#define DROP_REFS( aType, aList ) \
|
||||
do \
|
||||
{ \
|
||||
std::vector<aType*>::iterator sL = aList.begin(); \
|
||||
std::vector<aType*>::iterator eL = aList.end(); \
|
||||
while( sL != eL ) \
|
||||
{ \
|
||||
( (SGNODE*) *sL )->delNodeRef( this ); \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
#define DROP_REFS( aType, aList ) do { \
|
||||
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||
std::vector< aType* >::iterator eL = aList.end(); \
|
||||
while( sL != eL ) { \
|
||||
((SGNODE*)*sL)->delNodeRef( this ); \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
// Function to delete owned objects within an SGNODE
|
||||
// The owned object's parent is set to NULL before
|
||||
// deletion to avoid a redundant 'unlinkChildNode' call.
|
||||
#define DEL_OBJS( aType, aList ) \
|
||||
do \
|
||||
{ \
|
||||
std::vector<aType*>::iterator sL = aList.begin(); \
|
||||
std::vector<aType*>::iterator eL = aList.end(); \
|
||||
while( sL != eL ) \
|
||||
{ \
|
||||
( (SGNODE*) *sL )->SetParent( nullptr, false ); \
|
||||
delete *sL; \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
#define DEL_OBJS( aType, aList ) do { \
|
||||
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||
std::vector< aType* >::iterator eL = aList.end(); \
|
||||
while( sL != eL ) { \
|
||||
((SGNODE*)*sL)->SetParent( NULL, false ); \
|
||||
delete *sL; \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
// Function to unlink a child or reference node when that child or
|
||||
// reference node is being destroyed.
|
||||
#define UNLINK_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) \
|
||||
do \
|
||||
{ \
|
||||
if( aNodeID == aNode->GetNodeType() ) \
|
||||
{ \
|
||||
std::vector<aType*>* oSL; \
|
||||
std::vector<aType*>::iterator sL; \
|
||||
std::vector<aType*>::iterator eL; \
|
||||
if( isChild ) \
|
||||
{ \
|
||||
oSL = &aOwnedList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) \
|
||||
{ \
|
||||
if( (SGNODE*) *sL == aNode ) \
|
||||
{ \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
oSL = &aRefList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) \
|
||||
{ \
|
||||
if( (SGNODE*) *sL == aNode ) \
|
||||
{ \
|
||||
delNodeRef( this ); \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
} while( 0 )
|
||||
#define UNLINK_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||
if( aNodeID == aNode->GetNodeType() ) { \
|
||||
std::vector< aType* >* oSL; \
|
||||
std::vector< aType* >::iterator sL; \
|
||||
std::vector< aType* >::iterator eL; \
|
||||
if( isChild ) { \
|
||||
oSL = &aOwnedList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) { \
|
||||
if( (SGNODE*)*sL == aNode ) { \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} else { \
|
||||
oSL = &aRefList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) { \
|
||||
if( (SGNODE*)*sL == aNode ) { \
|
||||
delNodeRef( this ); \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} \
|
||||
return; \
|
||||
} } while( 0 )
|
||||
|
||||
|
||||
// Function to check a node type, check for an existing reference,
|
||||
// and add the node type to the reference list if applicable
|
||||
#define ADD_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) \
|
||||
do \
|
||||
{ \
|
||||
if( aNodeID == aNode->GetNodeType() ) \
|
||||
{ \
|
||||
std::vector<aType*>::iterator sL; \
|
||||
sL = std::find( aOwnedList.begin(), aOwnedList.end(), aNode ); \
|
||||
if( sL != aOwnedList.end() ) \
|
||||
return true; \
|
||||
sL = std::find( aRefList.begin(), aRefList.end(), aNode ); \
|
||||
if( sL != aRefList.end() ) \
|
||||
return true; \
|
||||
if( isChild ) \
|
||||
{ \
|
||||
SGNODE* ppn = (SGNODE*) aNode->GetParent(); \
|
||||
if( nullptr != ppn ) \
|
||||
{ \
|
||||
if( this != ppn ) \
|
||||
{ \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has multiple parents '" << ppn->GetName() << "', '"; \
|
||||
std::cerr << m_Name << "'\n"; \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
aOwnedList.push_back( (aType*) aNode ); \
|
||||
aNode->SetParent( this, false ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/*if( nullptr == aNode->GetParent() ) { \
|
||||
#define ADD_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||
if( aNodeID == aNode->GetNodeType() ) { \
|
||||
std::vector< aType* >::iterator sL; \
|
||||
sL = std::find( aOwnedList.begin(), aOwnedList.end(), aNode ); \
|
||||
if( sL != aOwnedList.end() ) return true; \
|
||||
sL = std::find( aRefList.begin(), aRefList.end(), aNode ); \
|
||||
if( sL != aRefList.end() ) return true; \
|
||||
if( isChild ) { \
|
||||
SGNODE* ppn = (SGNODE*)aNode->GetParent(); \
|
||||
if( NULL != ppn ) { \
|
||||
if( this != ppn ) { \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has multiple parents '" << ppn->GetName() << "', '"; \
|
||||
std::cerr << m_Name << "'\n"; \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
aOwnedList.push_back( (aType*)aNode ); \
|
||||
aNode->SetParent( this, false ); \
|
||||
} else { \
|
||||
/*if( NULL == aNode->GetParent() ) { \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has no parent\n"; \
|
||||
std::cerr << " * [INFO] possible copy assignment or copy constructor bug\n"; \
|
||||
return false; \
|
||||
} */ \
|
||||
aRefList.push_back( (aType*) aNode ); \
|
||||
aNode->addNodeRef( this ); \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
} while( 0 )
|
||||
} */ \
|
||||
aRefList.push_back( (aType*)aNode ); \
|
||||
aNode->addNodeRef( this ); \
|
||||
} \
|
||||
return true; \
|
||||
} } while( 0 )
|
||||
|
||||
|
||||
// Function to find a node object given a (non-unique) node name
|
||||
#define FIND_NODE( aType, aName, aNodeList, aCallingNode ) \
|
||||
do \
|
||||
{ \
|
||||
std::vector<aType*>::iterator sLA = aNodeList.begin(); \
|
||||
std::vector<aType*>::iterator eLA = aNodeList.end(); \
|
||||
SGNODE* psg = nullptr; \
|
||||
while( sLA != eLA ) \
|
||||
{ \
|
||||
if( (SGNODE*) *sLA != aCallingNode ) \
|
||||
{ \
|
||||
psg = (SGNODE*) ( *sLA )->FindNode( aName, this ); \
|
||||
if( nullptr != psg ) \
|
||||
return psg; \
|
||||
} \
|
||||
++sLA; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#define FIND_NODE( aType, aName, aNodeList, aCallingNode ) do { \
|
||||
std::vector< aType* >::iterator sLA = aNodeList.begin(); \
|
||||
std::vector< aType* >::iterator eLA = aNodeList.end(); \
|
||||
SGNODE* psg = NULL; \
|
||||
while( sLA != eLA ) { \
|
||||
if( (SGNODE*)*sLA != aCallingNode ) { \
|
||||
psg = (SGNODE*) (*sLA)->FindNode( aName, this ); \
|
||||
if( NULL != psg) \
|
||||
return psg; \
|
||||
} \
|
||||
++sLA; \
|
||||
} } while ( 0 )
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool degenerate( glm::dvec3* pts ) noexcept;
|
||||
bool degenerate( glm::dvec3* pts );
|
||||
|
||||
//
|
||||
// Normals calculations from triangles
|
||||
//
|
||||
|
||||
/*
|
||||
* Take an array of 3D coordinates and its corresponding index set and calculates
|
||||
* the normals assuming that indices are given in CCW order.
|
||||
* Function CalcTriangleNormals
|
||||
* takes an array of 3D coordinates and its corresponding index set and calculates
|
||||
* the normals assuming that indices are given in CCW order. Care must be taken in
|
||||
* using this function to ensure that:
|
||||
* (a) all coordinates are indexed; unindexed coordinates are assigned normal(0,0,1);
|
||||
* when dealing with VRML models which may list and reuse one large coordinate set it
|
||||
* is necessary to gather all index sets and perform this operation only once.
|
||||
* (b) index sets must represent triangles (multiple of 3 indices) and must not be
|
||||
* degenerate - that is all indices and coordinates in a triad must be unique.
|
||||
*
|
||||
* Care must be taken in using this function to ensure that:
|
||||
* -# All coordinates are indexed; unindexed coordinates are assigned normal(0,0,1);
|
||||
* when dealing with VRML models which may list and reuse one large coordinate set it
|
||||
* is necessary to gather all index sets and perform this operation only once.
|
||||
* -# Index sets must represent triangles (multiple of 3 indices) and must not be
|
||||
* degenerate, that is all indices and coordinates in a triad must be unique.
|
||||
*
|
||||
* @param coords is the array of 3D vertices.
|
||||
* @param index is the array of 3x vertex indices (triads).
|
||||
* @param norms is an empty array which holds the normals corresponding to each vector.
|
||||
* @param coords is the array of 3D vertices
|
||||
* @param index is the array of 3x vertex indices (triads)
|
||||
* @param norms is an empty array which holds the normals corresponding to each vector
|
||||
* @return true on success; otherwise false.
|
||||
*/
|
||||
bool CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >& index,
|
||||
std::vector< SGVECTOR >& norms );
|
||||
std::vector< SGVECTOR >& norms );
|
||||
|
||||
//
|
||||
// VRML related functions
|
||||
//
|
||||
|
||||
// formats a floating point number for text output to a VRML file
|
||||
void FormatFloat( std::string& result, double value );
|
||||
@@ -250,13 +218,19 @@ namespace S3D
|
||||
// write out an RGB color
|
||||
bool WriteColor( std::ostream& aFile, const SGCOLOR& aColor );
|
||||
|
||||
//
|
||||
// Cache related READ functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Read the text tag of a binary cache file which is the NodeTag and unique ID number combined.
|
||||
* Function ReadTag
|
||||
* reads the text tag of a binary cache file which is the
|
||||
* NodeTag and unique ID number combined
|
||||
*
|
||||
* @param aFile is a binary file open for reading.
|
||||
* @param aName will hold the tag name on successful return.
|
||||
* @return will be the NodeType which the tag represents or S3D::SGTYPES::SGTYPE_END on
|
||||
* failure.
|
||||
* @param aFile is a binary file open for reading
|
||||
* @param aName will hold the tag name on successful return
|
||||
* @return will be the NodeType which the tag represents or
|
||||
* S3D::SGTYPES::SGTYPE_END on failure
|
||||
*/
|
||||
S3D::SGTYPES ReadTag( std::istream& aFile, std::string& aName );
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -31,27 +30,33 @@
|
||||
|
||||
SGINDEX::SGINDEX( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGINDEX (type "
|
||||
"'%d')" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGINDEX (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGINDEX::~SGINDEX()
|
||||
{
|
||||
index.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -60,14 +65,14 @@ bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGINDEX and derived types
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -79,45 +84,65 @@ bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGINDEX::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGINDEX::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGINDEX::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGINDEX::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -128,7 +153,7 @@ bool SGINDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
if( index.empty() )
|
||||
{
|
||||
nIndices = 0;
|
||||
aIndexList = nullptr;
|
||||
aIndexList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -142,7 +167,7 @@ void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
index.clear();
|
||||
|
||||
if( 0 == nIndices || nullptr == aIndexList )
|
||||
if( 0 == nIndices || NULL == aIndexList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < nIndices; ++i )
|
||||
@@ -155,6 +180,7 @@ void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
void SGINDEX::AddIndex( int aIndex )
|
||||
{
|
||||
index.push_back( aIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -184,8 +210,17 @@ bool SGINDEX::writeCoordIndex( std::ostream& aFile )
|
||||
{
|
||||
size_t n = index.size();
|
||||
|
||||
wxCHECK_MSG( n % 3 == 0, false, wxT( "Coordinate index is not divisible by three (violates "
|
||||
"triangle constraint)" ) );
|
||||
if( n % 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] coord index is not divisible by three (violates triangle constraint)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << " coordIndex [\n ";
|
||||
|
||||
@@ -261,16 +296,26 @@ bool SGINDEX::writeIndexList( std::ostream& aFile )
|
||||
|
||||
bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -279,12 +324,26 @@ bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -306,7 +365,17 @@ bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( index.empty(), false );
|
||||
if( !index.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
@@ -317,7 +386,7 @@ bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
aFile.read( (char*) &tmp, sizeof( int ) );
|
||||
aFile.read( (char*)&tmp, sizeof(int) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_index.h
|
||||
* defines a generic Index interface for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_INDEX_H
|
||||
@@ -32,59 +32,8 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define a generic index interface for a scenegraph object.
|
||||
*/
|
||||
class SGINDEX : public SGNODE
|
||||
{
|
||||
public:
|
||||
SGINDEX( SGNODE* aParent );
|
||||
virtual ~SGINDEX();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char* aNodeName, const SGNODE* aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aCaller ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aCaller ) noexcept override;
|
||||
|
||||
/**
|
||||
* Retrieve the number of indices and a pointer to the list.
|
||||
*
|
||||
* @note The returned pointer may be invalidated by future operations on the SGNODE. The
|
||||
* caller must make immediate use of the data and must not rely on the pointer's
|
||||
* validity in the future.
|
||||
*
|
||||
* @param nIndices will hold the number of indices in the list.
|
||||
* @param aIndexList will store a pointer to the data.
|
||||
* @return true if there was available data (nIndices > 0) otherwise false.
|
||||
*/
|
||||
bool GetIndices( size_t& nIndices, int*& aIndexList );
|
||||
|
||||
/**
|
||||
* Set the number of indices and creates a copy of the given index data.
|
||||
*
|
||||
* @param nIndices the number of indices to be stored.
|
||||
* @param aIndexList the index data.
|
||||
*/
|
||||
void SetIndices( size_t nIndices, int* aIndexList );
|
||||
|
||||
|
||||
/**
|
||||
* Add a single index to the list.
|
||||
*
|
||||
* @param aIndex is the index to add.
|
||||
*/
|
||||
void AddIndex( int aIndex );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
protected:
|
||||
bool writeCoordIndex( std::ostream& aFile );
|
||||
bool writeColorIndex( std::ostream& aFile );
|
||||
@@ -93,6 +42,56 @@ protected:
|
||||
public:
|
||||
// for internal SG consumption only
|
||||
std::vector< int > index;
|
||||
void unlinkChildNode( const SGNODE* aCaller ) override;
|
||||
void unlinkRefNode( const SGNODE* aCaller ) override;
|
||||
|
||||
public:
|
||||
SGINDEX( SGNODE* aParent );
|
||||
virtual ~SGINDEX();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
/**
|
||||
* Function GetIndices
|
||||
* retrieves the number of indices and a pointer to
|
||||
* the list. Note: the returned pointer may be invalidated
|
||||
* by future operations on the SGNODE; the caller must make
|
||||
* immediate use of the data and must not rely on the pointer's
|
||||
* validity in the future.
|
||||
*
|
||||
* @param nIndices [out] will hold the number of indices in the list
|
||||
* @param aIndexList [out] will store a pointer to the data
|
||||
* @return true if there was available data (nIndices > 0) otherwise false
|
||||
*/
|
||||
bool GetIndices( size_t& nIndices, int*& aIndexList );
|
||||
|
||||
/**
|
||||
* Function SetIndices
|
||||
* sets the number of indices and creates a copy of the given index data.
|
||||
*
|
||||
* @param nIndices [in] the number of indices to be stored
|
||||
* @param aIndexList [in] the index data
|
||||
*/
|
||||
void SetIndices( size_t nIndices, int* aIndexList );
|
||||
|
||||
|
||||
/**
|
||||
* Function AddIndex
|
||||
* adds a single index to the list
|
||||
*
|
||||
* @param aIndex is the index to add
|
||||
*/
|
||||
void AddIndex( int aIndex );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_INDEX_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -32,7 +31,6 @@
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
|
||||
static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||
"TXFM",
|
||||
"APP",
|
||||
@@ -50,7 +48,7 @@ static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||
static unsigned int node_counts[S3D::SGTYPE_END] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
|
||||
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType ) noexcept
|
||||
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType )
|
||||
{
|
||||
return node_names[aType].c_str();
|
||||
}
|
||||
@@ -70,15 +68,19 @@ static void getNodeName( S3D::SGTYPES nodeType, std::string& aName )
|
||||
std::ostringstream ostr;
|
||||
ostr << node_names[nodeType] << "_" << seqNum;
|
||||
aName = ostr.str();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE::SGNODE( SGNODE* aParent )
|
||||
{
|
||||
m_Parent = aParent;
|
||||
m_Association = nullptr;
|
||||
m_Association = NULL;
|
||||
m_written = false;
|
||||
m_SGtype = S3D::SGTYPE_END;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +90,7 @@ SGNODE::~SGNODE()
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
if( m_Association )
|
||||
*m_Association = nullptr;
|
||||
*m_Association = NULL;
|
||||
|
||||
std::list< SGNODE* >::iterator sBP = m_BackPointers.begin();
|
||||
std::list< SGNODE* >::iterator eBP = m_BackPointers.end();
|
||||
@@ -98,16 +100,18 @@ SGNODE::~SGNODE()
|
||||
(*sBP)->unlinkRefNode( this );
|
||||
++sBP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES SGNODE::GetNodeType( void ) const noexcept
|
||||
S3D::SGTYPES SGNODE::GetNodeType( void ) const
|
||||
{
|
||||
return m_SGtype;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNODE::GetParent( void ) const noexcept
|
||||
SGNODE* SGNODE::GetParent( void ) const
|
||||
{
|
||||
return m_Parent;
|
||||
}
|
||||
@@ -118,10 +122,10 @@ bool SGNODE::SwapParent( SGNODE* aNewParent )
|
||||
if( aNewParent == m_Parent )
|
||||
return true;
|
||||
|
||||
if( nullptr == aNewParent )
|
||||
if( NULL == aNewParent )
|
||||
return false;
|
||||
|
||||
if( nullptr == m_Parent )
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
if( aNewParent->AddChildNode( this ) )
|
||||
return true;
|
||||
@@ -134,7 +138,7 @@ bool SGNODE::SwapParent( SGNODE* aNewParent )
|
||||
|
||||
SGNODE* oldParent = m_Parent;
|
||||
m_Parent->unlinkChildNode( this );
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
aNewParent->unlinkRefNode( this );
|
||||
aNewParent->AddChildNode( this );
|
||||
oldParent->AddRefNode( this );
|
||||
@@ -152,16 +156,18 @@ const char* SGNODE::GetName( void )
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::SetName( const char* aName )
|
||||
void SGNODE::SetName( const char *aName )
|
||||
{
|
||||
if( nullptr == aName || 0 == aName[0] )
|
||||
if( NULL == aName || 0 == aName[0] )
|
||||
getNodeName( m_SGtype, m_Name );
|
||||
else
|
||||
m_Name = aName;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const char* SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const noexcept
|
||||
const char * SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
return node_names[aNodeType].c_str();
|
||||
}
|
||||
@@ -169,7 +175,7 @@ const char* SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const noexcept
|
||||
|
||||
void SGNODE::addNodeRef( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
@@ -179,12 +185,13 @@ void SGNODE::addNodeRef( SGNODE* aNode )
|
||||
return;
|
||||
|
||||
m_BackPointers.push_back( aNode );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::delNodeRef( const SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
@@ -196,49 +203,110 @@ void SGNODE::delNodeRef( const SGNODE* aNode )
|
||||
return;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] delNodeRef() did not find its target, this "
|
||||
"node type %d, referenced node type %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
m_SGtype,
|
||||
aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] delNodeRef() did not find its target\n";
|
||||
ostr << " * This Node Type: " << m_SGtype << ", Referenced node type: ";
|
||||
ostr << aNode->GetNodeType() << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::AssociateWrapper( SGNODE** aWrapperRef ) noexcept
|
||||
void SGNODE::AssociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
wxCHECK( aWrapperRef && *aWrapperRef == this, /* void */ );
|
||||
if( NULL == aWrapperRef )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL handle";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( *aWrapperRef != this )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] handle value does not match this object's pointer";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is an existing association then break it and emit a warning
|
||||
// just in case the behavior is undesired
|
||||
if( m_Association )
|
||||
{
|
||||
*m_Association = nullptr;
|
||||
*m_Association = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [WARNING] association being broken with "
|
||||
"previous wrapper" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [WARNING] association being broken with previous wrapper";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
m_Association = aWrapperRef;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef ) noexcept
|
||||
void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
if( !m_Association )
|
||||
return;
|
||||
|
||||
wxCHECK( aWrapperRef, /* void */ );
|
||||
if( !aWrapperRef )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid handle value aWrapperRef";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
wxCHECK( *aWrapperRef == *m_Association && aWrapperRef == m_Association, /* void */ );
|
||||
return;
|
||||
}
|
||||
|
||||
m_Association = nullptr;
|
||||
if( *aWrapperRef != *m_Association || aWrapperRef != m_Association )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] *aWrapperRef (" << *aWrapperRef;
|
||||
ostr << ") does not match *m_Association (" << *m_Association << ") in type ";
|
||||
ostr << node_names[ m_SGtype] << "\n";
|
||||
ostr << " * [INFO] OR aWrapperRef(" << aWrapperRef << ") != m_Association(";
|
||||
ostr << m_Association << ")\n";
|
||||
ostr << " * [INFO] node name: " << GetName();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_Association = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::ResetNodeIndex( void ) noexcept
|
||||
void SGNODE::ResetNodeIndex( void )
|
||||
{
|
||||
for( int i = 0; i < (int)S3D::SGTYPE_END; ++i )
|
||||
node_counts[i] = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +314,28 @@ bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||
{
|
||||
aIndex = 0;
|
||||
|
||||
wxCHECK( aNode && S3D::SGTYPE_APPEARANCE == aNode->GetNodeType(), false );
|
||||
if( NULL == aNode || S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
ostr.str( "" );
|
||||
|
||||
if( NULL == aNode )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] aNode is NULL\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
ostr << " * [BUG] invalid node type (" << aNode->GetNodeType();
|
||||
ostr << "), expected " << S3D::SGTYPE_APPEARANCE;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGAPPEARANCE* node = (SGAPPEARANCE*)aNode;
|
||||
|
||||
@@ -260,7 +349,7 @@ bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||
|
||||
int idx = (int)aList.matorder.size();
|
||||
aList.matorder.push_back( node );
|
||||
aList.matmap.emplace( node, idx );
|
||||
aList.matmap.insert( std::pair< SGAPPEARANCE const*, int >( node, idx ) );
|
||||
aIndex = idx;
|
||||
|
||||
return true;
|
||||
@@ -273,74 +362,78 @@ void S3D::INIT_SMATERIAL( SMATERIAL& aMaterial )
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_SMESH( SMESH& aMesh ) noexcept
|
||||
void S3D::INIT_SMESH( SMESH& aMesh )
|
||||
{
|
||||
aMesh = {};
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_S3DMODEL( S3DMODEL& aModel ) noexcept
|
||||
void S3D::INIT_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
aModel = {};
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_SMESH( SMESH& aMesh ) noexcept
|
||||
void S3D::FREE_SMESH( SMESH& aMesh)
|
||||
{
|
||||
if( nullptr != aMesh.m_Positions )
|
||||
if( NULL != aMesh.m_Positions )
|
||||
{
|
||||
delete [] aMesh.m_Positions;
|
||||
aMesh.m_Positions = nullptr;
|
||||
aMesh.m_Positions = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Normals )
|
||||
if( NULL != aMesh.m_Normals )
|
||||
{
|
||||
delete [] aMesh.m_Normals;
|
||||
aMesh.m_Normals = nullptr;
|
||||
aMesh.m_Normals = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Texcoords )
|
||||
if( NULL != aMesh.m_Texcoords )
|
||||
{
|
||||
delete [] aMesh.m_Texcoords;
|
||||
aMesh.m_Texcoords = nullptr;
|
||||
aMesh.m_Texcoords = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Color )
|
||||
if( NULL != aMesh.m_Color )
|
||||
{
|
||||
delete [] aMesh.m_Color;
|
||||
aMesh.m_Color = nullptr;
|
||||
aMesh.m_Color = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_FaceIdx )
|
||||
if( NULL != aMesh.m_FaceIdx )
|
||||
{
|
||||
delete [] aMesh.m_FaceIdx;
|
||||
aMesh.m_FaceIdx = nullptr;
|
||||
aMesh.m_FaceIdx = NULL;
|
||||
}
|
||||
|
||||
aMesh.m_VertexSize = 0;
|
||||
aMesh.m_FaceIdxSize = 0;
|
||||
aMesh.m_MaterialIdx = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
if( nullptr != aModel.m_Materials )
|
||||
if( NULL != aModel.m_Materials )
|
||||
{
|
||||
delete [] aModel.m_Materials;
|
||||
aModel.m_Materials = nullptr;
|
||||
aModel.m_Materials = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MaterialsSize = 0;
|
||||
|
||||
if( nullptr != aModel.m_Meshes )
|
||||
if( NULL != aModel.m_Meshes )
|
||||
{
|
||||
for( unsigned int i = 0; i < aModel.m_MeshesSize; ++i )
|
||||
FREE_SMESH( aModel.m_Meshes[i] );
|
||||
|
||||
delete [] aModel.m_Meshes;
|
||||
aModel.m_Meshes = nullptr;
|
||||
aModel.m_Meshes = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MeshesSize = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+121
-107
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_node.h
|
||||
* defines the base class of the intermediate scene graph NODE
|
||||
*/
|
||||
|
||||
|
||||
@@ -47,9 +47,10 @@ class SGAPPEARANCE;
|
||||
namespace S3D
|
||||
{
|
||||
/**
|
||||
* Return the name of the given type of node
|
||||
* Function GetNodeTypeName
|
||||
* returns the name of the given type of node
|
||||
*/
|
||||
char const* GetNodeTypeName( S3D::SGTYPES aType ) noexcept;
|
||||
char const* GetNodeTypeName( S3D::SGTYPES aType );
|
||||
|
||||
struct MATLIST
|
||||
{
|
||||
@@ -60,67 +61,129 @@ namespace S3D
|
||||
bool GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex );
|
||||
|
||||
void INIT_SMATERIAL( SMATERIAL& aMaterial );
|
||||
void INIT_SMESH( SMESH& aMesh ) noexcept;
|
||||
void INIT_S3DMODEL( S3DMODEL& aModel ) noexcept;
|
||||
void INIT_SMESH( SMESH& aMesh );
|
||||
void INIT_S3DMODEL( S3DMODEL& aModel );
|
||||
|
||||
void FREE_SMESH( SMESH& aMesh) noexcept;
|
||||
void FREE_SMESH( SMESH& aMesh);
|
||||
void FREE_S3DMODEL( S3DMODEL& aModel );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The base class of all Scene Graph nodes.
|
||||
* Class SGNODE
|
||||
* represents the base class of all Scene Graph nodes
|
||||
*/
|
||||
class SGNODE
|
||||
{
|
||||
private:
|
||||
SGNODE** m_Association; // handle to the instance held by a wrapper
|
||||
|
||||
protected:
|
||||
std::list< SGNODE* > m_BackPointers; // nodes which hold a reference to this
|
||||
SGNODE* m_Parent; // pointer to parent node; may be NULL for top level transform
|
||||
S3D::SGTYPES m_SGtype; // type of SG node
|
||||
std::string m_Name; // name to use for referencing the entity by name
|
||||
bool m_written; // set true when the object has been written after a ReNameNodes()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Function unlinkChild
|
||||
* removes references to an owned child; it is invoked by the child upon destruction
|
||||
* to ensure that the parent has no invalid references.
|
||||
*
|
||||
* @param aNode is the child which is being deleted
|
||||
*/
|
||||
virtual void unlinkChildNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function unlinkRef
|
||||
* removes pointers to a referenced node; it is invoked by the referenced node
|
||||
* upon destruction to ensure that the referring node has no invalid references.
|
||||
*
|
||||
* @param aNode is the node which is being deleted
|
||||
*/
|
||||
virtual void unlinkRefNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function addNodeRef
|
||||
* adds a pointer to a node which references, but does not own, this node.
|
||||
* Such back-pointers are required to ensure that invalidated references
|
||||
* are removed when a node is deleted
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object
|
||||
*/
|
||||
void addNodeRef( SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Function delNodeRef
|
||||
* removes a pointer to a node which references, but does not own, this node.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object
|
||||
*/
|
||||
void delNodeRef( const SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Function IsWritten
|
||||
* returns true if the object had already been written to a
|
||||
* cache file or VRML file; for internal use only.
|
||||
*/
|
||||
bool isWritten( void )
|
||||
{
|
||||
return m_written;
|
||||
}
|
||||
|
||||
public:
|
||||
SGNODE( SGNODE* aParent );
|
||||
virtual ~SGNODE();
|
||||
|
||||
/**
|
||||
* Return the type of this node instance.
|
||||
* Function GetNodeType
|
||||
* returns the type of this node instance
|
||||
*/
|
||||
S3D::SGTYPES GetNodeType( void ) const noexcept;
|
||||
S3D::SGTYPES GetNodeType( void ) const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to the parent SGNODE of this object or NULL if the object has
|
||||
* no parent (ie. top level transform).
|
||||
* Function GetParent
|
||||
* returns a pointer to the parent SGNODE of this object
|
||||
* or NULL if the object has no parent (ie. top level transform)
|
||||
*/
|
||||
SGNODE* GetParent( void ) const noexcept;
|
||||
SGNODE* GetParent( void ) const;
|
||||
|
||||
/**
|
||||
* Set the parent #SGNODE of this object.
|
||||
* Function SetParent
|
||||
* sets the parent SGNODE of this object.
|
||||
*
|
||||
* @param aParent [in] is the desired parent node
|
||||
* @return true if the operation succeeds; false if the given node is not allowed to
|
||||
* be a parent to the derived object.
|
||||
* @return true if the operation succeeds; false if
|
||||
* the given node is not allowed to be a parent to
|
||||
* the derived object.
|
||||
*/
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) = 0;
|
||||
|
||||
/**
|
||||
* Swap the ownership with the given parent.
|
||||
* Function SwapParent
|
||||
* swaps the ownership with the given parent. This operation
|
||||
* may be required when reordering nodes for optimization.
|
||||
*
|
||||
* This operation may be required when reordering nodes for optimization.
|
||||
*
|
||||
* @param aNewParent will become the new parent to the object; it must be the same type
|
||||
* as the parent of this instance.
|
||||
* @param aNewParent [in] will become the new parent to the
|
||||
* object; it must be the same type as the parent of this
|
||||
* instance.
|
||||
*/
|
||||
bool SwapParent( SGNODE* aNewParent );
|
||||
|
||||
const char* GetName( void );
|
||||
void SetName(const char *aName);
|
||||
|
||||
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const noexcept;
|
||||
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const;
|
||||
|
||||
/**
|
||||
* Search the tree of linked nodes and return a reference to the first node found with
|
||||
* the given name.
|
||||
* Function FindNode searches the tree of linked nodes and returns a
|
||||
* reference to the first node found with the given name. The reference
|
||||
* is then typically added to another node via AddRefNode().
|
||||
*
|
||||
* The reference is then typically added to another node via AddRefNode().
|
||||
*
|
||||
* @param aNodeName is the name of the node to search for.
|
||||
* @param aCaller is a pointer to the node invoking this function.
|
||||
* @return is a valid node pointer on success, otherwise NULL.
|
||||
* @param aNodeName is the name of the node to search for
|
||||
* @param aCaller is a pointer to the node invoking this function
|
||||
* @return is a valid node pointer on success, otherwise NULL
|
||||
*/
|
||||
virtual SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) = 0;
|
||||
|
||||
@@ -129,108 +192,59 @@ public:
|
||||
virtual bool AddChildNode( SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Associate this object with a handle to itself.
|
||||
*
|
||||
* The handle is typically held by an IFSG* wrapper and the pointer which it refers to
|
||||
* is set to NULL upon destruction of this object. This mechanism provides a scheme
|
||||
* by which a wrapper can be notified of the destruction of the object which it wraps.
|
||||
* Function AssociateWrapper
|
||||
* associates this object with a handle to itself; this handle
|
||||
* is typically held by an IFSG* wrapper and the pointer which
|
||||
* it refers to is set to NULL upon destruction of this object.
|
||||
* This mechanism provides a scheme by which a wrapper can be
|
||||
* notified of the destruction of the object which it wraps.
|
||||
*/
|
||||
void AssociateWrapper( SGNODE** aWrapperRef ) noexcept;
|
||||
void AssociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Remove the association between an IFSG* wrapper object and this object.
|
||||
* Function DisassociateWrapper
|
||||
* removes the association between an IFSG* wrapper
|
||||
* object and this object.
|
||||
*/
|
||||
void DisassociateWrapper( SGNODE** aWrapperRef ) noexcept;
|
||||
void DisassociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Reset the global SG* node indices in preparation for write operations.
|
||||
* Function ResetNodeIndex
|
||||
* resets the global SG* node indices in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
void ResetNodeIndex( void ) noexcept;
|
||||
void ResetNodeIndex( void );
|
||||
|
||||
/**
|
||||
* Rename a node and all its child nodes in preparation for write operations.
|
||||
* Function ReNameNodes
|
||||
* renames a node and all its child nodes in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
virtual void ReNameNodes( void ) = 0;
|
||||
|
||||
/**
|
||||
* Writes this node's data to a VRML file.
|
||||
*
|
||||
* This includes all data of child and referenced nodes.
|
||||
* Function WriteVRML
|
||||
* writes this node's data to a VRML file; this includes
|
||||
* all data of child and referenced nodes.
|
||||
*/
|
||||
virtual bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) = 0;
|
||||
|
||||
/**
|
||||
* Write this node's data to a binary cache file.
|
||||
*
|
||||
* The data includes all data of children and references to children. If this function
|
||||
* is invoked by the user, parentNode must be set to NULL in order to ensure coherent data.
|
||||
* Function WriteCache
|
||||
* write's this node's data to a binary cache file; the data
|
||||
* includes all data of children and references to children.
|
||||
* If this function is invoked by the user, parentNode must be
|
||||
* set to NULL in order to ensure coherent data.
|
||||
*/
|
||||
virtual bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) = 0;
|
||||
|
||||
/**
|
||||
* Reads binary format data from a cache file.
|
||||
*
|
||||
* To read a cache file, open the file for reading and invoke this function from a new
|
||||
* #SCENEGRAPH node.
|
||||
* Function ReadCache
|
||||
* Reads binary format data from a cache file. To read a cache file,
|
||||
* open the file for reading and invoke this function from a new
|
||||
* SCENEGRAPH node.
|
||||
*/
|
||||
virtual bool ReadCache( std::istream& aFile, SGNODE* parentNode ) = 0;
|
||||
|
||||
/**
|
||||
* Remove references to an owned child.
|
||||
*
|
||||
* This is invoked by the child upon destruction to ensure that the parent has no
|
||||
* invalid references.
|
||||
*
|
||||
* @param aNode is the child which is being deleted.
|
||||
*/
|
||||
virtual void unlinkChildNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Remove pointers to a referenced node.
|
||||
*
|
||||
* This is invoked by the referenced node upon destruction to ensure that the referring
|
||||
* node has no invalid references.
|
||||
*
|
||||
* @param aNode is the node which is being deleted.
|
||||
*/
|
||||
virtual void unlinkRefNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Add a pointer to a node which references this node, but does not own.
|
||||
*
|
||||
* Such back-pointers are required to ensure that invalidated references are removed
|
||||
* when a node is deleted.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object.
|
||||
*/
|
||||
void addNodeRef( SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Remove a pointer to a node which references this node, but does not own.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object.
|
||||
*/
|
||||
void delNodeRef( const SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Return true if the object had already been written to a cache file or VRML file
|
||||
*
|
||||
* For internal use only.
|
||||
*/
|
||||
bool isWritten( void ) noexcept
|
||||
{
|
||||
return m_written;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::list< SGNODE* > m_BackPointers; ///< nodes which hold a reference to this.
|
||||
SGNODE* m_Parent; ///< Pointer to parent node; may be NULL for top level transform.
|
||||
S3D::SGTYPES m_SGtype; ///< Type of Scene Graph node.
|
||||
std::string m_Name; ///< name to use for referencing the entity by name.
|
||||
bool m_written; ///< Set to true when the object has been written after a ReNameNodes().
|
||||
|
||||
private:
|
||||
SGNODE** m_Association; ///< Handle to the instance held by a wrapper.
|
||||
};
|
||||
|
||||
#endif // SG_NODE_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -34,31 +33,37 @@ SGNORMALS::SGNORMALS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_NORMALS;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGNORMALS "
|
||||
"(type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGNORMALS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNORMALS::~SGNORMALS()
|
||||
{
|
||||
norms.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -67,14 +72,14 @@ bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGNORMALS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -86,41 +91,65 @@ bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNORMALS::FindNode( const char* aNodeName, const SGNODE* aCaller ) noexcept
|
||||
SGNODE* SGNORMALS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( false, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGNORMALS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( false, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGNORMALS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( false, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGNORMALS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( false, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -131,7 +160,7 @@ bool SGNORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
if( norms.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aNormalList = nullptr;
|
||||
aNormalList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,23 +174,27 @@ void SGNORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
norms.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aNormalList )
|
||||
if( 0 == aListSize || NULL == aNormalList )
|
||||
return;
|
||||
|
||||
for( int i = 0; i < (int)aListSize; ++i )
|
||||
norms.push_back( aNormalList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
norms.emplace_back( aXValue, aYValue, aZValue );
|
||||
norms.push_back( SGVECTOR( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
norms.push_back( aNormal );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,16 +266,26 @@ bool SGNORMALS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -251,12 +294,26 @@ bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -278,10 +335,20 @@ bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGNORMALS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( norms.empty(), false );
|
||||
if( !norms.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*) &npts, sizeof( size_t ) );
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGVECTOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_normals.h
|
||||
* defines a set of vertex normals for a scene graph object
|
||||
*/
|
||||
|
||||
#ifndef SG_NORMALS_H
|
||||
@@ -32,20 +32,23 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define a set of vertex normals for a scene graph object
|
||||
*/
|
||||
class SGNORMALS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGVECTOR > norms;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGNORMALS( SGNODE* aParent );
|
||||
virtual ~SGNORMALS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode( const char* aNodeName, const SGNODE* aCaller ) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList );
|
||||
void SetNormalList( size_t aListSize, const SGVECTOR* aNormalList );
|
||||
@@ -57,11 +60,6 @@ public:
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
std::vector< SGVECTOR > norms;
|
||||
};
|
||||
|
||||
#endif // SG_NORMALS_H
|
||||
|
||||
+249
-132
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -40,22 +39,29 @@
|
||||
SGSHAPE::SGSHAPE( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_SHAPE;
|
||||
m_Appearance = nullptr;
|
||||
m_RAppearance = nullptr;
|
||||
m_FaceSet = nullptr;
|
||||
m_RFaceSet = nullptr;
|
||||
m_Appearance = NULL;
|
||||
m_RAppearance = NULL;
|
||||
m_FaceSet = NULL;
|
||||
m_RFaceSet = NULL;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGSHAPE (type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGSHAPE (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,35 +71,37 @@ SGSHAPE::~SGSHAPE()
|
||||
if( m_RAppearance )
|
||||
{
|
||||
m_RAppearance->delNodeRef( this );
|
||||
m_RAppearance = nullptr;
|
||||
m_RAppearance = NULL;
|
||||
}
|
||||
|
||||
if( m_RFaceSet )
|
||||
{
|
||||
m_RFaceSet->delNodeRef( this );
|
||||
m_RFaceSet = nullptr;
|
||||
m_RFaceSet = NULL;
|
||||
}
|
||||
|
||||
// delete objects
|
||||
if( m_Appearance )
|
||||
{
|
||||
m_Appearance->SetParent( nullptr, false );
|
||||
m_Appearance->SetParent( NULL, false );
|
||||
delete m_Appearance;
|
||||
m_Appearance = nullptr;
|
||||
m_Appearance = NULL;
|
||||
}
|
||||
|
||||
if( m_FaceSet )
|
||||
{
|
||||
m_FaceSet->SetParent( nullptr, false );
|
||||
m_FaceSet->SetParent( NULL, false );
|
||||
delete m_FaceSet;
|
||||
m_FaceSet = nullptr;
|
||||
m_FaceSet = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -102,14 +110,14 @@ bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGTRANSFORM may be parent to a SGSHAPE
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -121,17 +129,17 @@ bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
SGNODE* SGSHAPE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
SGNODE* tmp = nullptr;
|
||||
SGNODE* tmp = NULL;
|
||||
|
||||
if( nullptr != m_Appearance )
|
||||
if( NULL != m_Appearance )
|
||||
{
|
||||
tmp = m_Appearance->FindNode( aNodeName, this );
|
||||
|
||||
@@ -141,7 +149,7 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
}
|
||||
}
|
||||
|
||||
if( nullptr != m_FaceSet )
|
||||
if( NULL != m_FaceSet )
|
||||
{
|
||||
tmp = m_FaceSet->FindNode( aNodeName, this );
|
||||
|
||||
@@ -152,8 +160,8 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
}
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -161,20 +169,20 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
|
||||
void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
if( aNode == m_Appearance )
|
||||
{
|
||||
m_Appearance = nullptr;
|
||||
m_Appearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_FaceSet )
|
||||
{
|
||||
m_FaceSet = nullptr;
|
||||
m_FaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -183,38 +191,58 @@ void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
if( aNode == m_RAppearance )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RAppearance = nullptr;
|
||||
m_RAppearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RFaceSet )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RFaceSet = nullptr;
|
||||
m_RFaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE == aNode->GetNodeType() )
|
||||
{
|
||||
@@ -222,9 +250,12 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Appearance && aNode != m_RAppearance )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Appearance "
|
||||
"nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Appearance nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -252,8 +283,12 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_FaceSet && aNode != m_RFaceSet )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple FaceSet nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple FaceSet nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -275,9 +310,15 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
return true;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] object %s is not a valid type for this "
|
||||
"object (%d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aNode->GetName(), aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -310,12 +351,15 @@ void SGSHAPE::ReNameNodes( void )
|
||||
// rename FaceSet
|
||||
if( m_FaceSet )
|
||||
m_FaceSet->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( !m_Appearance && !m_RAppearance && !m_FaceSet && !m_RFaceSet )
|
||||
if( !m_Appearance && !m_RAppearance
|
||||
&& !m_FaceSet && !m_RFaceSet )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -358,16 +402,26 @@ bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -376,21 +430,35 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if any references are unwritten and swap parents if so
|
||||
if( nullptr != m_RAppearance && !m_RAppearance->isWritten() )
|
||||
if( NULL != m_RAppearance && !m_RAppearance->isWritten() )
|
||||
m_RAppearance->SwapParent(this);
|
||||
|
||||
if( nullptr != m_RFaceSet && !m_RFaceSet->isWritten() )
|
||||
if( NULL != m_RFaceSet && !m_RFaceSet->isWritten() )
|
||||
m_RFaceSet->SwapParent( this );
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
@@ -402,23 +470,19 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
items[i] = 0;
|
||||
|
||||
i = 0;
|
||||
|
||||
if( nullptr != m_Appearance )
|
||||
if( NULL != m_Appearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_RAppearance )
|
||||
if( NULL != m_RAppearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_FaceSet )
|
||||
if( NULL != m_FaceSet )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_RFaceSet )
|
||||
if( NULL != m_RFaceSet )
|
||||
items[i] = true;
|
||||
|
||||
for( int jj = 0; jj < NITEMS; ++jj )
|
||||
@@ -446,8 +510,17 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( m_Appearance == nullptr && m_RAppearance == nullptr && m_FaceSet == nullptr &&
|
||||
m_RFaceSet == nullptr, false );
|
||||
if( m_Appearance || m_RAppearance || m_FaceSet || m_RFaceSet )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define NITEMS 4
|
||||
bool items[NITEMS];
|
||||
@@ -457,10 +530,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( ( items[0] && items[1] ) || ( items[2] && items[3] ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; multiple item definitions "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; multiple item definitions at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -471,10 +547,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child appearance "
|
||||
"tag at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child apperance tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -484,9 +563,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Appearance->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading appearance "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading appearance '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -496,10 +579,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref appearance tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref appearance tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -508,20 +594,26 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref "
|
||||
"appearance '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref appearance '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not "
|
||||
"SGAPPEARANCE '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGAPPEARANCE '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -534,10 +626,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child face set tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child face set tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -547,9 +642,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_FaceSet->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading face set "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading face set '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -559,10 +658,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref face set tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref face set tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -571,20 +673,26 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref face "
|
||||
"set '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref face set '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_FACESET != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGFACESET "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGFACESET '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -600,8 +708,8 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes )
|
||||
bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
SMESH m;
|
||||
S3D::INIT_SMESH( m );
|
||||
@@ -609,25 +717,28 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
SGAPPEARANCE* pa = m_Appearance;
|
||||
SGFACESET* pf = m_FaceSet;
|
||||
|
||||
if( nullptr == pa )
|
||||
if( NULL == pa )
|
||||
pa = m_RAppearance;
|
||||
|
||||
if( nullptr == pf )
|
||||
if( NULL == pf )
|
||||
pf = m_RFaceSet;
|
||||
|
||||
// no face sets = nothing to render, which is valid though pointless
|
||||
if( nullptr == pf )
|
||||
if( NULL == pf )
|
||||
return true;
|
||||
|
||||
if( !pf->validate() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; inconsistent data" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; inconsistent data";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if( nullptr == pa )
|
||||
if( NULL == pa )
|
||||
{
|
||||
m.m_MaterialIdx = 0;
|
||||
}
|
||||
@@ -650,22 +761,22 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
SGCOORDINDEX* vidx = pf->m_CoordIndices;
|
||||
SGNORMALS* pn = pf->m_Normals;
|
||||
|
||||
if( nullptr == pc )
|
||||
if( NULL == pc )
|
||||
pc = pf->m_RColors;
|
||||
|
||||
if( nullptr == pv )
|
||||
if( NULL == pv )
|
||||
pv = pf->m_RCoords;
|
||||
|
||||
if( nullptr == pn )
|
||||
if( NULL == pn )
|
||||
pn = pf->m_RNormals;
|
||||
|
||||
// set the vertex points and indices
|
||||
size_t nCoords = 0;
|
||||
SGPOINT* pCoords = nullptr;
|
||||
SGPOINT* pCoords = NULL;
|
||||
pv->GetCoordsList( nCoords, pCoords );
|
||||
|
||||
size_t nColors = 0;
|
||||
SGCOLOR* pColors = nullptr;
|
||||
SGCOLOR* pColors = NULL;
|
||||
|
||||
if( pc )
|
||||
{
|
||||
@@ -674,18 +785,20 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
if( nColors < nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; not enough colors per "
|
||||
"vertex (%ul vs %ul)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, static_cast<unsigned long>( nColors ),
|
||||
static_cast<unsigned long>( nCoords ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; not enough colors per vertex (";
|
||||
ostr << nColors << " vs " << nCoords << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// set the vertex indices
|
||||
size_t nvidx = 0;
|
||||
int* lv = nullptr;
|
||||
int* lv = NULL;
|
||||
vidx->GetIndices( nvidx, lv );
|
||||
|
||||
// note: reduce the vertex set to include only the referenced vertices
|
||||
@@ -699,21 +812,24 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
if( mit == indexmap.end() )
|
||||
{
|
||||
indexmap.emplace( lv[i], vertices.size() );
|
||||
indexmap.insert( std::pair< int, unsigned int >( lv[i], vertices.size() ) );
|
||||
vertices.push_back( lv[i] );
|
||||
}
|
||||
}
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; not enough vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; not enough vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// construct the final vertex/color list
|
||||
SFVEC3F* lColors = nullptr;
|
||||
SFVEC3F* lColors = NULL;
|
||||
SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
|
||||
int ti;
|
||||
|
||||
@@ -723,6 +839,7 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
m.m_Color = lColors;
|
||||
}
|
||||
|
||||
|
||||
if( pc )
|
||||
{
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
@@ -760,7 +877,7 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
// set the per-vertex normals
|
||||
size_t nNorms = 0;
|
||||
SGVECTOR* pNorms = nullptr;
|
||||
SGVECTOR* pNorms = NULL;
|
||||
double x, y, z;
|
||||
|
||||
pn->GetNormalList( nNorms, pNorms );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_shape.h
|
||||
* defines a complex 3D shape for a scenegraph object
|
||||
*/
|
||||
|
||||
|
||||
@@ -36,33 +36,8 @@
|
||||
class SGAPPEARANCE;
|
||||
class SGFACESET;
|
||||
|
||||
/**
|
||||
* Define a complex 3D shape for a scenegraph object.
|
||||
*/
|
||||
class SGSHAPE : public SGNODE
|
||||
{
|
||||
public:
|
||||
SGSHAPE( SGNODE* aParent );
|
||||
virtual ~SGSHAPE();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char* aNodeName, const SGNODE* aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes );
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
private:
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
@@ -75,6 +50,28 @@ public:
|
||||
// referenced nodes
|
||||
SGAPPEARANCE* m_RAppearance;
|
||||
SGFACESET* m_RFaceSet;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGSHAPE( SGNODE* aParent );
|
||||
virtual ~SGSHAPE();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,537 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2023 CERN
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef BOARD_ADAPTER_H
|
||||
#define BOARD_ADAPTER_H
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "../3d_rendering/raytracing/accelerators/container_2d.h"
|
||||
#include "../3d_rendering/raytracing/accelerators/container_3d.h"
|
||||
#include "../3d_rendering/raytracing/shapes3D/bbox_3d.h"
|
||||
#include <gal/3d/camera.h>
|
||||
#include <3d_enums.h>
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include "../common_ogl/ogl_attr_list.h"
|
||||
#include "../3d_viewer/eda_3d_viewer_settings.h"
|
||||
|
||||
#include <layer_ids.h>
|
||||
#include <pad.h>
|
||||
#include <pcb_track.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <pcb_text.h>
|
||||
#include <pcb_textbox.h>
|
||||
#include <pcb_table.h>
|
||||
#include <pcb_shape.h>
|
||||
#include <pcb_dimension.h>
|
||||
#include <zone.h>
|
||||
#include <footprint.h>
|
||||
#include <reporter.h>
|
||||
#include <dialogs/dialog_color_picker.h>
|
||||
|
||||
class COLOR_SETTINGS;
|
||||
class PCB_TEXTBOX;
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map<PCB_LAYER_ID, BVH_CONTAINER_2D*> MAP_CONTAINER_2D_BASE;
|
||||
|
||||
/// A type that stores polysets for each layer id
|
||||
typedef std::map<PCB_LAYER_ID, SHAPE_POLY_SET*> MAP_POLY;
|
||||
|
||||
/// This defines the range that all coord will have to be rendered.
|
||||
/// It will use this value to convert to a normalized value between
|
||||
/// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to handle information needed to display 3D board.
|
||||
*/
|
||||
class BOARD_ADAPTER
|
||||
{
|
||||
public:
|
||||
BOARD_ADAPTER();
|
||||
|
||||
~BOARD_ADAPTER();
|
||||
|
||||
/**
|
||||
* Update the cache manager pointer.
|
||||
*
|
||||
* @param aCachePointer: the pointer to the 3D cache manager.
|
||||
*/
|
||||
void Set3dCacheManager( S3D_CACHE* aCacheMgr ) noexcept { m_3dModelManager = aCacheMgr; }
|
||||
S3D_CACHE* Get3dCacheManager() const noexcept { return m_3dModelManager; }
|
||||
|
||||
/**
|
||||
* Check if a layer is enabled.
|
||||
*
|
||||
* @param aLayer layer ID to get status.
|
||||
*/
|
||||
bool Is3dLayerEnabled( PCB_LAYER_ID aLayer,
|
||||
const std::bitset<LAYER_3D_END>& aVisibilityFlags ) const;
|
||||
|
||||
/**
|
||||
* Test if footprint should be displayed in relation to attributes and the flags.
|
||||
*/
|
||||
bool IsFootprintShown( FOOTPRINT_ATTR_T aFPAttributes ) const;
|
||||
|
||||
/**
|
||||
* Set current board to be rendered.
|
||||
*
|
||||
* @param aBoard board to process.
|
||||
*/
|
||||
void SetBoard( BOARD* aBoard ) noexcept { m_board = aBoard; }
|
||||
const BOARD* GetBoard() const noexcept { return m_board; }
|
||||
|
||||
void ReloadColorSettings() noexcept;
|
||||
|
||||
/**
|
||||
* Build a color list which is used to store colors layers
|
||||
*/
|
||||
std::map<int, COLOR4D> GetLayerColors() const;
|
||||
|
||||
/**
|
||||
* Build the copper color list used by the board editor, and store it in m_BoardEditorColors
|
||||
*/
|
||||
void GetBoardEditorCopperLayerColors( PCBNEW_SETTINGS* aCfg );
|
||||
|
||||
std::map<int, COLOR4D> GetDefaultColors() const;
|
||||
void SetLayerColors( const std::map<int, COLOR4D>& aColors );
|
||||
|
||||
std::bitset<LAYER_3D_END> GetVisibleLayers() const;
|
||||
std::bitset<LAYER_3D_END> GetDefaultVisibleLayers() const;
|
||||
void SetVisibleLayers( const std::bitset<LAYER_3D_END>& aLayers );
|
||||
|
||||
/**
|
||||
* Function to be called by the render when it need to reload the settings for the board.
|
||||
*
|
||||
* @param aStatusReporter the pointer for the status reporter.
|
||||
* @param aWarningReporter pointer for the warning reporter.
|
||||
*/
|
||||
void InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningReporter );
|
||||
|
||||
/**
|
||||
* Board integer units To 3D units.
|
||||
*
|
||||
* @return the conversion factor to transform a position from the board to 3D units.
|
||||
*/
|
||||
double BiuTo3dUnits() const noexcept { return m_biuTo3Dunits; }
|
||||
|
||||
/**
|
||||
* Get the board outline bounding box.
|
||||
*
|
||||
* @return the board bounding box in 3D units.
|
||||
*/
|
||||
const BBOX_3D& GetBBox() const noexcept { return m_boardBoundingBox; }
|
||||
|
||||
/**
|
||||
* Get the board body thickness, including internal copper layers (in 3D units).
|
||||
*/
|
||||
float GetBoardBodyThickness() const noexcept { return m_boardBodyThickness3DU; }
|
||||
|
||||
/**
|
||||
* Get the non copper layers thickness (in 3D units).
|
||||
*/
|
||||
float GetNonCopperLayerThickness() const noexcept { return m_nonCopperLayerThickness3DU; }
|
||||
|
||||
/**
|
||||
* Get the copper layer thicknesses (in 3D units).
|
||||
*/
|
||||
float GetFrontCopperThickness() const noexcept { return m_frontCopperThickness3DU; }
|
||||
float GetBackCopperThickness() const noexcept { return m_backCopperThickness3DU; }
|
||||
|
||||
/**
|
||||
* Get the hole plating thickness (NB: in BOARD UNITS!).
|
||||
*/
|
||||
int GetHolePlatingThickness() const noexcept;
|
||||
|
||||
/**
|
||||
* Get the board size.
|
||||
*
|
||||
* @return size in BIU units.
|
||||
*/
|
||||
VECTOR2I GetBoardSize() const noexcept { return m_boardSize; }
|
||||
|
||||
/**
|
||||
* Get the board center.
|
||||
*
|
||||
* @return position in BIU units.
|
||||
*/
|
||||
VECTOR2I GetBoardPos() const noexcept { return m_boardPos; }
|
||||
|
||||
/**
|
||||
* The board center position in 3D units.
|
||||
*
|
||||
* @return board center vector position in 3D units.
|
||||
*/
|
||||
const SFVEC3F& GetBoardCenter() const noexcept { return m_boardCenter; }
|
||||
|
||||
/**
|
||||
* Get the position of the footprint in 3d integer units considering if it is flipped or not.
|
||||
*
|
||||
* @param aIsFlipped true for use in footprints on Front (top) layer, false
|
||||
* if footprint is on back (bottom) layer.
|
||||
* @return the Z position of 3D shapes, in 3D integer units.
|
||||
*/
|
||||
float GetFootprintZPos( bool aIsFlipped ) const ;
|
||||
|
||||
/**
|
||||
* Get the current polygon of the epoxy board.
|
||||
*
|
||||
* @return the shape polygon
|
||||
*/
|
||||
const SHAPE_POLY_SET& GetBoardPoly() const noexcept { return m_board_poly; }
|
||||
|
||||
/**
|
||||
* Get the technical color of a layer.
|
||||
*
|
||||
* @param aLayerId the layer to get the color information.
|
||||
* @return the color in SFVEC3F format.
|
||||
*/
|
||||
SFVEC4F GetLayerColor( PCB_LAYER_ID aLayerId ) const;
|
||||
|
||||
/**
|
||||
* Get the technical color of a layer.
|
||||
*
|
||||
* @param aItemId the item id to get the color information.
|
||||
* @return the color in SFVEC3F format.
|
||||
*/
|
||||
SFVEC4F GetItemColor( int aItemId ) const;
|
||||
|
||||
/**
|
||||
* @param[in] aColor is the color mapped.
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC4F GetColor( const COLOR4D& aColor ) const;
|
||||
|
||||
SFVEC2F GetSphericalCoord( int i ) const;
|
||||
|
||||
/**
|
||||
* Get the top z position.
|
||||
*
|
||||
* @param aLayerId layer id.
|
||||
* @return position in 3D units.
|
||||
*/
|
||||
float GetLayerTopZPos( PCB_LAYER_ID aLayerId ) const noexcept
|
||||
{
|
||||
auto it = m_layerZcoordTop.find( aLayerId );
|
||||
|
||||
if( it != m_layerZcoordTop.end() )
|
||||
return it->second;
|
||||
else
|
||||
return -( m_boardBodyThickness3DU / 2.0f );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bottom z position.
|
||||
*
|
||||
* @param aLayerId layer id.
|
||||
* @return position in 3D units.
|
||||
*/
|
||||
float GetLayerBottomZPos( PCB_LAYER_ID aLayerId ) const noexcept
|
||||
{
|
||||
auto it = m_layerZcoordBottom.find( aLayerId );
|
||||
|
||||
if( it != m_layerZcoordBottom.end() )
|
||||
return it->second;
|
||||
else
|
||||
return -( m_boardBodyThickness3DU / 2.0f ) - m_backCopperThickness3DU;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map of containers that have the objects per layer.
|
||||
*
|
||||
* @return the map containers of this board.
|
||||
*/
|
||||
const MAP_CONTAINER_2D_BASE& GetLayerMap() const noexcept { return m_layerMap; }
|
||||
const BVH_CONTAINER_2D* GetPlatedPadsFront() const noexcept { return m_platedPadsFront; }
|
||||
const BVH_CONTAINER_2D* GetPlatedPadsBack() const noexcept { return m_platedPadsBack; }
|
||||
const BVH_CONTAINER_2D* GetOffboardPadsFront() const noexcept { return m_offboardPadsFront; }
|
||||
const BVH_CONTAINER_2D* GetOffboardPadsBack() const noexcept { return m_offboardPadsBack; }
|
||||
|
||||
const MAP_CONTAINER_2D_BASE& GetLayerHoleMap() const noexcept { return m_layerHoleMap; }
|
||||
const BVH_CONTAINER_2D& GetTH_IDs() const noexcept { return m_TH_IDs; }
|
||||
const BVH_CONTAINER_2D& GetTH_ODs() const noexcept { return m_TH_ODs; }
|
||||
|
||||
/**
|
||||
* Get through hole outside diameter 2D polygons.
|
||||
*
|
||||
* The outside diameter 2D polygon is the hole diameter plus the plating thickness.
|
||||
*
|
||||
* @return a container with through hold outside diameter 2D polygons.
|
||||
*/
|
||||
const SHAPE_POLY_SET& GetTH_ODPolys() const noexcept
|
||||
{
|
||||
return m_TH_ODPolys;
|
||||
}
|
||||
|
||||
const BVH_CONTAINER_2D& GetViaAnnuli() const noexcept
|
||||
{
|
||||
return m_viaAnnuli;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetViaAnnuliPolys() const noexcept
|
||||
{
|
||||
return m_viaAnnuliPolys;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetNPTH_ODPolys() const noexcept
|
||||
{
|
||||
return m_NPTH_ODPolys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a container with through hole via hole outside diameters.
|
||||
*/
|
||||
const BVH_CONTAINER_2D& GetViaTH_ODs() const noexcept
|
||||
{
|
||||
return m_viaTH_ODs;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetViaTH_ODPolys() const noexcept
|
||||
{
|
||||
return m_viaTH_ODPolys;
|
||||
}
|
||||
|
||||
unsigned int GetViaCount() const noexcept { return m_viaCount; }
|
||||
unsigned int GetHoleCount() const noexcept { return m_holeCount; }
|
||||
|
||||
/**
|
||||
* @return via hole average diameter dimension in 3D units.
|
||||
*/
|
||||
float GetAverageViaHoleDiameter() const noexcept { return m_averageViaHoleDiameter; }
|
||||
|
||||
/**
|
||||
* @return the average diameter of through holes in 3D units.
|
||||
*/
|
||||
float GetAverageHoleDiameter() const noexcept { return m_averageHoleDiameter; }
|
||||
|
||||
/**
|
||||
* @return average track width in 3D units.
|
||||
*/
|
||||
float GetAverageTrackWidth() const noexcept { return m_averageTrackWidth; }
|
||||
|
||||
/**
|
||||
* @param aDiameter3DU diameter in 3DU.
|
||||
* @return number of sides that should be used in a circle with \a aDiameter3DU.
|
||||
*/
|
||||
unsigned int GetCircleSegmentCount( float aDiameter3DU ) const;
|
||||
|
||||
/**
|
||||
* @param aDiameterBIU diameter in board internal units.
|
||||
* @return number of sides that should be used in circle with \a aDiameterBIU.
|
||||
*/
|
||||
unsigned int GetCircleSegmentCount( int aDiameterBIU ) const;
|
||||
|
||||
/**
|
||||
* Get map of polygon's layers.
|
||||
*
|
||||
* @return the map with polygon's layers.
|
||||
*/
|
||||
const MAP_POLY& GetPolyMap() const noexcept { return m_layers_poly; }
|
||||
|
||||
const SHAPE_POLY_SET* GetFrontPlatedPadAndGraphicPolys()
|
||||
{
|
||||
return m_frontPlatedPadAndGraphicPolys;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET* GetBackPlatedPadAndGraphicPolys()
|
||||
{
|
||||
return m_backPlatedPadAndGraphicPolys;
|
||||
}
|
||||
|
||||
const MAP_POLY& GetHoleIdPolysMap() const noexcept { return m_layerHoleIdPolys; }
|
||||
const MAP_POLY& GetHoleOdPolysMap() const noexcept { return m_layerHoleOdPolys; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Create the board outline polygon.
|
||||
*
|
||||
* @return false if the outline could not be created
|
||||
*/
|
||||
bool createBoardPolygon( wxString* aErrorMsg );
|
||||
void createLayers( REPORTER* aStatusReporter );
|
||||
void destroyLayers();
|
||||
|
||||
// Helper functions to create the board
|
||||
void createTrackWithMargin( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayer, int aMargin = 0 );
|
||||
|
||||
void createPadWithMargin( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const;
|
||||
|
||||
void createPadWithHole( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||
int aInflateValue );
|
||||
|
||||
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads );
|
||||
|
||||
void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
const std::bitset<LAYER_3D_END>& aVisibilityFlags );
|
||||
|
||||
void addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aDstContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner, PCB_LAYER_ID aLayer );
|
||||
|
||||
void addShape( const PCB_DIMENSION_BASE* aDimension, CONTAINER_2D_BASE* aDstContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addTable( const PCB_TABLE* aTable, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
void createArcSegments( const VECTOR2I& aCentre, const VECTOR2I& aStart,
|
||||
const EDA_ANGLE& aArcAngle, int aCircleToSegmentsCount, int aWidth,
|
||||
CONTAINER_2D_BASE* aContainer, const BOARD_ITEM& aOwner );
|
||||
|
||||
void buildPadOutlineAsSegments( const PAD* aPad, PCB_LAYER_ID aLayer,
|
||||
CONTAINER_2D_BASE* aDstContainer, int aWidth );
|
||||
|
||||
public:
|
||||
static CUSTOM_COLORS_LIST g_SilkColors;
|
||||
static CUSTOM_COLORS_LIST g_MaskColors;
|
||||
static CUSTOM_COLORS_LIST g_PasteColors;
|
||||
static CUSTOM_COLORS_LIST g_FinishColors;
|
||||
static CUSTOM_COLORS_LIST g_BoardColors;
|
||||
|
||||
static KIGFX::COLOR4D g_DefaultBackgroundTop;
|
||||
static KIGFX::COLOR4D g_DefaultBackgroundBot;
|
||||
static KIGFX::COLOR4D g_DefaultSilkscreen;
|
||||
static KIGFX::COLOR4D g_DefaultSolderMask;
|
||||
static KIGFX::COLOR4D g_DefaultSolderPaste;
|
||||
static KIGFX::COLOR4D g_DefaultSurfaceFinish;
|
||||
static KIGFX::COLOR4D g_DefaultBoardBody;
|
||||
static KIGFX::COLOR4D g_DefaultComments;
|
||||
static KIGFX::COLOR4D g_DefaultECOs;
|
||||
|
||||
public:
|
||||
EDA_3D_VIEWER_SETTINGS* m_Cfg;
|
||||
|
||||
bool m_IsBoardView;
|
||||
bool m_MousewheelPanning;
|
||||
bool m_IsPreviewer; ///< true if we're in a 3D preview panel, false
|
||||
///< for the standard 3D viewer
|
||||
|
||||
SFVEC4F m_BgColorBot; ///< background bottom color
|
||||
SFVEC4F m_BgColorTop; ///< background top color
|
||||
SFVEC4F m_BoardBodyColor; ///< in realistic mode: FR4 board color
|
||||
SFVEC4F m_SolderMaskColorBot; ///< in realistic mode: solder mask color ( bot )
|
||||
SFVEC4F m_SolderMaskColorTop; ///< in realistic mode: solder mask color ( top )
|
||||
SFVEC4F m_SolderPasteColor; ///< in realistic mode: solder paste color
|
||||
SFVEC4F m_SilkScreenColorBot; ///< in realistic mode: SilkScreen color ( bot )
|
||||
SFVEC4F m_SilkScreenColorTop; ///< in realistic mode: SilkScreen color ( top )
|
||||
SFVEC4F m_CopperColor; ///< in realistic mode: copper color
|
||||
SFVEC4F m_UserDrawingsColor;
|
||||
SFVEC4F m_UserCommentsColor;
|
||||
SFVEC4F m_ECO1Color;
|
||||
SFVEC4F m_ECO2Color;
|
||||
|
||||
std::map<int, COLOR4D> m_ColorOverrides; ///< allows to override color scheme colors
|
||||
std::map<int, COLOR4D> m_BoardEditorColors; ///< list of colors used by the board editor
|
||||
|
||||
private:
|
||||
BOARD* m_board;
|
||||
S3D_CACHE* m_3dModelManager;
|
||||
COLOR_SETTINGS* m_colors;
|
||||
|
||||
VECTOR2I m_boardPos; ///< Board center position in board internal units.
|
||||
VECTOR2I m_boardSize; ///< Board size in board internal units.
|
||||
SFVEC3F m_boardCenter; ///< 3D center position of the board in 3D units.
|
||||
BBOX_3D m_boardBoundingBox; ///< 3D bounding box of the board in 3D units.
|
||||
|
||||
MAP_POLY m_layers_poly; ///< Amalgamated polygon contours for various types
|
||||
///< of items
|
||||
|
||||
SHAPE_POLY_SET* m_frontPlatedPadAndGraphicPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedPadAndGraphicPolys;
|
||||
SHAPE_POLY_SET* m_frontPlatedCopperPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedCopperPolys;
|
||||
|
||||
MAP_POLY m_layerHoleOdPolys; ///< Hole outer diameters (per layer)
|
||||
MAP_POLY m_layerHoleIdPolys; ///< Hole inner diameters (per layer)
|
||||
|
||||
SHAPE_POLY_SET m_NPTH_ODPolys; ///< NPTH outer diameters
|
||||
SHAPE_POLY_SET m_TH_ODPolys; ///< PTH outer diameters
|
||||
SHAPE_POLY_SET m_viaTH_ODPolys; ///< Via hole outer diameters
|
||||
SHAPE_POLY_SET m_viaAnnuliPolys; ///< Via annular ring outer diameters
|
||||
|
||||
SHAPE_POLY_SET m_board_poly; ///< Board outline polygon.
|
||||
|
||||
MAP_CONTAINER_2D_BASE m_layerMap; ///< 2D elements for each layer.
|
||||
MAP_CONTAINER_2D_BASE m_layerHoleMap; ///< Holes for each layer.
|
||||
|
||||
BVH_CONTAINER_2D* m_platedPadsFront;
|
||||
BVH_CONTAINER_2D* m_platedPadsBack;
|
||||
BVH_CONTAINER_2D* m_offboardPadsFront;
|
||||
BVH_CONTAINER_2D* m_offboardPadsBack;
|
||||
|
||||
BVH_CONTAINER_2D m_TH_ODs; ///< List of PTH outer diameters
|
||||
BVH_CONTAINER_2D m_TH_IDs; ///< List of PTH inner diameters
|
||||
BVH_CONTAINER_2D m_viaAnnuli; ///< List of via annular rings
|
||||
BVH_CONTAINER_2D m_viaTH_ODs; ///< List of via hole outer diameters
|
||||
|
||||
unsigned int m_copperLayersCount;
|
||||
|
||||
double m_biuTo3Dunits; ///< Scale factor to convert board internal units
|
||||
///< to 3D units normalized between -1.0 and 1.0.
|
||||
|
||||
std::map<PCB_LAYER_ID, float> m_layerZcoordTop; ///< Top (End) Z position of each
|
||||
///< layer in 3D units.
|
||||
|
||||
std::map<PCB_LAYER_ID, float> m_layerZcoordBottom; ///< Bottom (Start) Z position of
|
||||
///< each layer in 3D units.
|
||||
|
||||
float m_frontCopperThickness3DU;
|
||||
float m_backCopperThickness3DU;
|
||||
float m_boardBodyThickness3DU;
|
||||
float m_nonCopperLayerThickness3DU;
|
||||
float m_solderPasteLayerThickness3DU;
|
||||
|
||||
unsigned int m_trackCount;
|
||||
float m_averageTrackWidth;
|
||||
unsigned int m_viaCount;
|
||||
float m_averageViaHoleDiameter;
|
||||
unsigned int m_holeCount;
|
||||
float m_averageHoleDiameter;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable debug output for this class. Output can be turned
|
||||
* on by setting the WXTRACE environment variable to "KI_TRACE_EDA_CINFO3D_VISU". See the
|
||||
* wxWidgets documentation on wxLogTrace for more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // BOARD_ADAPTER_H
|
||||
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cinfo3d_visu.cpp
|
||||
* @brief Handles data related with the board to be visualized
|
||||
*/
|
||||
|
||||
#include "../3d_rendering/ccamera.h"
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h>
|
||||
#include <class_board.h>
|
||||
#include <3d_math.h>
|
||||
#include "3d_fastmath.h"
|
||||
#include <geometry/geometry_utils.h>
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
const wxChar *CINFO3D_VISU::m_logTrace = wxT( "KI_TRACE_EDA_CINFO3D_VISU" );
|
||||
|
||||
|
||||
CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
|
||||
CINFO3D_VISU::CINFO3D_VISU() :
|
||||
m_currentCamera( m_trackBallCamera ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::CINFO3D_VISU" ) );
|
||||
|
||||
m_board = NULL;
|
||||
m_3d_model_manager = NULL;
|
||||
m_3D_grid_type = GRID3D_NONE;
|
||||
m_drawFlags.resize( FL_LAST, false );
|
||||
|
||||
m_render_engine = RENDER_ENGINE_OPENGL_LEGACY;
|
||||
m_material_mode = MATERIAL_MODE_NORMAL;
|
||||
|
||||
m_boardPos = wxPoint();
|
||||
m_boardSize = wxSize();
|
||||
m_boardCenter = SFVEC3F( 0.0f );
|
||||
|
||||
m_boardBoudingBox.Reset();
|
||||
|
||||
m_layers_container2D.clear();
|
||||
m_layers_holes2D.clear();
|
||||
m_through_holes_inner.Clear();
|
||||
m_through_holes_outer.Clear();
|
||||
|
||||
m_copperLayersCount = -1;
|
||||
m_epoxyThickness3DU = 0.0f;
|
||||
m_copperThickness3DU = 0.0f;
|
||||
m_nonCopperLayerThickness3DU = 0.0f;
|
||||
m_biuTo3Dunits = 1.0;
|
||||
|
||||
m_stats_nr_tracks = 0;
|
||||
m_stats_nr_vias = 0;
|
||||
m_stats_via_med_hole_diameter = 0.0f;
|
||||
m_stats_nr_holes = 0;
|
||||
m_stats_hole_med_diameter = 0.0f;
|
||||
m_stats_track_med_width = 0.0f;
|
||||
|
||||
m_calc_seg_min_factor3DU = 0.0f;
|
||||
m_calc_seg_max_factor3DU = 0.0f;
|
||||
|
||||
|
||||
memset( m_layerZcoordTop, 0, sizeof( m_layerZcoordTop ) );
|
||||
memset( m_layerZcoordBottom, 0, sizeof( m_layerZcoordBottom ) );
|
||||
|
||||
SetFlag( FL_USE_REALISTIC_MODE, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_SHOW_BOARD_BODY, true );
|
||||
SetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL, true );
|
||||
SetFlag( FL_ZONE, true );
|
||||
SetFlag( FL_SILKSCREEN, true );
|
||||
SetFlag( FL_SOLDERMASK, true );
|
||||
|
||||
m_BgColorBot = SFVEC3D( 0.4, 0.4, 0.5 );
|
||||
m_BgColorTop = SFVEC3D( 0.8, 0.8, 0.9 );
|
||||
m_BoardBodyColor = SFVEC3D( 0.4, 0.4, 0.5 );
|
||||
m_SolderMaskColor = SFVEC3D( 0.1, 0.2, 0.1 );
|
||||
m_SolderPasteColor = SFVEC3D( 0.4, 0.4, 0.4 );
|
||||
m_SilkScreenColor = SFVEC3D( 0.9, 0.9, 0.9 );
|
||||
m_CopperColor = SFVEC3D( 0.75, 0.61, 0.23 );
|
||||
}
|
||||
|
||||
|
||||
CINFO3D_VISU::~CINFO3D_VISU()
|
||||
{
|
||||
destroyLayers();
|
||||
}
|
||||
|
||||
|
||||
bool CINFO3D_VISU::Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
wxASSERT( aLayer < PCB_LAYER_ID_COUNT );
|
||||
|
||||
DISPLAY3D_FLG flg;
|
||||
|
||||
// see if layer needs to be shown
|
||||
// check the flags
|
||||
switch( aLayer )
|
||||
{
|
||||
case B_Adhes:
|
||||
case F_Adhes:
|
||||
flg = FL_ADHESIVE;
|
||||
break;
|
||||
|
||||
case B_Paste:
|
||||
case F_Paste:
|
||||
flg = FL_SOLDERPASTE;
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
case F_SilkS:
|
||||
flg = FL_SILKSCREEN;
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case F_Mask:
|
||||
flg = FL_SOLDERMASK;
|
||||
break;
|
||||
|
||||
case Dwgs_User:
|
||||
case Cmts_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
flg = FL_COMMENTS;
|
||||
break;
|
||||
|
||||
case Eco1_User:
|
||||
case Eco2_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
flg = FL_ECO;
|
||||
break;
|
||||
|
||||
case Edge_Cuts:
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) || GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case Margin:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case B_Cu:
|
||||
case F_Cu:
|
||||
return m_board->GetDesignSettings().IsLayerVisible( aLayer ) ||
|
||||
GetFlag( FL_USE_REALISTIC_MODE );
|
||||
break;
|
||||
|
||||
default:
|
||||
// the layer is an internal copper layer, used the visibility
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) &&
|
||||
(m_render_engine == RENDER_ENGINE_OPENGL_LEGACY) )
|
||||
{
|
||||
// Do not render internal layers if it is overlap with the board
|
||||
// (on OpenGL render)
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_board->GetDesignSettings().IsLayerVisible( aLayer );
|
||||
}
|
||||
|
||||
// The layer has a flag, return the flag
|
||||
return GetFlag( flg );
|
||||
}
|
||||
|
||||
|
||||
bool CINFO3D_VISU::GetFlag( DISPLAY3D_FLG aFlag ) const
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
return m_drawFlags[aFlag];
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::SetFlag( DISPLAY3D_FLG aFlag, bool aState )
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
m_drawFlags[aFlag] = aState;
|
||||
}
|
||||
|
||||
bool CINFO3D_VISU::ShouldModuleBeDisplayed( MODULE_ATTR_T aModuleAttributs ) const
|
||||
{
|
||||
if( ( ( aModuleAttributs == MOD_DEFAULT ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_NORMAL ) ) ||
|
||||
( ( ( aModuleAttributs & MOD_CMS) == MOD_CMS ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT ) ) ||
|
||||
( ( ( aModuleAttributs & MOD_VIRTUAL) == MOD_VIRTUAL ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// !TODO: define the actual copper thickness by user
|
||||
#define COPPER_THICKNESS KiROUND( 0.035 * IU_PER_MM ) // for 35 um
|
||||
#define TECH_LAYER_THICKNESS KiROUND( 0.04 * IU_PER_MM )
|
||||
|
||||
int CINFO3D_VISU::GetCopperThicknessBIU() const
|
||||
{
|
||||
return COPPER_THICKNESS;
|
||||
}
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( float aDiameter3DU ) const
|
||||
{
|
||||
wxASSERT( aDiameter3DU > 0.0f );
|
||||
|
||||
return GetNrSegmentsCircle( (int)( aDiameter3DU / m_biuTo3Dunits ) );
|
||||
}
|
||||
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( int aDiameterBIU ) const
|
||||
{
|
||||
wxASSERT( aDiameterBIU > 0 );
|
||||
|
||||
// Require at least 3 segments for a circle
|
||||
return std::max( GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, 360.0 ), 3 );
|
||||
}
|
||||
|
||||
|
||||
double CINFO3D_VISU::GetCircleCorrectionFactor( int aNrSides ) const
|
||||
{
|
||||
wxASSERT( aNrSides >= 3 );
|
||||
|
||||
return GetCircletoPolyCorrectionFactor( aNrSides );
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::InitSettings( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::InitSettings" ) );
|
||||
|
||||
// Calculates the board bounding box (board outlines + items)
|
||||
// to ensure any item, even outside the board outlines can be seen
|
||||
EDA_RECT bbbox = m_board->ComputeBoundingBox( false );
|
||||
|
||||
// Gives a non null size to avoid issues in zoom / scale calculations
|
||||
if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
|
||||
bbbox.Inflate( Millimeter2iu( 10 ) );
|
||||
|
||||
m_boardSize = bbbox.GetSize();
|
||||
m_boardPos = bbbox.Centre();
|
||||
|
||||
wxASSERT( (m_boardSize.x > 0) && (m_boardSize.y > 0) );
|
||||
|
||||
m_boardPos.y = -m_boardPos.y; // The y coord is inverted in 3D viewer
|
||||
|
||||
m_copperLayersCount = m_board->GetCopperLayerCount();
|
||||
|
||||
// Ensure the board has 2 sides for 3D views, because it is hard to find
|
||||
// a *really* single side board in the true life...
|
||||
if( m_copperLayersCount < 2 )
|
||||
m_copperLayersCount = 2;
|
||||
|
||||
// Calculate the convertion to apply to all positions.
|
||||
m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y );
|
||||
|
||||
m_epoxyThickness3DU = m_board->GetDesignSettings().GetBoardThickness() *
|
||||
m_biuTo3Dunits;
|
||||
|
||||
// !TODO: use value defined by user (currently use default values by ctor
|
||||
m_copperThickness3DU = COPPER_THICKNESS * m_biuTo3Dunits;
|
||||
m_nonCopperLayerThickness3DU = TECH_LAYER_THICKNESS * m_biuTo3Dunits;
|
||||
|
||||
// Init Z position of each layer
|
||||
// calculate z position for each copper layer
|
||||
// Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31)
|
||||
// Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0)
|
||||
// all unused copper layer z position are set to 0
|
||||
|
||||
// ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0,
|
||||
// | | Top = Bottom + m_copperThickness
|
||||
// |__________________________________|
|
||||
// == == == == <- Bottom = -m_epoxyThickness / 2.0,
|
||||
// Top = Bottom - m_copperThickness
|
||||
|
||||
unsigned int layer;
|
||||
|
||||
for( layer = 0; layer < m_copperLayersCount; ++layer )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f -
|
||||
(m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) );
|
||||
|
||||
if( layer < (m_copperLayersCount / 2) )
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_copperThickness3DU;
|
||||
else
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_copperThickness3DU;
|
||||
}
|
||||
|
||||
#define layerThicknessMargin 1.1
|
||||
const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
|
||||
|
||||
// Fill remaining unused copper layers and back layer zpos
|
||||
// with -m_epoxyThickness / 2.0
|
||||
for( ; layer < MAX_CU_LAYERS; layer++ )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f);
|
||||
m_layerZcoordTop[layer] = -(m_epoxyThickness3DU / 2.0f) - m_copperThickness3DU;
|
||||
}
|
||||
|
||||
// This is the top of the copper layer thickness.
|
||||
const float zpos_copperTop_back = m_layerZcoordTop[B_Cu];
|
||||
const float zpos_copperTop_front = m_layerZcoordTop[F_Cu];
|
||||
|
||||
// calculate z position for each non copper layer
|
||||
// Solder mask and Solder paste have the same Z position
|
||||
for( int layer_id = MAX_CU_LAYERS; layer_id < PCB_LAYER_ID_COUNT; ++layer_id )
|
||||
{
|
||||
float zposTop;
|
||||
float zposBottom;
|
||||
|
||||
switch( layer_id )
|
||||
{
|
||||
case B_Adhes:
|
||||
zposBottom = zpos_copperTop_back - 2.0f * zpos_offset;
|
||||
zposTop = zposBottom - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Adhes:
|
||||
zposBottom = zpos_copperTop_front + 2.0f * zpos_offset;
|
||||
zposTop = zposBottom + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case B_Paste:
|
||||
zposBottom = zpos_copperTop_back;
|
||||
zposTop = zpos_copperTop_back - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Mask:
|
||||
case F_Paste:
|
||||
zposTop = zpos_copperTop_front + m_nonCopperLayerThickness3DU;
|
||||
zposBottom = zpos_copperTop_front;
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
zposBottom = zpos_copperTop_back - 1.0f * zpos_offset;
|
||||
zposTop = zposBottom - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_SilkS:
|
||||
zposBottom = zpos_copperTop_front + 1.0f * zpos_offset;
|
||||
zposTop = zposBottom + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
// !TODO: review
|
||||
default:
|
||||
zposTop = zpos_copperTop_front + (layer_id - MAX_CU_LAYERS + 3.0f) * zpos_offset;
|
||||
zposBottom = zposTop - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
}
|
||||
|
||||
m_layerZcoordTop[layer_id] = zposTop;
|
||||
m_layerZcoordBottom[layer_id] = zposBottom;
|
||||
}
|
||||
|
||||
m_boardCenter = SFVEC3F( m_boardPos.x * m_biuTo3Dunits,
|
||||
m_boardPos.y * m_biuTo3Dunits,
|
||||
0.0f );
|
||||
|
||||
SFVEC3F boardSize = SFVEC3F( m_boardSize.x * m_biuTo3Dunits,
|
||||
m_boardSize.y * m_biuTo3Dunits,
|
||||
0.0f );
|
||||
boardSize /= 2.0f;
|
||||
|
||||
SFVEC3F boardMin = (m_boardCenter - boardSize);
|
||||
SFVEC3F boardMax = (m_boardCenter + boardSize);
|
||||
|
||||
boardMin.z = m_layerZcoordTop[B_Adhes];
|
||||
boardMax.z = m_layerZcoordTop[F_Adhes];
|
||||
|
||||
m_boardBoudingBox = CBBOX( boardMin, boardMax );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_startCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Build board body" ) );
|
||||
|
||||
createBoardPolygon();
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_stopCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
unsigned stats_startCreateLayersTime = stats_stopCreateBoardPolyTime;
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Create layers" ) );
|
||||
|
||||
createLayers( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_stopCreateLayersTime = GetRunningMicroSecs();
|
||||
|
||||
printf( "CINFO3D_VISU::InitSettings times\n" );
|
||||
printf( " CreateBoardPoly: %.3f ms\n",
|
||||
(float)( stats_stopCreateBoardPolyTime - stats_startCreateBoardPolyTime ) / 1e3 );
|
||||
printf( " CreateLayers and holes: %.3f ms\n",
|
||||
(float)( stats_stopCreateLayersTime - stats_startCreateLayersTime ) / 1e3 );
|
||||
printf( "\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::createBoardPolygon()
|
||||
{
|
||||
m_board_poly.RemoveAllContours();
|
||||
|
||||
wxString errmsg;
|
||||
|
||||
if( !m_board->GetBoardPolygonOutlines( m_board_poly, /*allLayerHoles,*/ &errmsg ) )
|
||||
{
|
||||
errmsg.append( wxT( "\n\n" ) );
|
||||
errmsg.append( _( "Cannot determine the board outline." ) );
|
||||
wxLogMessage( errmsg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float CINFO3D_VISU::GetModulesZcoord3DIU( bool aIsFlipped ) const
|
||||
{
|
||||
if( aIsFlipped )
|
||||
{
|
||||
if( GetFlag( FL_SOLDERPASTE ) )
|
||||
return m_layerZcoordBottom[B_SilkS];
|
||||
else
|
||||
return m_layerZcoordBottom[B_Paste];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetFlag( FL_SOLDERPASTE ) )
|
||||
return m_layerZcoordTop[F_SilkS];
|
||||
else
|
||||
return m_layerZcoordTop[F_Paste];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::CameraSetType( CAMERA_TYPE aCameraType )
|
||||
{
|
||||
switch( aCameraType )
|
||||
{
|
||||
case CAMERA_TRACKBALL:
|
||||
m_currentCamera = m_trackBallCamera;
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "CINFO3D_VISU::CameraSetType() error: unknown camera type %d" ),
|
||||
(int)aCameraType );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetLayerColor( PCB_LAYER_ID aLayerId ) const
|
||||
{
|
||||
wxASSERT( aLayerId < PCB_LAYER_ID_COUNT );
|
||||
|
||||
const COLOR4D color = m_board->Colors().GetLayerColor( aLayerId );
|
||||
|
||||
return SFVEC3F( color.r, color.g, color.b );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetItemColor( int aItemId ) const
|
||||
{
|
||||
return GetColor( m_board->Colors().GetItemColor( aItemId ) );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetColor( COLOR4D aColor ) const
|
||||
{
|
||||
return SFVEC3F( aColor.r, aColor.g, aColor.b );
|
||||
}
|
||||
@@ -0,0 +1,677 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cinfo3d_visu.h
|
||||
* @brief Handles data related with the board to be visualized
|
||||
*/
|
||||
|
||||
#ifndef CINFO3D_VISU_H
|
||||
#define CINFO3D_VISU_H
|
||||
|
||||
#include <vector>
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../3d_rendering/ccamera.h"
|
||||
#include "../3d_rendering/ctrack_ball.h"
|
||||
#include "../3d_enums.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <class_pcb_text.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_dimension.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_module.h>
|
||||
#include <reporter.h>
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, CBVHCONTAINER2D *> MAP_CONTAINER_2D;
|
||||
|
||||
/// A type that stores polysets for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, SHAPE_POLY_SET *> MAP_POLY;
|
||||
|
||||
/// This defines the range that all coord will have to be rendered.
|
||||
/// It will use this value to convert to a normalized value between
|
||||
/// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
/**
|
||||
* Class CINFO3D_VISU
|
||||
* Helper class to handle information needed to display 3D board
|
||||
*/
|
||||
class CINFO3D_VISU
|
||||
{
|
||||
public:
|
||||
|
||||
CINFO3D_VISU();
|
||||
|
||||
~CINFO3D_VISU();
|
||||
|
||||
/**
|
||||
* @brief Set3DCacheManager - Update the Cache manager pointer
|
||||
* @param aCachePointer: the pointer to the 3d cache manager
|
||||
*/
|
||||
void Set3DCacheManager( S3D_CACHE *aCachePointer ) { m_3d_model_manager = aCachePointer; }
|
||||
|
||||
/**
|
||||
* @brief Get3DCacheManager - Return the 3d cache manager pointer
|
||||
* @return
|
||||
*/
|
||||
S3D_CACHE *Get3DCacheManager( ) const { return m_3d_model_manager; }
|
||||
|
||||
/**
|
||||
* @brief GetFlag - get a configuration status of a flag
|
||||
* @param aFlag: the flag to get the status
|
||||
* @return true if flag is set, false if not
|
||||
*/
|
||||
bool GetFlag( DISPLAY3D_FLG aFlag ) const ;
|
||||
|
||||
/**
|
||||
* @brief SetFlag - set the status of a flag
|
||||
* @param aFlag: the flag to get the status
|
||||
* @param aState: status to set
|
||||
*/
|
||||
void SetFlag( DISPLAY3D_FLG aFlag, bool aState );
|
||||
|
||||
/**
|
||||
* @brief Is3DLayerEnabled - Check if a layer is enabled
|
||||
* @param aLayer: layer ID to get status
|
||||
* @return true if layer should be displayed, false if not
|
||||
*/
|
||||
bool Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const;
|
||||
|
||||
/**
|
||||
* @brief ShouldModuleBeDisplayed - Test if module should be displayed in
|
||||
* relation to attributs and the flags
|
||||
* @return true if module should be displayed, false if not
|
||||
*/
|
||||
bool ShouldModuleBeDisplayed( MODULE_ATTR_T aModuleAttributs ) const;
|
||||
|
||||
/**
|
||||
* @brief SetBoard - Set current board to be rendered
|
||||
* @param aBoard: board to process
|
||||
*/
|
||||
void SetBoard( BOARD *aBoard ) { m_board = aBoard; }
|
||||
|
||||
/**
|
||||
* @brief GetBoard - Get current board to be rendered
|
||||
* @return BOARD pointer
|
||||
*/
|
||||
const BOARD *GetBoard() const { return m_board; }
|
||||
|
||||
/**
|
||||
* @brief InitSettings - Function to be called by the render when it need to
|
||||
* reload the settings for the board.
|
||||
* @param aStatusTextReporter: the pointer for the status reporter
|
||||
*/
|
||||
void InitSettings( REPORTER *aStatusTextReporter );
|
||||
|
||||
/**
|
||||
* @brief BiuTo3Dunits - Board integer units To 3D units
|
||||
* @return the conversion factor to transform a position from the board to 3d units
|
||||
*/
|
||||
double BiuTo3Dunits() const { return m_biuTo3Dunits; }
|
||||
|
||||
/**
|
||||
* @brief GetBBox3DU - Get the bbox of the pcb board
|
||||
* @return the board bbox in 3d units
|
||||
*/
|
||||
const CBBOX &GetBBox3DU() const { return m_boardBoudingBox; }
|
||||
|
||||
/**
|
||||
* @brief GetEpoxyThickness3DU - Get the current epoxy thickness
|
||||
* @return thickness in 3d unities
|
||||
*/
|
||||
float GetEpoxyThickness3DU() const { return m_epoxyThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetNonCopperLayerThickness3DU - Get the current non copper layers thickness
|
||||
* @return thickness in 3d unities of non copperlayers
|
||||
*/
|
||||
float GetNonCopperLayerThickness3DU() const { return m_nonCopperLayerThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThickness3DU - Get the current copper layer thickness
|
||||
* @return thickness in 3d unities of copperlayers
|
||||
*/
|
||||
float GetCopperThickness3DU() const { return m_copperThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThicknessBIU - Get the current copper layer thickness
|
||||
* @return thickness in board unities
|
||||
*/
|
||||
int GetCopperThicknessBIU() const;
|
||||
|
||||
/**
|
||||
* @brief GetBoardSizeBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxSize GetBoardSizeBIU() const { return m_boardSize; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardPosBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxPoint GetBoardPosBIU() const { return m_boardPos; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardCenter - the board center position in 3d units
|
||||
* @return board center vector position in 3d units
|
||||
*/
|
||||
const SFVEC3F &GetBoardCenter3DU() const { return m_boardCenter; }
|
||||
|
||||
/**
|
||||
* @brief GetModulesZcoord3DIU - Get the position of the module in 3d integer units
|
||||
* considering if it is flipped or not.
|
||||
* @param aIsFlipped: true for use in modules on Front (top) layer, false
|
||||
* if module is on back (bottom) layer
|
||||
* @return the Z position of 3D shapes, in 3D integer units
|
||||
*/
|
||||
float GetModulesZcoord3DIU( bool aIsFlipped ) const ;
|
||||
|
||||
/**
|
||||
* @brief CameraSetType - Set the camera type to use
|
||||
* @param aCameraType: camera type to use in this canvas
|
||||
*/
|
||||
void CameraSetType( CAMERA_TYPE aCameraType );
|
||||
|
||||
/**
|
||||
* @brief CameraGet - get current camera in use
|
||||
* @return a camera
|
||||
*/
|
||||
CCAMERA &CameraGet() const { return m_currentCamera; }
|
||||
|
||||
/**
|
||||
* @brief GridGet - get the current grid
|
||||
* @return space type of the grid
|
||||
*/
|
||||
GRID3D_TYPE GridGet() const { return m_3D_grid_type; }
|
||||
|
||||
/**
|
||||
* @brief GridSet - set the current grid
|
||||
* @param aGridType = the type space of the grid
|
||||
*/
|
||||
void GridSet( GRID3D_TYPE aGridType ) { m_3D_grid_type = aGridType; }
|
||||
|
||||
/**
|
||||
* @brief RenderEngineSet
|
||||
* @param aRenderEngine = the render engine mode selected
|
||||
*/
|
||||
void RenderEngineSet( RENDER_ENGINE aRenderEngine ) { m_render_engine = aRenderEngine; }
|
||||
|
||||
/**
|
||||
* @brief RenderEngineGet
|
||||
* @return render engine on use
|
||||
*/
|
||||
RENDER_ENGINE RenderEngineGet() const { return m_render_engine; }
|
||||
|
||||
/**
|
||||
* @brief MaterialModeSet
|
||||
* @param aMaterialMode = the render material mode
|
||||
*/
|
||||
void MaterialModeSet( MATERIAL_MODE aMaterialMode ) { m_material_mode = aMaterialMode; }
|
||||
|
||||
/**
|
||||
* @brief MaterialModeGet
|
||||
* @return material rendering mode
|
||||
*/
|
||||
MATERIAL_MODE MaterialModeGet() const { return m_material_mode; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardPoly - Get the current polygon of the epoxy board
|
||||
* @return the shape polygon
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetBoardPoly() const { return m_board_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerColor - get the technical color of a layer
|
||||
* @param aLayerId: the layer to get the color information
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetLayerColor( PCB_LAYER_ID aLayerId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetItemColor - get the technical color of a layer
|
||||
* @param aItemId: the item id to get the color information
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetItemColor( int aItemId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetColor
|
||||
* @param aColor: the color mapped
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetColor( COLOR4D aColor ) const;
|
||||
|
||||
/**
|
||||
* @brief GetLayerTopZpos3DU - Get the top z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
*/
|
||||
float GetLayerTopZpos3DU( PCB_LAYER_ID aLayerId ) const { return m_layerZcoordTop[aLayerId]; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerBottomZpos3DU - Get the bottom z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
*/
|
||||
float GetLayerBottomZpos3DU( PCB_LAYER_ID aLayerId ) const { return m_layerZcoordBottom[aLayerId]; }
|
||||
|
||||
/**
|
||||
* @brief GetMapLayers - Get the map of container that have the objects per layer
|
||||
* @return the map containers of this board
|
||||
*/
|
||||
const MAP_CONTAINER_2D &GetMapLayers() const { return m_layers_container2D; }
|
||||
|
||||
/**
|
||||
* @brief GetMapLayersHoles -Get the map of container that have the holes per layer
|
||||
* @return the map containers of holes from this board
|
||||
*/
|
||||
const MAP_CONTAINER_2D &GetMapLayersHoles() const { return m_layers_holes2D; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer - Get the inflated ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Outer() const { return m_through_holes_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Outer_poly() const { return m_through_outer_holes_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer_poly_NPTH -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Outer_poly_NPTH() const {
|
||||
return m_through_outer_holes_poly_NPTH; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Outer -
|
||||
* @return a container with via THT holes only
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Vias_Outer() const { return m_through_holes_vias_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Inner -
|
||||
* @return a container with via THT holes only
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Vias_Inner() const { return m_through_holes_vias_inner; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Outer_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Vias_Outer_poly() const {
|
||||
return m_through_outer_holes_vias_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Inner_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Vias_Inner_poly() const {
|
||||
return m_through_inner_holes_vias_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inner - Get the ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Inner() const { return m_through_holes_inner; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inner_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Inner_poly() const { return m_through_inner_holes_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Nr_Vias - Get statistics of the nr of vias
|
||||
* @return number of vias
|
||||
*/
|
||||
unsigned int GetStats_Nr_Vias() const { return m_stats_nr_vias; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Nr_Holes - Get statistics of the nr of holes
|
||||
* @return number of holes
|
||||
*/
|
||||
unsigned int GetStats_Nr_Holes() const { return m_stats_nr_holes; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Via_Hole_Diameter3DU - Average diameter of the via holes
|
||||
* @return dimension in 3D units
|
||||
*/
|
||||
float GetStats_Med_Via_Hole_Diameter3DU() const { return m_stats_via_med_hole_diameter; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Hole_Diameter3DU - Average diameter of holes
|
||||
* @return dimension in 3D units
|
||||
*/
|
||||
float GetStats_Med_Hole_Diameter3DU() const { return m_stats_hole_med_diameter; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Track_Width - Average width of the tracks
|
||||
* @return dimensions in 3D units
|
||||
*/
|
||||
float GetStats_Med_Track_Width() const { return m_stats_track_med_width; }
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameter3DU: diameter in 3DU
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( float aDiameter3DU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameterBIU: diameter in board internal units
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( int aDiameterBIU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetCircleCorrectionFactor - computes a angle correction
|
||||
* factor used when creating circles
|
||||
* @param aNrSides: the number of segments sides of the circle
|
||||
* @return a factor to apply to contour creation
|
||||
*/
|
||||
double GetCircleCorrectionFactor( int aNrSides ) const;
|
||||
|
||||
/**
|
||||
* @brief GetPolyMap - Get maps of polygons's layers
|
||||
* @return the map with polygons's layers
|
||||
*/
|
||||
const MAP_POLY &GetPolyMap() const { return m_layers_poly; }
|
||||
|
||||
const MAP_POLY &GetPolyMapHoles_Inner() const { return m_layers_inner_holes_poly; }
|
||||
|
||||
const MAP_POLY &GetPolyMapHoles_Outer() const { return m_layers_outer_holes_poly; }
|
||||
|
||||
private:
|
||||
void createBoardPolygon();
|
||||
void createLayers( REPORTER *aStatusTextReporter );
|
||||
void destroyLayers();
|
||||
|
||||
// Helper functions to create the board
|
||||
COBJECT2D *createNewTrack( const TRACK* aTrack , int aClearanceValue ) const;
|
||||
|
||||
void createNewPad( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aInflateValue ) const;
|
||||
|
||||
void createNewPadWithClearance( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aClearanceValue ) const;
|
||||
|
||||
COBJECT2D *createNewPadDrill( const D_PAD* aPad, int aInflateValue );
|
||||
|
||||
void AddPadsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper );
|
||||
|
||||
void AddGraphicsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const TEXTE_PCB *aTextPCB,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DRAWSEGMENT *aDrawSegment,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DIMENSION *aDimension,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddSolidAreasShapesToContainer( const ZONE_CONTAINER *aZoneContainer,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
void TransformArcToSegments( const wxPoint &aCentre,
|
||||
const wxPoint &aStart,
|
||||
double aArcAngle,
|
||||
int aCircleToSegmentsCount,
|
||||
int aWidth,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
const BOARD_ITEM &aBoardItem );
|
||||
|
||||
void buildPadShapeThickOutlineAsSegments( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
int aWidth );
|
||||
|
||||
// Helper functions to create poly contours
|
||||
void buildPadShapeThickOutlineAsPolygon( const D_PAD *aPad,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aWidth) const;
|
||||
|
||||
void transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD> &aPads,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper) const;
|
||||
|
||||
void transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const;
|
||||
|
||||
void buildPadShapePolygon( const D_PAD *aPad,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
wxSize aInflateValue,
|
||||
int aSegmentsPerCircle,
|
||||
double aCorrectionFactor ) const;
|
||||
|
||||
|
||||
public:
|
||||
SFVEC3D m_BgColorBot; ///< background bottom color
|
||||
SFVEC3D m_BgColorTop; ///< background top color
|
||||
SFVEC3D m_BoardBodyColor; ///< in realistic mode: FR4 board color
|
||||
SFVEC3D m_SolderMaskColor; ///< in realistic mode: solder mask color
|
||||
SFVEC3D m_SolderPasteColor; ///< in realistic mode: solder paste color
|
||||
SFVEC3D m_SilkScreenColor; ///< in realistic mode: SilkScreen color
|
||||
SFVEC3D m_CopperColor; ///< in realistic mode: copper color
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/// Current board
|
||||
BOARD *m_board;
|
||||
|
||||
/// pointer to the 3d model manager
|
||||
S3D_CACHE *m_3d_model_manager;
|
||||
|
||||
|
||||
// Render options
|
||||
|
||||
/// options flags to render the board
|
||||
std::vector< bool > m_drawFlags;
|
||||
|
||||
/// Stores the current grid type
|
||||
GRID3D_TYPE m_3D_grid_type;
|
||||
|
||||
/// render engine currently on use
|
||||
RENDER_ENGINE m_render_engine;
|
||||
|
||||
/// mode to render the 3d shape models material
|
||||
MATERIAL_MODE m_material_mode;
|
||||
|
||||
|
||||
// Pcb board position
|
||||
|
||||
/// center board actual position in board units
|
||||
wxPoint m_boardPos;
|
||||
|
||||
/// board actual size in board units
|
||||
wxSize m_boardSize;
|
||||
|
||||
/// 3d center position of the pcb board in 3d units
|
||||
SFVEC3F m_boardCenter;
|
||||
|
||||
|
||||
// Pcb board bounding boxes
|
||||
|
||||
/// 3d bouding box of the pcb board in 3d units
|
||||
CBBOX m_boardBoudingBox;
|
||||
|
||||
/// It contains polygon contours for each layer
|
||||
MAP_POLY m_layers_poly;
|
||||
|
||||
/// It contains polygon contours for holes of each layer (outer holes)
|
||||
MAP_POLY m_layers_outer_holes_poly;
|
||||
|
||||
/// It contains polygon contours for holes of each layer (inner holes)
|
||||
MAP_POLY m_layers_inner_holes_poly;
|
||||
|
||||
/// It contains polygon contours for (just) non plated through holes (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_poly_NPTH;
|
||||
|
||||
/// It contains polygon contours for through holes (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_poly;
|
||||
|
||||
/// It contains polygon contours for through holes (inner cylinder)
|
||||
SHAPE_POLY_SET m_through_inner_holes_poly;
|
||||
|
||||
/// It contains polygon contours for through holes vias (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_vias_poly;
|
||||
|
||||
/// It contains polygon contours for through holes vias (inner cylinder)
|
||||
SHAPE_POLY_SET m_through_inner_holes_vias_poly;
|
||||
|
||||
/// PCB board outline polygon
|
||||
SHAPE_POLY_SET m_board_poly;
|
||||
|
||||
|
||||
// 2D element containers
|
||||
|
||||
/// It contains the 2d elements of each layer
|
||||
MAP_CONTAINER_2D m_layers_container2D;
|
||||
|
||||
/// It contains the holes per each layer
|
||||
MAP_CONTAINER_2D m_layers_holes2D;
|
||||
|
||||
/// It contains the list of throughHoles of the board,
|
||||
/// the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_through_holes_outer;
|
||||
|
||||
/// It contains the list of throughHoles of the board,
|
||||
/// the radius is the inner hole
|
||||
CBVHCONTAINER2D m_through_holes_inner;
|
||||
|
||||
/// It contains the list of throughHoles vias of the board,
|
||||
/// the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_through_holes_vias_outer;
|
||||
|
||||
/// It contains the list of throughHoles vias of the board,
|
||||
/// the radius of the hole
|
||||
CBVHCONTAINER2D m_through_holes_vias_inner;
|
||||
|
||||
|
||||
// Layers information
|
||||
|
||||
/// Number of copper layers actually used by the board
|
||||
unsigned int m_copperLayersCount;
|
||||
|
||||
/// Normalization scale to convert board internal units to 3D units to
|
||||
/// normalize 3D units between -1.0 and +1.0
|
||||
double m_biuTo3Dunits;
|
||||
|
||||
/// Top (End) Z position of each layer (normalized)
|
||||
float m_layerZcoordTop[PCB_LAYER_ID_COUNT];
|
||||
|
||||
/// Bottom (Start) Z position of each layer (normalized)
|
||||
float m_layerZcoordBottom[PCB_LAYER_ID_COUNT];
|
||||
|
||||
/// Copper thickness (normalized)
|
||||
float m_copperThickness3DU;
|
||||
|
||||
/// Epoxy thickness (normalized)
|
||||
float m_epoxyThickness3DU;
|
||||
|
||||
/// Non copper layers thickness
|
||||
float m_nonCopperLayerThickness3DU;
|
||||
|
||||
|
||||
// Cameras
|
||||
|
||||
/// Holds a pointer to current camera in use.
|
||||
CCAMERA &m_currentCamera;
|
||||
CTRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// min factor used for cicle segment approximation calculation
|
||||
float m_calc_seg_min_factor3DU;
|
||||
|
||||
/// max factor used for cicle segment approximation calculation
|
||||
float m_calc_seg_max_factor3DU;
|
||||
|
||||
|
||||
// Statistics
|
||||
|
||||
/// Number of tracks in the board
|
||||
unsigned int m_stats_nr_tracks;
|
||||
|
||||
/// Track average width
|
||||
float m_stats_track_med_width;
|
||||
|
||||
/// Nr of vias
|
||||
unsigned int m_stats_nr_vias;
|
||||
|
||||
/// Computed medium diameter of the via holes in 3D units
|
||||
float m_stats_via_med_hole_diameter;
|
||||
|
||||
/// number of holes in the board
|
||||
unsigned int m_stats_nr_holes;
|
||||
|
||||
/// Computed medium diameter of the holes in 3D units
|
||||
float m_stats_hole_med_diameter;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
|
||||
};
|
||||
|
||||
/// This is a dummy visualization configuration
|
||||
extern CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
#endif // CINFO3D_VISU_H
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file create_layer_poly.cpp
|
||||
* @brief This file implements the creation of the pcb board items in the poly
|
||||
* contours format. It is based on the function found in the files:
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
*/
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_module.h>
|
||||
|
||||
|
||||
// This is the same function as in board_items_to_polygon_shape_transform.cpp
|
||||
// but it adds the rect/trapezoid shapes with a different winding
|
||||
void CINFO3D_VISU::buildPadShapePolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
wxSize aInflateValue,
|
||||
int aSegmentsPerCircle,
|
||||
double aCorrectionFactor ) const
|
||||
{
|
||||
wxPoint corners[4];
|
||||
wxPoint PadShapePos = aPad->ShapePos(); /* Note: for pad having a shape offset,
|
||||
* the pad position is NOT the shape position */
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
case PAD_SHAPE_OVAL:
|
||||
case PAD_SHAPE_ROUNDRECT:
|
||||
{
|
||||
// We are using TransformShapeWithClearanceToPolygon to build the shape.
|
||||
// Currently, this method uses only the same inflate value for X and Y dirs.
|
||||
// so because here this is not the case, we use a inflated dummy pad to build
|
||||
// the polygonal shape
|
||||
// TODO: remove this dummy pad when TransformShapeWithClearanceToPolygon will use
|
||||
// a wxSize to inflate the pad size
|
||||
D_PAD dummy( *aPad );
|
||||
wxSize new_size = aPad->GetSize() + aInflateValue + aInflateValue;
|
||||
dummy.SetSize( new_size );
|
||||
dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, 0,
|
||||
aSegmentsPerCircle, aCorrectionFactor );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_RECT:
|
||||
{
|
||||
SHAPE_LINE_CHAIN aLineChain;
|
||||
|
||||
aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
|
||||
|
||||
for( int ii = 0; ii < 4; ++ii )
|
||||
{
|
||||
corners[3-ii] += PadShapePos; // Shift origin to position
|
||||
aLineChain.Append( corners[3-ii].x, corners[3-ii].y );
|
||||
}
|
||||
|
||||
aLineChain.SetClosed( true );
|
||||
|
||||
aCornerBuffer.AddOutline( aLineChain );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
{
|
||||
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
|
||||
polyList.Append( aPad->GetCustomShapeAsPolygon() );
|
||||
aPad->CustomShapeAsPolygonToBoardPosition( &polyList, aPad->ShapePos(), aPad->GetOrientation() );
|
||||
aCornerBuffer.Append( polyList );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aWidth ) const
|
||||
{
|
||||
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
|
||||
{
|
||||
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( ( aPad->GetSize().x / 2 +
|
||||
aWidth / 2 ) * 2 );
|
||||
|
||||
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
|
||||
aPad->GetSize().x / 2, nr_sides_per_circle, aWidth );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// For other shapes, draw polygon outlines
|
||||
SHAPE_POLY_SET corners;
|
||||
|
||||
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
|
||||
aPad->GetSize().y) );
|
||||
buildPadShapePolygon( aPad, corners, wxSize( 0, 0 ),
|
||||
nr_sides_per_circle,
|
||||
GetCircleCorrectionFactor( nr_sides_per_circle ) );
|
||||
|
||||
// Add outlines as thick segments in polygon buffer
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
|
||||
for( int ii = 0; ii < path.PointCount(); ++ii )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( ii );
|
||||
const VECTOR2I& b = path.CPoint( ii + 1 );
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
|
||||
wxPoint( a.x, a.y ),
|
||||
wxPoint( b.x, b.y ),
|
||||
nr_sides_per_circle,
|
||||
aWidth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on the same function name in board_items_to_polyshape_transform.cpp
|
||||
// It was implemented here to allow dynamic segments count per pad shape
|
||||
void CINFO3D_VISU::transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD>& aPads, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper ) const
|
||||
{
|
||||
const D_PAD* pad = aPads;
|
||||
|
||||
wxSize margin;
|
||||
for( ; pad != NULL; pad = pad->Next() )
|
||||
{
|
||||
if( !pad->IsOnLayer(aLayer) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the shape size and pos is the same
|
||||
// as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
|
||||
{
|
||||
if( (pad->GetDrillSize() == pad->GetSize()) &&
|
||||
(pad->GetOffset() == wxPoint( 0, 0 )) )
|
||||
{
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_OVAL:
|
||||
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( aLayer )
|
||||
{
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
|
||||
break;
|
||||
|
||||
case F_Paste:
|
||||
case B_Paste:
|
||||
margin = pad->GetSolderPasteMargin();
|
||||
margin.x += aInflateValue;
|
||||
margin.y += aInflateValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
margin.x = margin.y = aInflateValue;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int aCircleToSegmentsCount = GetNrSegmentsCircle( pad->GetSize().x );
|
||||
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
||||
|
||||
buildPadShapePolygon( pad, aCornerBuffer, margin,
|
||||
aCircleToSegmentsCount, aCorrectionFactor );
|
||||
}
|
||||
}
|
||||
|
||||
void CINFO3D_VISU::transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const
|
||||
{
|
||||
for( const EDA_ITEM* item = aModule->GraphicalItemsList();
|
||||
item != NULL;
|
||||
item = item->Next() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_EDGE_T:
|
||||
{
|
||||
EDGE_MODULE*outline = (EDGE_MODULE*) item;
|
||||
|
||||
if( outline->GetLayer() != aLayer )
|
||||
break;
|
||||
|
||||
unsigned int aCircleToSegmentsCount =
|
||||
GetNrSegmentsCircle( outline->GetBoundingBox().GetSizeMax() );
|
||||
|
||||
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
||||
|
||||
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer,
|
||||
0,
|
||||
aCircleToSegmentsCount,
|
||||
aCorrectionFactor );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+164
-208
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -22,73 +22,61 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_canvas.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef EDA_3D_CANVAS_H
|
||||
#define EDA_3D_CANVAS_H
|
||||
|
||||
#include <atomic>
|
||||
#include "board_adapter.h"
|
||||
#include "3d_rendering/raytracing/accelerators/accelerator_3d.h"
|
||||
#include "3d_rendering/render_3d_base.h"
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include "3d_rendering/c3d_render_base.h"
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h"
|
||||
#include "3d_rendering/3d_render_raytracing/c3d_render_raytracing.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include <gal/hidpi_gl_3D_canvas.h>
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/statusbr.h>
|
||||
#include <pcb_base_frame.h>
|
||||
|
||||
|
||||
class WX_INFOBAR;
|
||||
class wxStatusBar;
|
||||
class BOARD;
|
||||
class RENDER_3D_RAYTRACE_GL;
|
||||
class RENDER_3D_OPENGL;
|
||||
|
||||
|
||||
#define EDA_3D_CANVAS_ID wxID_HIGHEST + 1321
|
||||
|
||||
/**
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class EDA_3D_CANVAS : public HIDPI_GL_3D_CANVAS
|
||||
class EDA_3D_CANVAS : public HIDPI_GL_CANVAS
|
||||
{
|
||||
public:
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create a new 3D Canvas with an attribute list.
|
||||
*
|
||||
* @param aParent the parent creator of this canvas.
|
||||
* @param aGLAttribs openGL attributes created by #OGL_ATT_LIST::GetAttributesList.
|
||||
* @param aBoard The board.
|
||||
* @param aSettings the settings options to be used by this canvas.
|
||||
* @brief EDA_3D_CANVAS - Creates a new 3D Canvas with a attribute list
|
||||
* @param aParent: the parent creator of this canvas
|
||||
* @param aAttribList: a list of openGL options created by GetOpenGL_AttributesList
|
||||
* @param aBoard: The board
|
||||
* @param aSettings: the settings options to be used by this canvas
|
||||
*/
|
||||
EDA_3D_CANVAS( wxWindow* aParent, const wxGLAttributes& aGLAttribs, BOARD_ADAPTER& aSettings,
|
||||
CAMERA& aCamera, S3D_CACHE* a3DCachePointer );
|
||||
EDA_3D_CANVAS( wxWindow *aParent,
|
||||
const int *aAttribList = 0,
|
||||
BOARD *aBoard = NULL,
|
||||
CINFO3D_VISU &aSettings = G_null_CINFO3D_VISU,
|
||||
S3D_CACHE *a3DCachePointer = NULL );
|
||||
|
||||
~EDA_3D_CANVAS();
|
||||
|
||||
/**
|
||||
* Set a dispatcher that processes events and forwards them to tools.
|
||||
*
|
||||
* #DRAW_PANEL_GAL does not take over the ownership. Passing NULL disconnects all event
|
||||
* handlers from the DRAW_PANEL_GAL and parent frame.
|
||||
*
|
||||
* @param aEventDispatcher is the object that will be used for dispatching events.
|
||||
*/
|
||||
void SetEventDispatcher( TOOL_DISPATCHER* aEventDispatcher );
|
||||
void SetStatusBar( wxStatusBar *aStatusBar ) { m_parentStatusBar = aStatusBar; }
|
||||
|
||||
void SetStatusBar( wxStatusBar* aStatusBar )
|
||||
{
|
||||
m_parentStatusBar = aStatusBar;
|
||||
}
|
||||
|
||||
void SetInfoBar( WX_INFOBAR* aInfoBar )
|
||||
{
|
||||
m_parentInfoBar = aInfoBar;
|
||||
}
|
||||
|
||||
void ReloadRequest( BOARD* aBoard = nullptr, S3D_CACHE* aCachePointer = nullptr );
|
||||
void ReloadRequest( BOARD *aBoard = NULL, S3D_CACHE *aCachePointer = NULL );
|
||||
|
||||
/**
|
||||
* Query if there is a pending reload request.
|
||||
*
|
||||
* @return true if it wants to reload, false if there is no reload pending.
|
||||
* @brief IsReloadRequestPending - Query if there is a pending reload request
|
||||
* @return true if it wants to reload, false if there is no reload pending
|
||||
*/
|
||||
bool IsReloadRequestPending() const
|
||||
{
|
||||
@@ -99,241 +87,209 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current render ( a RENDER_3D_RAYTRACE_GL* or a RENDER_3D_OPENGL* render )
|
||||
*/
|
||||
RENDER_3D_BASE* GetCurrentRender() const { return m_3d_render; }
|
||||
|
||||
/**
|
||||
* Request to render the current view in Raytracing mode.
|
||||
* @brief RenderRaytracingRequest - Request to render the current view in Raytracing mode
|
||||
*/
|
||||
void RenderRaytracingRequest();
|
||||
|
||||
/**
|
||||
* Request a screenshot and output it to the \a aDstImage.
|
||||
*
|
||||
* @param aDstImage - Screenshot destination image.
|
||||
* Request a screenshot and output it to the aDstImage
|
||||
* @param aDstImage - Screenshot destination image
|
||||
*/
|
||||
void GetScreenshot( wxImage& aDstImage );
|
||||
void GetScreenshot( wxImage &aDstImage );
|
||||
|
||||
/**
|
||||
* Select a specific 3D view or operation.
|
||||
*
|
||||
* @param aRequestedView the view to move to.
|
||||
* @return true if the view request was handled, false if no command found for this view.
|
||||
* @brief SetView3D - Helper function to call view commands
|
||||
* @param aKeycode: ascii key commands
|
||||
* @return true if the key code was handled,
|
||||
* false if no command found for this code.
|
||||
*/
|
||||
bool SetView3D( VIEW3D_TYPE aRequestedView );
|
||||
bool SetView3D( int aKeycode );
|
||||
|
||||
/**
|
||||
* Enable or disable camera animation when switching to a pre-defined view.
|
||||
*/
|
||||
void SetAnimationEnabled( bool aEnable ) { m_animation_enabled = aEnable; }
|
||||
bool GetAnimationEnabled() const { return m_animation_enabled; }
|
||||
|
||||
/**
|
||||
* Set the camera animation moving speed multiplier option.
|
||||
*
|
||||
* @param aMultiplier one of the possible integer options: [1,2,3,4,5].
|
||||
*/
|
||||
void SetMovingSpeedMultiplier( int aMultiplier ) { m_moving_speed_multiplier = aMultiplier; }
|
||||
int GetMovingSpeedMultiplier() const { return m_moving_speed_multiplier; }
|
||||
|
||||
int GetProjectionMode() const { return (int) m_camera.GetProjection(); };
|
||||
void SetProjectionMode( int aMode ) { m_camera.SetProjection( (PROJECTION_TYPE) aMode ); }
|
||||
|
||||
/**
|
||||
* Notify that the render engine was changed.
|
||||
* @brief RenderEngineChanged - Notify that the render engine was changed
|
||||
*/
|
||||
void RenderEngineChanged();
|
||||
|
||||
/**
|
||||
* Update the status bar with the position information.
|
||||
* @brief DisplayStatus - Update the status bar with the position information
|
||||
*/
|
||||
void DisplayStatus();
|
||||
|
||||
/**
|
||||
* Schedule a refresh update of the canvas.
|
||||
*
|
||||
* @param aRedrawImmediately true will request a redraw, false will schedule a redraw
|
||||
* after a short timeout.
|
||||
* @brief Request_refresh - Schedule a refresh update of the canvas
|
||||
* @param aRedrawImmediately - true will request a redraw, false will
|
||||
* schedule a redraw, after a short timeout.
|
||||
*/
|
||||
void Request_refresh( bool aRedrawImmediately = true );
|
||||
|
||||
/**
|
||||
* Used to forward events to the canvas from popups, etc.
|
||||
*/
|
||||
void OnEvent( wxEvent& aEvent );
|
||||
void OnKeyEvent( wxKeyEvent& event );
|
||||
|
||||
bool SupportsRayTracing() const { return m_opengl_supports_raytracing; }
|
||||
|
||||
bool IsOpenGLInitialized() const { return m_is_opengl_initialized; }
|
||||
|
||||
/**
|
||||
* Get information used to display 3D board.
|
||||
* Return a structure containing currently used hotkey mapping.
|
||||
*/
|
||||
const BOARD_ADAPTER& GetBoardAdapter() const { return m_boardAdapter; }
|
||||
EDA_HOTKEY_CONFIG* GetHotkeyConfig() const;
|
||||
|
||||
/**
|
||||
* Get a value indicating whether to render the pivot.
|
||||
private:
|
||||
|
||||
/** Called by a wxPaintEvent event
|
||||
*/
|
||||
bool GetRenderPivot() { return m_render_pivot; }
|
||||
|
||||
/**
|
||||
* Set aValue indicating whether to render the pivot.
|
||||
*
|
||||
* @param aValue true will cause the pivot to be rendered on the next redraw.
|
||||
*/
|
||||
void SetRenderPivot( bool aValue ) { m_render_pivot = aValue; }
|
||||
|
||||
/**
|
||||
* Get a value indicating whether to render the 3dmouse pivot.
|
||||
*/
|
||||
bool GetRender3dmousePivot()
|
||||
{
|
||||
return m_render3dmousePivot;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set aValue indicating whether to render the 3dmouse pivot.
|
||||
*
|
||||
* @param aValue true will cause the pivot to be rendered on the next redraw.
|
||||
*/
|
||||
void SetRender3dmousePivot( bool aValue )
|
||||
{
|
||||
m_render3dmousePivot = aValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the position of the the 3dmouse pivot.
|
||||
*
|
||||
* @param aPos is the position of the 3dmouse rotation pivot
|
||||
*/
|
||||
void Set3dmousePivotPos( const SFVEC3F& aPos )
|
||||
{
|
||||
m_3dmousePivotPos = aPos;
|
||||
}
|
||||
void OnPaint( wxPaintEvent& aEvent );
|
||||
|
||||
/**
|
||||
* The actual function to repaint the canvas.
|
||||
*
|
||||
* It is usually called by OnPaint() but because it does not use a wxPaintDC it can be
|
||||
* called outside a wxPaintEvent
|
||||
* It is usually called by OnPaint() but because it does not use a wxPaintDC
|
||||
* it can be called outside a wxPaintEvent
|
||||
*/
|
||||
void DoRePaint();
|
||||
|
||||
void OnCloseWindow( wxCloseEvent& event );
|
||||
|
||||
private:
|
||||
// The wxPaintEvent event. mainly calls DoRePaint()
|
||||
void OnPaint( wxPaintEvent& aEvent );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent& event );
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
void OnRefreshRequest( wxEvent& aEvent );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent& event );
|
||||
void OnMouseWheel( wxMouseEvent &event );
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent &event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent &event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
||||
void OnPopUpMenu( wxCommandEvent &event );
|
||||
|
||||
void OnCharHook( wxKeyEvent& event );
|
||||
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
void OnMouseMove( wxMouseEvent& event );
|
||||
void OnLeftDown( wxMouseEvent& event );
|
||||
void OnLeftUp( wxMouseEvent& event );
|
||||
void OnMiddleUp( wxMouseEvent& event );
|
||||
void OnMiddleDown( wxMouseEvent& event );
|
||||
void OnTimerTimeout_Editing( wxTimerEvent& event );
|
||||
void OnResize( wxSizeEvent& event );
|
||||
void OnTimerTimeout_Redraw( wxTimerEvent& event );
|
||||
|
||||
void OnZoomGesture( wxZoomGestureEvent& event );
|
||||
void OnPanGesture( wxPanGestureEvent& event );
|
||||
void OnRotateGesture( wxRotateGestureEvent& event );
|
||||
/**
|
||||
* @brief OnCloseWindow - called when the frame is closed
|
||||
* @param event
|
||||
*/
|
||||
void OnCloseWindow( wxCloseEvent &event );
|
||||
|
||||
void OnResize( wxSizeEvent &event );
|
||||
|
||||
void OnTimerTimeout_Redraw( wxTimerEvent& event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
*Stop the editing time so it will not timeout.
|
||||
* @brief stop_editingTimeOut_Timer - stop the editing time, so it will not timeout
|
||||
*/
|
||||
void stop_editingTimeOut_Timer();
|
||||
|
||||
|
||||
/**
|
||||
* Reset the editing timer.
|
||||
* @brief restart_editingTimeOut_Timer - reset the editing timer
|
||||
*/
|
||||
void restart_editingTimeOut_Timer();
|
||||
|
||||
/**
|
||||
* Start a camera movement.
|
||||
*
|
||||
* @param aMovingSpeed the time speed.
|
||||
* @param aRenderPivot if it should display pivot cursor while move.
|
||||
*/
|
||||
void request_start_moving_camera( float aMovingSpeed = 2.0f, bool aRenderPivot = true );
|
||||
|
||||
/**
|
||||
* This function hits a ray to the board and start a movement.
|
||||
* @brief request_start_moving_camera - start a camera movement
|
||||
* @param aMovingSpeed: the time speed
|
||||
* @param aRenderPivot: if it should display pivot cursor while move
|
||||
*/
|
||||
void request_start_moving_camera( float aMovingSpeed = 2.0f,
|
||||
bool aRenderPivot = true );
|
||||
|
||||
|
||||
/**
|
||||
* @brief move_pivot_based_on_cur_mouse_position -
|
||||
* This function hits a ray to the board and start a moviment
|
||||
*/
|
||||
void move_pivot_based_on_cur_mouse_position();
|
||||
|
||||
|
||||
/**
|
||||
* Render the pivot cursor.
|
||||
*
|
||||
* @param t time between 0.0 and 1.0.
|
||||
* @param aScale scale to apply on the cursor.
|
||||
* @brief render_pivot - render the pivot cursor
|
||||
* @param t: time between 0.0 and 1.0
|
||||
* @param aScale: scale to apply on the cursor
|
||||
*/
|
||||
void render_pivot( float t, float aScale );
|
||||
|
||||
/**
|
||||
* Render the 3dmouse pivot cursor.
|
||||
*
|
||||
* @param aScale scale to apply on the cursor.
|
||||
*/
|
||||
void render3dmousePivot( float aScale );
|
||||
|
||||
/**
|
||||
* @return true if OpenGL initialization succeeded.
|
||||
* @brief initializeOpenGL
|
||||
* @return if OpenGL initialization succeed
|
||||
*/
|
||||
bool initializeOpenGL();
|
||||
|
||||
/**
|
||||
* Free created targets and openGL context.
|
||||
* @brief releaseOpenGL - free created targets and openGL context
|
||||
*/
|
||||
void releaseOpenGL();
|
||||
|
||||
RAY getRayAtCurrentMousePosition();
|
||||
private:
|
||||
|
||||
private:
|
||||
TOOL_DISPATCHER* m_eventDispatcher;
|
||||
wxStatusBar* m_parentStatusBar; // Parent statusbar to report progress
|
||||
WX_INFOBAR* m_parentInfoBar;
|
||||
/// current OpenGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
wxGLContext* m_glRC; // Current OpenGL context
|
||||
bool m_is_opengl_initialized;
|
||||
bool m_is_opengl_version_supported;
|
||||
/// Parent statusbar to report progress
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
|
||||
wxTimer m_editing_timeout_timer; // Expires after some time signaling that
|
||||
// the mouse / keyboard movements are over
|
||||
wxTimer m_redraw_trigger_timer; // Used to schedule a redraw event
|
||||
std::atomic_flag m_is_currently_painting; // Avoid drawing twice at the same time
|
||||
/// Time timeout will expires after some time sinalizing that the mouse /
|
||||
/// keyboard movements are over.
|
||||
wxTimer m_editing_timeout_timer;
|
||||
|
||||
bool m_render_pivot; // Render the pivot while camera moving
|
||||
float m_camera_moving_speed; // 1.0f will be 1:1
|
||||
int64_t m_strtime_camera_movement; // Ticktime of camera movement start
|
||||
bool m_animation_enabled; // Camera animation enabled
|
||||
int m_moving_speed_multiplier; // Camera animation speed multiplier option
|
||||
/// This timer will be used to schedule a redraw event
|
||||
wxTimer m_redraw_trigger_timer;
|
||||
|
||||
BOARD_ADAPTER& m_boardAdapter; // Pre-computed 3D info and settings
|
||||
RENDER_3D_BASE* m_3d_render;
|
||||
RENDER_3D_RAYTRACE_GL* m_3d_render_raytracing;
|
||||
RENDER_3D_OPENGL* m_3d_render_opengl;
|
||||
/// true if mouse activity is on progress
|
||||
bool m_mouse_is_moving;
|
||||
|
||||
bool m_opengl_supports_raytracing;
|
||||
bool m_render_raytracing_was_requested;
|
||||
/// true if there was some type of activity, it will be used to render in
|
||||
/// preview mode
|
||||
bool m_mouse_was_moved;
|
||||
|
||||
ACCELERATOR_3D* m_accelerator3DShapes; // used for mouse over searching
|
||||
/// true if camera animation is ongoing
|
||||
bool m_camera_is_moving;
|
||||
|
||||
BOARD_ITEM* m_currentRollOverItem;
|
||||
/// activated the render of pivot while camera moving
|
||||
bool m_render_pivot;
|
||||
|
||||
bool m_render3dmousePivot = false; // Render the 3dmouse pivot
|
||||
SFVEC3F m_3dmousePivotPos; // The position of the 3dmouse pivot
|
||||
/// 1.0f will be 1:1
|
||||
float m_camera_moving_speed;
|
||||
|
||||
/// Used to track gesture events.
|
||||
double m_gestureLastZoomFactor = 1.0;
|
||||
double m_gestureLastAngle = 0.0;
|
||||
/// Stores the ticktime when the camera star its movement
|
||||
unsigned m_strtime_camera_movement;
|
||||
|
||||
/// Stores all pre-computed 3D information and visualization settings to render the board
|
||||
CINFO3D_VISU &m_settings;
|
||||
|
||||
/// The current render in used for this canvas
|
||||
C3D_RENDER_BASE *m_3d_render;
|
||||
|
||||
/// Raytracing render class
|
||||
C3D_RENDER_RAYTRACING *m_3d_render_raytracing;
|
||||
|
||||
/// OpenGL legacy render class
|
||||
C3D_RENDER_OGL_LEGACY *m_3d_render_ogl_legacy;
|
||||
|
||||
/// Flag to store if opengl was initialized already
|
||||
bool m_is_opengl_initialized;
|
||||
|
||||
/// Step factor to used with cursor on relation to the current zoom
|
||||
static const float m_delta_move_step_factor;
|
||||
|
||||
/// Flags that the user requested the current view to be render with raytracing
|
||||
bool m_render_raytracing_was_requested;
|
||||
|
||||
bool m_opengl_supports_raytracing;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
@@ -341,7 +297,7 @@ private:
|
||||
* "KI_TRACE_EDA_3D_CANVAS". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -35,26 +35,26 @@
|
||||
static void pivot_render_triangles( float t )
|
||||
{
|
||||
wxASSERT( t >= 0.0f );
|
||||
|
||||
|
||||
SFVEC3F vertexPointer[12];
|
||||
|
||||
const float u = 1.0f / 6.0f;
|
||||
|
||||
vertexPointer[0] = SFVEC3F( ( -3.0f + t ) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[1] = SFVEC3F( ( -3.0f + t ) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[2] = SFVEC3F( ( -1.0f + t ) * u, 0.0f * u, 0.0f );
|
||||
vertexPointer[0] = SFVEC3F( (-3.0f + t) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[1] = SFVEC3F( (-3.0f + t) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[2] = SFVEC3F( (-1.0f + t) * u, 0.0f * u, 0.0f );
|
||||
|
||||
vertexPointer[3] = SFVEC3F( -2.0f * u, ( -3.0f + t ) * u, 0.0f );
|
||||
vertexPointer[4] = SFVEC3F( 2.0f * u, ( -3.0f + t ) * u, 0.0f );
|
||||
vertexPointer[5] = SFVEC3F( 0.0f * u, ( -1.0f + t ) * u, 0.0f );
|
||||
vertexPointer[3] = SFVEC3F( -2.0f * u, (-3.0f + t) * u, 0.0f );
|
||||
vertexPointer[4] = SFVEC3F( 2.0f * u, (-3.0f + t) * u, 0.0f );
|
||||
vertexPointer[5] = SFVEC3F( 0.0f * u, (-1.0f + t) * u, 0.0f );
|
||||
|
||||
vertexPointer[6] = SFVEC3F( ( 3.0f - t ) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[7] = SFVEC3F( ( 3.0f - t ) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[8] = SFVEC3F( ( 1.0f - t ) * u, 0.0f * u, 0.0f );
|
||||
vertexPointer[6] = SFVEC3F( (3.0f - t) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[7] = SFVEC3F( (3.0f - t) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[8] = SFVEC3F( (1.0f - t) * u, 0.0f * u, 0.0f );
|
||||
|
||||
vertexPointer[9] = SFVEC3F( 2.0f * u, ( 3.0f - t ) * u, 0.0f );
|
||||
vertexPointer[10] = SFVEC3F( -2.0f * u, ( 3.0f - t ) * u, 0.0f );
|
||||
vertexPointer[11] = SFVEC3F( 0.0f * u, ( 1.0f - t ) * u, 0.0f );
|
||||
vertexPointer[9] = SFVEC3F( 2.0f * u, (3.0f - t) * u, 0.0f );
|
||||
vertexPointer[10] = SFVEC3F( -2.0f * u, (3.0f - t) * u, 0.0f );
|
||||
vertexPointer[11] = SFVEC3F( 0.0f * u, (1.0f - t) * u, 0.0f );
|
||||
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
@@ -73,7 +73,7 @@ static void pivot_render_triangles( float t )
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::render_pivot( float t, float aScale )
|
||||
void EDA_3D_CANVAS::render_pivot( float t , float aScale )
|
||||
{
|
||||
wxASSERT( aScale >= 0.0f );
|
||||
wxASSERT( t >= 0.0f );
|
||||
@@ -81,27 +81,29 @@ void EDA_3D_CANVAS::render_pivot( float t, float aScale )
|
||||
if( t > 1.0f )
|
||||
t = 1.0f;
|
||||
|
||||
const SFVEC3F &lookAtPos = m_camera.GetLookAtPos_T1();
|
||||
const SFVEC3F &lookAtPos = m_settings.CameraGet().GetLookAtPos_T1();
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_CULL_FACE );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetProjectionMatrix() ) );
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetViewMatrix() ) );
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( 0.0f, 1.0f, 0.0f, 0.75f - t * 0.75f );
|
||||
|
||||
// Translate to the look at position
|
||||
glTranslatef( lookAtPos.x, lookAtPos.y, lookAtPos.z );
|
||||
|
||||
|
||||
glScalef( aScale, aScale, aScale );
|
||||
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
|
||||
t = t * 0.80f;
|
||||
@@ -118,44 +120,3 @@ void EDA_3D_CANVAS::render_pivot( float t, float aScale )
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::render3dmousePivot( float aScale )
|
||||
{
|
||||
wxASSERT( aScale >= 0.0f );
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_CULL_FACE );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( 0.0f, 0.667f, 0.902f, 0.75f );
|
||||
|
||||
// Translate to the look at position
|
||||
glTranslatef( m_3dmousePivotPos.x, m_3dmousePivotPos.y, m_3dmousePivotPos.z );
|
||||
|
||||
glPointSize( 16.0f );
|
||||
glEnable( GL_POINT_SMOOTH );
|
||||
glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glScalef( aScale, aScale, aScale );
|
||||
|
||||
// Draw a point at the look at position.
|
||||
glBegin( GL_POINTS );
|
||||
glVertex3f( 0, 0, 0 );
|
||||
glEnd();
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glDisable( GL_POINT_SMOOTH );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file status_text_reporter.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef STATUS_TEXT_REPORTER_H_
|
||||
#define STATUS_TEXT_REPORTER_H_
|
||||
|
||||
#include <reporter.h>
|
||||
|
||||
/**
|
||||
* Class STATUS_TEXT_REPORTER
|
||||
* is a wrapper for reporting to a wxString in a wxFrame status text.
|
||||
*/
|
||||
class STATUS_TEXT_REPORTER : public REPORTER
|
||||
{
|
||||
private:
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
int m_position;
|
||||
bool m_hasMessage;
|
||||
|
||||
public:
|
||||
STATUS_TEXT_REPORTER( wxStatusBar* aParentStatusBar, int aPosition = 0 ) :
|
||||
REPORTER(),
|
||||
m_parentStatusBar( aParentStatusBar ), m_position( aPosition )
|
||||
{
|
||||
m_hasMessage = false;
|
||||
}
|
||||
|
||||
REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_UNDEFINED ) override
|
||||
{
|
||||
if( !aText.IsEmpty() )
|
||||
m_hasMessage = true;
|
||||
|
||||
if( m_parentStatusBar )
|
||||
m_parentStatusBar->SetStatusText( aText, m_position );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HasMessage() const override { return m_hasMessage; }
|
||||
};
|
||||
|
||||
|
||||
#endif // STATUS_TEXT_REPORTER_H_
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_enums.h
|
||||
* @brief declared enumerations and flags
|
||||
*/
|
||||
|
||||
#ifndef _3D_ENUMS_H_
|
||||
#define _3D_ENUMS_H_
|
||||
|
||||
/// Flags used in rendering options
|
||||
enum DISPLAY3D_FLG {
|
||||
FL_AXIS=0, FL_ZONE,
|
||||
FL_ADHESIVE, FL_SILKSCREEN, FL_SOLDERMASK, FL_SOLDERPASTE,
|
||||
FL_COMMENTS, FL_ECO,
|
||||
|
||||
FL_MODULE_ATTRIBUTES_NORMAL,
|
||||
FL_MODULE_ATTRIBUTES_NORMAL_INSERT,
|
||||
FL_MODULE_ATTRIBUTES_VIRTUAL,
|
||||
|
||||
FL_SHOW_BOARD_BODY,
|
||||
FL_MOUSEWHEEL_PANNING,
|
||||
FL_USE_REALISTIC_MODE,
|
||||
|
||||
// OpenGL options
|
||||
FL_RENDER_OPENGL_SHOW_MODEL_BBOX,
|
||||
FL_RENDER_OPENGL_COPPER_THICKNESS,
|
||||
|
||||
// Raytracing options
|
||||
FL_RENDER_RAYTRACING_SHADOWS,
|
||||
FL_RENDER_RAYTRACING_BACKFLOOR,
|
||||
FL_RENDER_RAYTRACING_REFRACTIONS,
|
||||
FL_RENDER_RAYTRACING_REFLECTIONS,
|
||||
FL_RENDER_RAYTRACING_POST_PROCESSING,
|
||||
FL_RENDER_RAYTRACING_ANTI_ALIASING,
|
||||
FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES,
|
||||
FL_LAST
|
||||
};
|
||||
|
||||
|
||||
/// Camera types
|
||||
enum CAMERA_TYPE
|
||||
{
|
||||
CAMERA_TRACKBALL
|
||||
};
|
||||
|
||||
|
||||
/// Grid types
|
||||
enum GRID3D_TYPE
|
||||
{
|
||||
GRID3D_NONE,
|
||||
GRID3D_1MM,
|
||||
GRID3D_2P5MM,
|
||||
GRID3D_5MM,
|
||||
GRID3D_10MM
|
||||
};
|
||||
|
||||
|
||||
/// Render engine mode
|
||||
enum RENDER_ENGINE
|
||||
{
|
||||
RENDER_ENGINE_OPENGL_LEGACY,
|
||||
RENDER_ENGINE_RAYTRACING,
|
||||
};
|
||||
|
||||
|
||||
/// Render 3d model shape materials mode
|
||||
enum MATERIAL_MODE
|
||||
{
|
||||
MATERIAL_MODE_NORMAL, ///< Use all material properties from model file
|
||||
MATERIAL_MODE_DIFFUSE_ONLY, ///< Use only diffuse material properties
|
||||
MATERIAL_MODE_CAD_MODE ///< Use a gray shading based on diffuse material
|
||||
};
|
||||
|
||||
#endif // _3D_ENUMS_H_
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -30,9 +30,9 @@
|
||||
#ifndef _3D_FASTMATH_H
|
||||
#define _3D_FASTMATH_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
// Define this flag to use fast math optimizations
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
||||
+39
-30
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -33,43 +33,44 @@
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
/**
|
||||
* https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
*
|
||||
* @brief SphericalToCartesian
|
||||
* @param aInclination θ ∈ [0, π]
|
||||
* @param aAzimuth φ ∈ [0, 2π]
|
||||
* @return Cartesian coordinates
|
||||
* @return Cartesian cordinates
|
||||
*/
|
||||
inline SFVEC3F SphericalToCartesian( float aInclination, float aAzimuth )
|
||||
{
|
||||
float sinInc = glm::sin( aInclination );
|
||||
|
||||
return SFVEC3F( sinInc * glm::cos( aAzimuth ), sinInc * glm::sin( aAzimuth ),
|
||||
return SFVEC3F( sinInc * glm::cos( aAzimuth ),
|
||||
sinInc * glm::sin( aAzimuth ),
|
||||
glm::cos( aInclination ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @todo This is not correct because it is not a gaussian random.
|
||||
*/
|
||||
inline SFVEC3F UniformRandomHemisphereDirection()
|
||||
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||
// !TODO: this is not correct because it is not a gaussian random
|
||||
inline SFVEC3F UniformRandomHemisphereDirection( )
|
||||
{
|
||||
// It was experienced that this function is slow! do not use it :/
|
||||
// SFVEC3F b( (rand()/(float)RAND_MAX) - 0.5f,
|
||||
// (rand()/(float)RAND_MAX) - 0.5f,
|
||||
// (rand()/(float)RAND_MAX) - 0.5f );
|
||||
|
||||
SFVEC3F b( Fast_RandFloat() * 0.5f, Fast_RandFloat() * 0.5f, Fast_RandFloat() * 0.5f );
|
||||
SFVEC3F b( Fast_RandFloat() * 0.5f,
|
||||
Fast_RandFloat() * 0.5f,
|
||||
Fast_RandFloat() * 0.5f );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||
inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F& n )
|
||||
inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F &n )
|
||||
{
|
||||
const float Xi1 = (float) rand() / (float) RAND_MAX;
|
||||
const float Xi2 = (float) rand() / (float) RAND_MAX;
|
||||
const float Xi1 = (float)rand() / (float)RAND_MAX;
|
||||
const float Xi2 = (float)rand() / (float)RAND_MAX;
|
||||
|
||||
const float theta = acos( sqrt( 1.0f - Xi1 ) );
|
||||
const float phi = 2.0f * glm::pi<float>() * Xi2;
|
||||
@@ -98,19 +99,21 @@ inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F& n )
|
||||
|
||||
|
||||
/**
|
||||
* @brief Refract
|
||||
* Based on:
|
||||
* https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h
|
||||
* See also:
|
||||
* http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_3_Refractions_and_Beers_Law.shtml
|
||||
*
|
||||
* @param aInVector incoming vector.
|
||||
* @param aNormal normal in the intersection point.
|
||||
* @param aRin_over_Rout incoming refraction index / out refraction index.
|
||||
* @param aOutVector the refracted vector.
|
||||
* @param aInVector incoming vector
|
||||
* @param aNormal normal in the intersection point
|
||||
* @param aRin_over_Rout incoming refraction index / out refraction index
|
||||
* @param aOutVector the refracted vector
|
||||
* @return true
|
||||
*/
|
||||
inline bool Refract( const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRin_over_Rout,
|
||||
SFVEC3F& aOutVector )
|
||||
inline bool Refract( const SFVEC3F &aInVector,
|
||||
const SFVEC3F &aNormal,
|
||||
float aRin_over_Rout,
|
||||
SFVEC3F &aOutVector )
|
||||
{
|
||||
float cosThetaI = -glm::dot( aNormal, aInVector );
|
||||
float sin2ThetaI = glm::max( 0.0f, 1.0f - cosThetaI * cosThetaI );
|
||||
@@ -130,7 +133,11 @@ inline bool Refract( const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRi
|
||||
}
|
||||
|
||||
|
||||
inline float mapf( float x, float in_min, float in_max, float out_min, float out_max )
|
||||
inline float mapf( float x,
|
||||
float in_min,
|
||||
float in_max,
|
||||
float out_min,
|
||||
float out_max)
|
||||
{
|
||||
x = glm::clamp( x, in_min, in_max );
|
||||
|
||||
@@ -147,15 +154,17 @@ inline float RGBtoGray( const SFVEC3F &aColor )
|
||||
inline SFVEC3F MaterialDiffuseToColorCAD( const SFVEC3F &aDiffuseColor )
|
||||
{
|
||||
// convert to a discret scale of grays
|
||||
const float luminance = glm::min(
|
||||
( ( (float) ( (unsigned int) ( 4.0f * RGBtoGray( aDiffuseColor ) ) ) + 0.5f ) / 4.0f )
|
||||
* 1.0f,
|
||||
1.0f );
|
||||
const float luminance = glm::min( (((float)((unsigned int) ( 4.0f *
|
||||
RGBtoGray( aDiffuseColor ) ) ) + 0.5f) /
|
||||
4.0f) * 1.0f,
|
||||
1.0f );
|
||||
|
||||
const float maxValue = glm::max( glm::max( glm::max( aDiffuseColor.r, aDiffuseColor.g ),
|
||||
aDiffuseColor.b ), FLT_EPSILON );
|
||||
const float maxValue = glm::max( glm::max( glm::max( aDiffuseColor.r,
|
||||
aDiffuseColor.g),
|
||||
aDiffuseColor.b ),
|
||||
FLT_EPSILON );
|
||||
|
||||
return ( aDiffuseColor / SFVEC3F( maxValue ) ) * 0.125f + luminance * 0.875f;
|
||||
return (aDiffuseColor / SFVEC3F(maxValue) ) * 0.125f + luminance* 0.875f;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +179,7 @@ inline float QuadricEasingInOut( float t )
|
||||
{
|
||||
t = t - 1.0f;
|
||||
|
||||
return -2.0f * ( t * t ) + 1.0f;
|
||||
return -2.0f * (t * t) + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_model_viewer.cpp
|
||||
* @brief Implements a model viewer canvas. The propose of model viewer is to
|
||||
* render 3d models that come in the original data from the files without any
|
||||
* transformations.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h"
|
||||
#include "c3d_model_viewer.h"
|
||||
#include "../3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include "common_ogl/ogl_utils.h"
|
||||
#include <wx/dcclient.h>
|
||||
#include <base_units.h>
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
/**
|
||||
* Scale convertion from 3d model units to pcb units
|
||||
*/
|
||||
#define UNITS3D_TO_UNITSPCB (IU_PER_MM)
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
const wxChar * C3D_MODEL_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_MODEL_VIEWER" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( C3D_MODEL_VIEWER, wxGLCanvas )
|
||||
EVT_PAINT( C3D_MODEL_VIEWER::OnPaint )
|
||||
|
||||
// mouse events
|
||||
EVT_LEFT_DOWN( C3D_MODEL_VIEWER::OnLeftDown )
|
||||
EVT_LEFT_UP( C3D_MODEL_VIEWER::OnLeftUp )
|
||||
EVT_MIDDLE_UP( C3D_MODEL_VIEWER::OnMiddleUp )
|
||||
EVT_MIDDLE_DOWN(C3D_MODEL_VIEWER::OnMiddleDown)
|
||||
EVT_RIGHT_DOWN( C3D_MODEL_VIEWER::OnRightClick )
|
||||
EVT_MOUSEWHEEL( C3D_MODEL_VIEWER::OnMouseWheel )
|
||||
EVT_MOTION( C3D_MODEL_VIEWER::OnMouseMove )
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
EVT_MAGNIFY( C3D_MODEL_VIEWER::OnMagnify )
|
||||
#endif
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( C3D_MODEL_VIEWER::OnEraseBackground )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
// This defines the range that all coord will have to be rendered.
|
||||
// It will use this value to convert to a normalized value between
|
||||
// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::C3D_MODEL_VIEWER(wxWindow *aParent,
|
||||
const int *aAttribList , S3D_CACHE *aCacheManager) :
|
||||
|
||||
HIDPI_GL_CANVAS( aParent,
|
||||
wxID_ANY,
|
||||
aAttribList,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D * 2.0f ),
|
||||
m_cacheManager(aCacheManager)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::C3D_MODEL_VIEWER" ) );
|
||||
|
||||
m_ogl_initialized = false;
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = NULL;
|
||||
m_3d_model = NULL;
|
||||
m_BiuTo3Dunits = 1.0;
|
||||
|
||||
m_glRC = NULL;
|
||||
}
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER" ) );
|
||||
|
||||
if( m_glRC )
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Set3DModel( const S3DMODEL &a3DModel )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a S3DMODEL" ) );
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != NULL );
|
||||
wxASSERT( a3DModel.m_Meshes != NULL );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
// Delete the old model
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
m_3d_model = NULL;
|
||||
|
||||
if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
|
||||
(a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
|
||||
{
|
||||
m_3d_model = &a3DModel;
|
||||
m_reload_is_needed = true;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Set3DModel(const wxString &aModelPathName)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a wxString" ) );
|
||||
|
||||
if( m_cacheManager )
|
||||
{
|
||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName );
|
||||
|
||||
if( model )
|
||||
Set3DModel( (const S3DMODEL &)*model );
|
||||
else
|
||||
Clear3DModel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Clear3DModel()
|
||||
{
|
||||
// Delete the old model
|
||||
m_reload_is_needed = false;
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
m_3d_model = NULL;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::ogl_initialize()
|
||||
{
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
//glDepthFunc( GL_LEQUAL );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glShadeModel( GL_SMOOTH );
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
glEnable( GL_NORMALIZE );
|
||||
|
||||
// Setup light
|
||||
// https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
const GLfloat ambient[] = { 0.01f, 0.01f, 0.01f, 1.0f };
|
||||
const GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
const GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
// defines a directional light that points along the negative z-axis
|
||||
const GLfloat position[] = { 0.0f, 0.0f, 2.0f * RANGE_SCALE_3D, 0.0f };
|
||||
|
||||
const GLfloat lmodel_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, position );
|
||||
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::ogl_set_arrow_material()
|
||||
{
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
||||
{
|
||||
wxPaintDC( this );
|
||||
|
||||
event.Skip( false );
|
||||
|
||||
// SwapBuffer requires the window to be shown before calling
|
||||
if( !IsShownOnScreen() )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint !IsShown" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// "Makes the OpenGL state that is represented by the OpenGL rendering
|
||||
// context context current, i.e. it will be used by all subsequent OpenGL calls.
|
||||
// This function may only be called when the window is shown on screen"
|
||||
if( m_glRC == NULL )
|
||||
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
// This is done here rather than in a wxSizeEvent handler because our
|
||||
// OpenGL rendering context (and thus viewport setting) is used with
|
||||
// multiple canvases: If we updated the viewport in the wxSizeEvent
|
||||
// handler, changing the size of one canvas causes a viewport setting that
|
||||
// is wrong when next another canvas is repainted.
|
||||
wxSize clientSize = GetClientSize();
|
||||
|
||||
if( !m_ogl_initialized )
|
||||
{
|
||||
m_ogl_initialized = true;
|
||||
ogl_initialize();
|
||||
}
|
||||
|
||||
if( m_reload_is_needed )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) );
|
||||
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = new C_OGL_3DMODEL( *m_3d_model, MATERIAL_MODE_NORMAL );
|
||||
|
||||
// It convert a model as it was a board, so get the max size dimension of the board
|
||||
// and compute the conversion scale
|
||||
m_BiuTo3Dunits = (double)RANGE_SCALE_3D /
|
||||
( (double)m_ogl_3dmodel->GetBBox().GetMaxDimension() *
|
||||
UNITS3D_TO_UNITSPCB );
|
||||
}
|
||||
|
||||
glViewport( 0, 0, clientSize.x, clientSize.y );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( clientSize );
|
||||
|
||||
// clear color and depth buffers
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
|
||||
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||
glClearDepth( 1.0f );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_LIGHT0 );
|
||||
|
||||
// Render Model
|
||||
if( m_ogl_3dmodel )
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
double modelunit_to_3d_units_factor = m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glScaled( modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor );
|
||||
|
||||
// Center model in the render viewport
|
||||
const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
|
||||
|
||||
glTranslatef( -model_center.x, -model_center.y, -model_center.z );
|
||||
|
||||
m_ogl_3dmodel->Draw_opaque();
|
||||
m_ogl_3dmodel->Draw_transparent();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
// YxY squared view port
|
||||
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 );
|
||||
glClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
gluPerspective( 45.0f, 1.0f, 0.01f, RANGE_SCALE_3D * 2.0f );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
const glm::mat4 TranslationMatrix = glm::translate( glm::mat4(1.0f),
|
||||
SFVEC3F( 0.0f, 0.0f, -RANGE_SCALE_3D ) );
|
||||
|
||||
const glm::mat4 ViewMatrix = TranslationMatrix * m_trackBallCamera.GetRotationMatrix();
|
||||
|
||||
glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
|
||||
|
||||
ogl_set_arrow_material();
|
||||
|
||||
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( RANGE_SCALE_3D / 2.65f, 0.0f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( 0.0f, RANGE_SCALE_3D / 2.65f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 2.65f ),
|
||||
0.275f );
|
||||
|
||||
// "Swaps the double-buffer of this window, making the back-buffer the
|
||||
// front-buffer and vice versa, so that the output of the previous OpenGL
|
||||
// commands is displayed on the window."
|
||||
SwapBuffers();
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnEraseBackground( wxEraseEvent &event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnEraseBackground" ) );
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMouseWheel( wxMouseEvent &event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnMouseWheel" ) );
|
||||
|
||||
if( event.ShiftDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() < 0 )
|
||||
//SetView3D( WXK_UP ); // move up
|
||||
//else
|
||||
//SetView3D( WXK_DOWN ); // move down
|
||||
}
|
||||
else if( event.ControlDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() > 0 )
|
||||
//SetView3D( WXK_RIGHT ); // move right
|
||||
//else
|
||||
//SetView3D( WXK_LEFT ); // move left
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackBallCamera.Zoom( event.GetWheelRotation() > 0 ? 1.1f : 1/1.1f );
|
||||
|
||||
//DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void C3D_MODEL_VIEWER::OnMagnify( wxMouseEvent& event )
|
||||
{
|
||||
/*
|
||||
double magnification = ( event.GetMagnification() + 1.0f );
|
||||
GetPrm3DVisu().m_Zoom /= magnification;
|
||||
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||
GetPrm3DVisu().m_Zoom = 0.01;
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMouseMove( wxMouseEvent &event )
|
||||
{
|
||||
m_trackBallCamera.SetCurWindowSize( GetClientSize() );
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() ) // Drag
|
||||
m_trackBallCamera.Drag( event.GetPosition() );
|
||||
//else if( event.MiddleIsDown() ) // Pan
|
||||
// m_trackBallCamera.Pan( event.GetPosition() );
|
||||
|
||||
// orientation has changed, redraw mesh
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnLeftDown( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = true;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnLeftUp( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = false;
|
||||
//Refresh( false );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMiddleDown( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = true;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMiddleUp( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = false;
|
||||
//Refresh( false );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnRightClick( wxMouseEvent &event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_model_viewer.h
|
||||
* @brief Implements a model viewer canvas. The propose of model viewer is to
|
||||
* render 3d models that come in the original data from the files without any
|
||||
* transformations.
|
||||
*/
|
||||
|
||||
#ifndef _C3D_MODEL_VIEWER_H_
|
||||
#define _C3D_MODEL_VIEWER_H_
|
||||
|
||||
#include "3d_rendering/ctrack_ball.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class C_OGL_3DMODEL;
|
||||
|
||||
/**
|
||||
* Class C3D_MODEL_VIEWER
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class C3D_MODEL_VIEWER : public HIDPI_GL_CANVAS
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new 3D Canvas with a attribute list
|
||||
* @param aParent = the parent creator of this canvas
|
||||
* @param aAttribList = a list of openGL options created by
|
||||
* COGL_ATT_LIST::GetAttributesList
|
||||
*/
|
||||
C3D_MODEL_VIEWER( wxWindow *aParent,
|
||||
const int *aAttribList = 0,
|
||||
S3D_CACHE *aCacheManager = NULL );
|
||||
|
||||
~C3D_MODEL_VIEWER();
|
||||
|
||||
/**
|
||||
* @brief Set3DModel - Set this model to be displayed
|
||||
* @param a3DModel - 3d model data
|
||||
*/
|
||||
void Set3DModel( const S3DMODEL &a3DModel );
|
||||
|
||||
/**
|
||||
* @brief Set3DModel - Set this model to be displayed
|
||||
* @param aModelPathName - 3d model path name
|
||||
*/
|
||||
void Set3DModel( wxString const& aModelPathName );
|
||||
|
||||
/**
|
||||
* @brief Clear3DModel - Unloads the displayed 3d model
|
||||
*/
|
||||
void Clear3DModel();
|
||||
|
||||
private:
|
||||
void ogl_initialize();
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
private:
|
||||
|
||||
void OnPaint( wxPaintEvent &event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent &event );
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent &event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent &event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
|
||||
private:
|
||||
/// openGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
/// Camera used in this canvas
|
||||
CTRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// Original 3d model data
|
||||
const S3DMODEL *m_3d_model;
|
||||
|
||||
/// Class holder for 3d model to display on openGL
|
||||
C_OGL_3DMODEL *m_ogl_3dmodel;
|
||||
|
||||
/// Flag that we have a new model and it need to be reloaded when the paint is called
|
||||
bool m_reload_is_needed;
|
||||
|
||||
/// Flag if open gl was initialized
|
||||
bool m_ogl_initialized;
|
||||
|
||||
/// factor to convert the model or any other items to keep it in relation to
|
||||
/// the +/-RANGE_SCALE_3D
|
||||
/// (it is named same as the board render for better understanding proposes)
|
||||
double m_BiuTo3Dunits;
|
||||
|
||||
/// Optional cache manager
|
||||
S3D_CACHE* m_cacheManager;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
#endif // _C3D_MODEL_VIEWER_H_
|
||||
@@ -1,483 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Implements a model viewer canvas. The purpose of the model viewer is to render
|
||||
* 3d models that come in the original data from the files without any transformations.
|
||||
*/
|
||||
|
||||
#include <gal/opengl/kiglew.h> // Must be included first
|
||||
#include <iostream>
|
||||
#include "3d_rendering/opengl/3d_model.h"
|
||||
#include "eda_3d_model_viewer.h"
|
||||
#include "../3d_rendering/opengl/opengl_utils.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include <wx/dcclient.h>
|
||||
#include <base_units.h>
|
||||
#include <build_version.h>
|
||||
#include <gal/opengl/gl_context_mgr.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <pgm_base.h>
|
||||
#include <dpi_scaling_common.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
#include <macros.h>
|
||||
|
||||
/**
|
||||
* Scale conversion from 3d model units to pcb units
|
||||
*/
|
||||
#define UNITS3D_TO_UNITSPCB ( pcbIUScale.IU_PER_MM )
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* EDA_3D_MODEL_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_MODEL_VIEWER" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_3D_MODEL_VIEWER, wxGLCanvas )
|
||||
EVT_PAINT( EDA_3D_MODEL_VIEWER::OnPaint )
|
||||
|
||||
// mouse events
|
||||
EVT_LEFT_DOWN( EDA_3D_MODEL_VIEWER::OnLeftDown )
|
||||
EVT_LEFT_UP( EDA_3D_MODEL_VIEWER::OnLeftUp )
|
||||
EVT_MIDDLE_UP( EDA_3D_MODEL_VIEWER::OnMiddleUp )
|
||||
EVT_MIDDLE_DOWN( EDA_3D_MODEL_VIEWER::OnMiddleDown)
|
||||
EVT_RIGHT_DOWN( EDA_3D_MODEL_VIEWER::OnRightClick )
|
||||
EVT_MOUSEWHEEL( EDA_3D_MODEL_VIEWER::OnMouseWheel )
|
||||
EVT_MOTION( EDA_3D_MODEL_VIEWER::OnMouseMove )
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
EVT_MAGNIFY( EDA_3D_MODEL_VIEWER::OnMagnify )
|
||||
#endif
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( EDA_3D_MODEL_VIEWER::OnEraseBackground )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
// This defines the range that all coord will have to be rendered.
|
||||
// It will use this value to convert to a normalized value between
|
||||
// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
EDA_3D_MODEL_VIEWER::EDA_3D_MODEL_VIEWER( wxWindow* aParent, const wxGLAttributes& aGLAttribs,
|
||||
S3D_CACHE* aCacheManager ) :
|
||||
HIDPI_GL_CANVAS( EDA_DRAW_PANEL_GAL::GetVcSettings(), aParent, aGLAttribs, wxID_ANY,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D * 4.0f ),
|
||||
m_cacheManager( aCacheManager )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::EDA_3D_MODEL_VIEWER" ) );
|
||||
|
||||
m_ogl_initialized = false;
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
m_3d_model = nullptr;
|
||||
m_BiuTo3dUnits = 1.0;
|
||||
|
||||
m_glRC = nullptr;
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_MODEL_VIEWER::~EDA_3D_MODEL_VIEWER()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::~EDA_3D_MODEL_VIEWER" ) );
|
||||
GL_CONTEXT_MANAGER* gl_mgr = Pgm().GetGLContextManager();
|
||||
|
||||
if( m_glRC )
|
||||
{
|
||||
gl_mgr->LockCtx( m_glRC, this );
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
gl_mgr->UnlockCtx( m_glRC );
|
||||
gl_mgr->DestroyCtx( m_glRC );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::Set3DModel( const S3DMODEL& a3DModel )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::Set3DModel with a S3DMODEL" ) );
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != nullptr );
|
||||
wxASSERT( a3DModel.m_Meshes != nullptr );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
// Delete the old model
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
m_3d_model = nullptr;
|
||||
|
||||
if( ( a3DModel.m_Materials != nullptr ) && ( a3DModel.m_Meshes != nullptr )
|
||||
&& ( a3DModel.m_MaterialsSize > 0 ) && ( a3DModel.m_MeshesSize > 0 ) )
|
||||
{
|
||||
m_3d_model = &a3DModel;
|
||||
m_reload_is_needed = true;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::Set3DModel( const wxString& aModelPathName)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::Set3DModel with a wxString" ) );
|
||||
|
||||
if( m_cacheManager )
|
||||
{
|
||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString, nullptr );
|
||||
|
||||
if( model )
|
||||
Set3DModel( (const S3DMODEL &)*model );
|
||||
else
|
||||
Clear3DModel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::Clear3DModel()
|
||||
{
|
||||
// Delete the old model
|
||||
m_reload_is_needed = false;
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
m_3d_model = nullptr;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::ogl_initialize()
|
||||
{
|
||||
const GLenum err = glewInit();
|
||||
|
||||
if( GLEW_OK != err )
|
||||
{
|
||||
const wxString msgError = (const char*) glewGetErrorString( err );
|
||||
|
||||
wxLogMessage( msgError );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::ogl_initialize Using GLEW version %s" ),
|
||||
From_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
|
||||
}
|
||||
|
||||
SetOpenGLInfo( (const char*) glGetString( GL_VENDOR ), (const char*) glGetString( GL_RENDERER ),
|
||||
(const char*) glGetString( GL_VERSION ) );
|
||||
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glShadeModel( GL_SMOOTH );
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
glEnable( GL_NORMALIZE );
|
||||
|
||||
// Setup light
|
||||
// https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
|
||||
const GLfloat ambient[] = { 0.01f, 0.01f, 0.01f, 1.0f };
|
||||
const GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
const GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
// defines a directional light that points along the negative z-axis
|
||||
const GLfloat position[] = { 0.0f, 0.0f, 2.0f * RANGE_SCALE_3D, 0.0f };
|
||||
|
||||
const GLfloat lmodel_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, position );
|
||||
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::ogl_set_arrow_material()
|
||||
{
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event )
|
||||
{
|
||||
event.Skip( false );
|
||||
|
||||
// SwapBuffer requires the window to be shown before calling
|
||||
if( !IsShownOnScreen() )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint !IsShown" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// "Makes the OpenGL state that is represented by the OpenGL rendering
|
||||
// context context current, i.e. it will be used by all subsequent OpenGL calls.
|
||||
// This function may only be called when the window is shown on screen"
|
||||
if( m_glRC == nullptr )
|
||||
m_glRC = Pgm().GetGLContextManager()->CreateCtx( this );
|
||||
|
||||
// CreateCtx could and does fail per sentry crash events, lets be graceful
|
||||
if( m_glRC == nullptr )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint creating gl context failed" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Pgm().GetGLContextManager()->LockCtx( m_glRC, this );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
// This is done here rather than in a wxSizeEvent handler because our
|
||||
// OpenGL rendering context (and thus viewport setting) is used with
|
||||
// multiple canvases: If we updated the viewport in the wxSizeEvent
|
||||
// handler, changing the size of one canvas causes a viewport setting that
|
||||
// is wrong when next another canvas is repainted.
|
||||
wxSize clientSize = GetNativePixelSize();
|
||||
|
||||
if( !m_ogl_initialized )
|
||||
{
|
||||
m_ogl_initialized = true;
|
||||
ogl_initialize();
|
||||
}
|
||||
|
||||
if( m_reload_is_needed )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) );
|
||||
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = new MODEL_3D( *m_3d_model, MATERIAL_MODE::NORMAL );
|
||||
|
||||
// It convert a model as it was a board, so get the max size dimension of the board
|
||||
// and compute the conversion scale
|
||||
m_BiuTo3dUnits =
|
||||
(double) RANGE_SCALE_3D
|
||||
/ ( (double) m_ogl_3dmodel->GetBBox().GetMaxDimension() * UNITS3D_TO_UNITSPCB );
|
||||
}
|
||||
|
||||
glViewport( 0, 0, clientSize.x, clientSize.y );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( clientSize );
|
||||
|
||||
// clear color and depth buffers
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
glClearDepth( 1.0f );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Set projection and modelview matrices
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetProjectionMatrix() ) );
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) );
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_LIGHT0 );
|
||||
|
||||
// Render Model
|
||||
if( m_ogl_3dmodel )
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
double modelunit_to_3d_units_factor = m_BiuTo3dUnits * UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glScaled( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor );
|
||||
|
||||
// Center model in the render viewport
|
||||
const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
|
||||
|
||||
glTranslatef( -model_center.x, -model_center.y, -model_center.z );
|
||||
|
||||
m_ogl_3dmodel->BeginDrawMulti( true );
|
||||
|
||||
m_ogl_3dmodel->DrawOpaque( false );
|
||||
|
||||
glDepthMask( GL_FALSE );
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
m_ogl_3dmodel->DrawTransparent( 1.0f, false );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glDepthMask( GL_TRUE );
|
||||
|
||||
m_ogl_3dmodel->EndDrawMulti();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// YxY squared view port
|
||||
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 );
|
||||
glClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
gluPerspective( 45.0f, 1.0f, 0.01f, RANGE_SCALE_3D * 2.0f );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
const glm::mat4 TranslationMatrix = glm::translate( glm::mat4(1.0f),
|
||||
SFVEC3F( 0.0f, 0.0f, -RANGE_SCALE_3D ) );
|
||||
|
||||
const glm::mat4 ViewMatrix = TranslationMatrix * m_trackBallCamera.GetRotationMatrix();
|
||||
|
||||
glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
|
||||
|
||||
ogl_set_arrow_material();
|
||||
|
||||
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||
DrawRoundArrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( RANGE_SCALE_3D / 2.65f, 0.0f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||
DrawRoundArrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( 0.0f, RANGE_SCALE_3D / 2.65f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||
DrawRoundArrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 2.65f ),
|
||||
0.275f );
|
||||
|
||||
// "Swaps the double-buffer of this window, making the back-buffer the
|
||||
// front-buffer and vice versa, so that the output of the previous OpenGL
|
||||
// commands is displayed on the window."
|
||||
SwapBuffers();
|
||||
|
||||
Pgm().GetGLContextManager()->UnlockCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnEraseBackground( wxEraseEvent& event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnEraseBackground" ) );
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMouseWheel( wxMouseEvent& event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnMouseWheel" ) );
|
||||
|
||||
if( event.ShiftDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() < 0 )
|
||||
//SetView3D( VIEW_3D_TYPE::VIEW3D_PAN_UP ); // move up
|
||||
//else
|
||||
//SetView3D( VIEW_3D_TYPE::VIEW3D_PAN_DOWN ); // move down
|
||||
}
|
||||
else if( event.ControlDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() > 0 )
|
||||
//SetView3D( VIEW_3D_TYPE::VIEW3D_PAN_RIGHT ); // move right
|
||||
//else
|
||||
//SetView3D( VIEW_3D_TYPE::VIEW3D_PAN_LEFT ); // move left
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackBallCamera.Zoom( event.GetWheelRotation() > 0 ? 1.1f : 1/1.1f );
|
||||
|
||||
//DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void EDA_3D_MODEL_VIEWER::OnMagnify( wxMouseEvent& event )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMouseMove( wxMouseEvent& event )
|
||||
{
|
||||
const wxSize& nativeWinSize = GetNativePixelSize();
|
||||
const wxPoint& nativePosition = GetNativePosition( event.GetPosition() );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( nativeWinSize );
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() ) // Drag
|
||||
m_trackBallCamera.Drag( nativePosition );
|
||||
|
||||
// orientation has changed, redraw mesh
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( nativePosition );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnLeftDown( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnLeftUp( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMiddleDown( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMiddleUp( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnRightClick( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_model_viewer.h
|
||||
* @brief Implements a model viewer canvas.
|
||||
*
|
||||
* The purpose of model viewer is to render 3d models that come in the original data from
|
||||
* the files without any transformations.
|
||||
*/
|
||||
|
||||
#ifndef _C3D_MODEL_VIEWER_H_
|
||||
#define _C3D_MODEL_VIEWER_H_
|
||||
|
||||
#include "3d_rendering/track_ball.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class MODEL_3D;
|
||||
|
||||
/**
|
||||
* Implement a canvas based on a wxGLCanvas.
|
||||
*/
|
||||
class EDA_3D_MODEL_VIEWER : public HIDPI_GL_CANVAS
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a new 3D Canvas with a attribute list.
|
||||
*
|
||||
* @param aParent the parent creator of this canvas.
|
||||
* @param aGLAttribs openGL attributes created by #OGL_ATT_LIST::GetAttributesList.
|
||||
*/
|
||||
EDA_3D_MODEL_VIEWER( wxWindow* aParent, const wxGLAttributes& aGLAttribs,
|
||||
S3D_CACHE* aCacheManager = nullptr );
|
||||
|
||||
~EDA_3D_MODEL_VIEWER();
|
||||
|
||||
/**
|
||||
* Set this model to be displayed.
|
||||
*
|
||||
* @param a3DModel 3D model data.
|
||||
*/
|
||||
void Set3DModel( const S3DMODEL& a3DModel );
|
||||
|
||||
/**
|
||||
* Set this model to be displayed.
|
||||
*
|
||||
* N.B. This will not load a model from the internal cache. Only from on disk.
|
||||
*
|
||||
* @param aModelPathName 3D model path name. Must be a file on disk.
|
||||
*/
|
||||
void Set3DModel( const wxString& aModelPathName );
|
||||
|
||||
/**
|
||||
* Unload the displayed 3D model.
|
||||
*/
|
||||
void Clear3DModel();
|
||||
|
||||
private:
|
||||
void ogl_initialize();
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
void OnPaint( wxPaintEvent& event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent& event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent& event );
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent& event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent& event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent& event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent& event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent& event );
|
||||
|
||||
void OnRightClick( wxMouseEvent& event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
/// openGL context
|
||||
wxGLContext* m_glRC;
|
||||
|
||||
/// Camera used in this canvas
|
||||
TRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// Original 3d model data
|
||||
const S3DMODEL* m_3d_model;
|
||||
|
||||
/// Class holder for 3d model to display on openGL
|
||||
MODEL_3D* m_ogl_3dmodel;
|
||||
|
||||
/// Flag that we have a new model and it need to be reloaded when the paint is called
|
||||
bool m_reload_is_needed;
|
||||
|
||||
/// Flag if open gl was initialized
|
||||
bool m_ogl_initialized;
|
||||
|
||||
/// factor to convert the model or any other items to keep it in relation to
|
||||
/// the +/-RANGE_SCALE_3D
|
||||
/// (it is named same as the board render for better understanding proposes)
|
||||
double m_BiuTo3dUnits;
|
||||
|
||||
/// Optional cache manager
|
||||
S3D_CACHE* m_cacheManager;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
};
|
||||
|
||||
#endif // _C3D_MODEL_VIEWER_H_
|
||||
@@ -1,27 +0,0 @@
|
||||
add_library(3d-viewer_navlib STATIC
|
||||
"nl_3d_viewer_plugin.cpp"
|
||||
"nl_3d_viewer_plugin_impl.cpp"
|
||||
"nl_footprint_properties_plugin.cpp"
|
||||
"nl_footprint_properties_plugin_impl.cpp"
|
||||
)
|
||||
|
||||
# 3d-viewer_navlib depends on make_lexer outputs in common
|
||||
add_dependencies( 3d-viewer_navlib pcbcommon )
|
||||
|
||||
# Find the 3DxWare SDK component 3DxWare::NlClient
|
||||
# find_package(TDxWare_SDK 4.0 REQUIRED COMPONENTS 3DxWare::Navlib)
|
||||
target_compile_definitions(3d-viewer_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
target_compile_options(3d-viewer_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_OPTIONS>
|
||||
)
|
||||
target_include_directories(3d-viewer_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:pcbnew_kiface_objects,INCLUDE_DIRECTORIES>
|
||||
)
|
||||
target_link_libraries(3d-viewer_navlib
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_LINK_LIBRARIES>
|
||||
3DxWare::Navlib
|
||||
)
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 3Dconnexion
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nl_3d_viewer_plugin.h"
|
||||
#include "nl_3d_viewer_plugin_impl.h"
|
||||
#include <advanced_config.h>
|
||||
#include <kiplatform/drivers.h>
|
||||
|
||||
|
||||
NL_3D_VIEWER_PLUGIN::NL_3D_VIEWER_PLUGIN( EDA_3D_CANVAS* aViewport )
|
||||
{
|
||||
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver
|
||||
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() )
|
||||
{
|
||||
m_impl = std::make_unique<NL_3D_VIEWER_PLUGIN_IMPL>( aViewport, "KiCAD 3D" );
|
||||
m_impl->Connect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NL_3D_VIEWER_PLUGIN::~NL_3D_VIEWER_PLUGIN() = default;
|
||||
|
||||
|
||||
void NL_3D_VIEWER_PLUGIN::SetFocus( bool focus )
|
||||
{
|
||||
if( m_impl )
|
||||
m_impl->SetFocus( focus );
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 3Dconnexion
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_3d_viewer_plugin.h
|
||||
* @brief Declaration of the NL_3D_VIEWER_PLUGIN class
|
||||
*/
|
||||
|
||||
#ifndef NL_3D_VIEWER_PLUGIN_H_
|
||||
#define NL_3D_VIEWER_PLUGIN_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_3D_CANVAS;
|
||||
class NL_3D_VIEWER_PLUGIN_IMPL;
|
||||
|
||||
/**
|
||||
* The class that implements the public interface to the SpaceMouse plug-in.
|
||||
*/
|
||||
class NL_3D_VIEWER_PLUGIN
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_3D_VIEWER_PLUGIN.
|
||||
*
|
||||
* @param aViewport is the viewport to be navigated.
|
||||
*/
|
||||
NL_3D_VIEWER_PLUGIN( EDA_3D_CANVAS* aViewport );
|
||||
|
||||
virtual ~NL_3D_VIEWER_PLUGIN();
|
||||
|
||||
/**
|
||||
* Set the connection to the 3Dconnexion driver to the focus state so that
|
||||
* 3DMouse data is routed here.
|
||||
*
|
||||
* @param aFocus is true to set the connection active.
|
||||
*/
|
||||
void SetFocus( bool aFocus = true );
|
||||
|
||||
private:
|
||||
std::unique_ptr<NL_3D_VIEWER_PLUGIN_IMPL> m_impl;
|
||||
};
|
||||
|
||||
#endif // NL_3D_VIEWER_PLUGIN_H_
|
||||
@@ -1,663 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nl_3d_viewer_plugin_impl.h"
|
||||
|
||||
// 3d-viewer
|
||||
#include <3d-viewer/3d_rendering/track_ball.h>
|
||||
#include <3d-viewer/3d_canvas/eda_3d_canvas.h>
|
||||
|
||||
// KiCad includes
|
||||
#include <tool/action_manager.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tool/tools_holder.h>
|
||||
|
||||
// stdlib
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/mstream.h>
|
||||
|
||||
/**
|
||||
* Flag to enable the NL_3D_VIEWER_PLUGIN debug tracing.
|
||||
*
|
||||
* Use "KI_TRACE_NL_3D_VIEWER_PLUGIN" to enable.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* NL_3D_VIEWER_PLUGIN_IMPL::m_logTrace = wxT( "KI_TRACE_NL_3D_VIEWER_PLUGIN" );
|
||||
|
||||
|
||||
/**
|
||||
* Template to compare two glm::mat<T> values for equality within a required epsilon.
|
||||
*
|
||||
* @param aFirst value to compare.
|
||||
* @param aSecond value to compare.
|
||||
* @param aEpsilon allowed error.
|
||||
* @return true if the values considered equal within the specified epsilon, otherwise false.
|
||||
*/
|
||||
template <glm::length_t L, glm::length_t C, class T, glm::qualifier Q>
|
||||
bool equals( glm::mat<L, C, T, Q> const& aFirst, glm::mat<L, C, T, Q> const& aSecond,
|
||||
T aEpsilon = static_cast<T>( FLT_EPSILON * 10 ) )
|
||||
{
|
||||
T const* first = glm::value_ptr( aFirst );
|
||||
T const* second = glm::value_ptr( aSecond );
|
||||
|
||||
for( glm::length_t j = 0; j < L * C; ++j )
|
||||
{
|
||||
if( !equals( first[j], second[j], aEpsilon ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NL_3D_VIEWER_PLUGIN_IMPL::NL_3D_VIEWER_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas,
|
||||
const std::string& aProfileHint ) :
|
||||
NAV_3D( false, false ),
|
||||
m_canvas( aCanvas ),
|
||||
m_capIsMoving( false ),
|
||||
m_newWidth( 0.0 )
|
||||
{
|
||||
m_camera = dynamic_cast<TRACK_BALL*>( m_canvas->GetCamera() );
|
||||
|
||||
PutProfileHint( aProfileHint );
|
||||
}
|
||||
|
||||
|
||||
NL_3D_VIEWER_PLUGIN_IMPL::~NL_3D_VIEWER_PLUGIN_IMPL()
|
||||
{
|
||||
EnableNavigation( false );
|
||||
}
|
||||
|
||||
|
||||
void NL_3D_VIEWER_PLUGIN_IMPL::SetFocus( bool aFocus )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "NL_3D_VIEWER_PLUGIN_IMPL::SetFocus %d" ), aFocus );
|
||||
NAV_3D::Write( navlib::focus_k, aFocus );
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_CANVAS* NL_3D_VIEWER_PLUGIN_IMPL::GetCanvas() const
|
||||
{
|
||||
return m_canvas;
|
||||
}
|
||||
|
||||
|
||||
void NL_3D_VIEWER_PLUGIN_IMPL::Connect()
|
||||
{
|
||||
EnableNavigation(true);
|
||||
PutFrameTimingSource(TimingSource::SpaceMouse);
|
||||
exportCommandsAndImages();
|
||||
}
|
||||
|
||||
|
||||
CATEGORY_STORE::iterator add_category( std::string aCategoryPath, CATEGORY_STORE& aCategoryStore )
|
||||
{
|
||||
using TDx::SpaceMouse::CCategory;
|
||||
|
||||
CATEGORY_STORE::iterator parent_iter = aCategoryStore.begin();
|
||||
std::string::size_type pos = aCategoryPath.find_last_of( '.' );
|
||||
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
std::string parentPath = aCategoryPath.substr( 0, pos );
|
||||
parent_iter = aCategoryStore.find( parentPath );
|
||||
|
||||
if( parent_iter == aCategoryStore.end() )
|
||||
{
|
||||
parent_iter = add_category( parentPath, aCategoryStore );
|
||||
}
|
||||
}
|
||||
|
||||
std::string name = aCategoryPath.substr( pos + 1 );
|
||||
std::unique_ptr<CCategory> categoryNode =
|
||||
std::make_unique<CCategory>( aCategoryPath.c_str(), name.c_str() );
|
||||
|
||||
CATEGORY_STORE::iterator iter = aCategoryStore.insert(
|
||||
aCategoryStore.end(), CATEGORY_STORE::value_type( aCategoryPath, categoryNode.get() ) );
|
||||
|
||||
parent_iter->second->push_back( std::move( categoryNode ) );
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
void NL_3D_VIEWER_PLUGIN_IMPL::exportCommandsAndImages()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "NL_3D_VIEWER_PLUGIN_IMPL::exportCommandsAndImages" ) );
|
||||
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
|
||||
if( actions.size() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using TDx::SpaceMouse::CCommand;
|
||||
using TDx::SpaceMouse::CCommandSet;
|
||||
|
||||
// The root action set node
|
||||
CCommandSet commandSet( "EDA_3D_CANVAS", "3D Viewer" );
|
||||
|
||||
// Activate the command set
|
||||
NAV_3D::PutActiveCommands( commandSet.GetId() );
|
||||
|
||||
// temporary store for the categories
|
||||
CATEGORY_STORE categoryStore;
|
||||
|
||||
std::vector<TDx::CImage> vImages;
|
||||
|
||||
// add the action set to the category_store
|
||||
categoryStore.insert( categoryStore.end(), CATEGORY_STORE::value_type( ".", &commandSet ) );
|
||||
|
||||
std::list<TOOL_ACTION*>::const_iterator it;
|
||||
|
||||
for( it = actions.begin(); it != actions.end(); ++it )
|
||||
{
|
||||
const TOOL_ACTION* action = *it;
|
||||
std::string label = action->GetMenuLabel().ToStdString();
|
||||
|
||||
if( label.empty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = action->GetName();
|
||||
|
||||
// Do no export commands for the Pcbnew app.
|
||||
if( name.rfind( "pcbnew.", 0 ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string strCategory = action->GetToolName();
|
||||
CATEGORY_STORE::iterator iter = categoryStore.find( strCategory );
|
||||
|
||||
if( iter == categoryStore.end() )
|
||||
{
|
||||
iter = add_category( std::move( strCategory ), categoryStore );
|
||||
}
|
||||
|
||||
std::string description = action->GetDescription().ToStdString();
|
||||
|
||||
// Arbitrary 8-bit data stream
|
||||
wxMemoryOutputStream imageStream;
|
||||
|
||||
if( action->GetIcon() != BITMAPS::INVALID_BITMAP )
|
||||
{
|
||||
wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage();
|
||||
image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG );
|
||||
image.Destroy();
|
||||
|
||||
if( imageStream.GetSize() )
|
||||
{
|
||||
wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer();
|
||||
TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() );
|
||||
tdxImage.AssignImage( std::string( reinterpret_cast<const char*>(
|
||||
streamBuffer->GetBufferStart() ),
|
||||
streamBuffer->GetBufferSize() ),
|
||||
0 );
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
|
||||
vImages.push_back( std::move( tdxImage ) );
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
|
||||
name, description, iter->first );
|
||||
|
||||
iter->second->push_back(
|
||||
CCommand( std::move( name ), std::move( label ), std::move( description ) ) );
|
||||
}
|
||||
|
||||
NAV_3D::AddCommandSet( commandSet );
|
||||
NAV_3D::AddImages( vImages );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetCameraMatrix( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
// cache the camera matrix so that we can tell if the view has been moved and
|
||||
// calculate a delta transform if required.
|
||||
m_cameraMatrix = m_camera->GetViewMatrix();
|
||||
|
||||
std::copy_n( glm::value_ptr( glm::inverse( m_cameraMatrix ) ), 16, matrix.m );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetPointerPosition( navlib::point_t& position ) const
|
||||
{
|
||||
SFVEC3F origin, direction;
|
||||
m_camera->MakeRayAtCurrentMousePosition( origin, direction );
|
||||
|
||||
position = { origin.x, origin.y, origin.z };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetViewExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
if( m_camera->GetProjection() == PROJECTION_TYPE::PERSPECTIVE )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
const CAMERA_FRUSTUM& f = m_camera->GetFrustum();
|
||||
|
||||
double half_width = f.fw / 2.;
|
||||
double half_height = f.fh / 2.;
|
||||
extents = { -half_width, -half_height, f.nearD, half_width, half_height, f.farD };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetViewFOV( double& aFov ) const
|
||||
{
|
||||
const CAMERA_FRUSTUM& f = m_camera->GetFrustum();
|
||||
|
||||
aFov = glm::radians( f.angle );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetViewFrustum( navlib::frustum_t& aFrustum ) const
|
||||
{
|
||||
if( m_camera->GetProjection() != PROJECTION_TYPE::PERSPECTIVE )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
const CAMERA_FRUSTUM& f = m_camera->GetFrustum();
|
||||
double half_width = f.nw / 2.;
|
||||
double half_height = f.nh / 2.;
|
||||
aFrustum = { -half_width, half_width, -half_height, half_height, f.nearD, f.farD };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetIsViewPerspective( navlib::bool_t& perspective ) const
|
||||
{
|
||||
perspective = m_camera->GetProjection() == PROJECTION_TYPE::PERSPECTIVE ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetCameraMatrix( const navlib::matrix_t& aCameraMatrix )
|
||||
{
|
||||
long result = 0;
|
||||
|
||||
glm::mat4 cam, viewMatrix;
|
||||
std::copy_n( aCameraMatrix.m, 16, glm::value_ptr( cam ) );
|
||||
viewMatrix = glm::inverse( cam );
|
||||
|
||||
glm::mat4 camera = m_camera->GetViewMatrix();
|
||||
|
||||
// The navlib does not move the camera in its z-axis in an orthographic projection
|
||||
// as this does not change the viewed object size. However ...
|
||||
|
||||
if( m_camera->GetProjection() == PROJECTION_TYPE::ORTHO )
|
||||
{
|
||||
// ... the CAMERA class couples zoom and distance to the object: we need to
|
||||
// ensure that The CAMERA's z position relative to the lookat_pos is not changed
|
||||
// in an orthographic projection.
|
||||
glm::vec4 lookat( m_camera->GetLookAtPos(), 1.0f );
|
||||
glm::vec4 lookat_new = viewMatrix * lookat;
|
||||
glm::vec4 lookat_old = camera * lookat;
|
||||
|
||||
viewMatrix[3].z += lookat_old.z - lookat_new.z;
|
||||
}
|
||||
|
||||
if( !equals( camera, m_cameraMatrix ) )
|
||||
{
|
||||
// Some other input device has moved the camera. Apply only the intended delta
|
||||
// transform ...
|
||||
m_camera->SetViewMatrix( viewMatrix * glm::inverse( m_cameraMatrix ) * camera );
|
||||
m_camera->Update();
|
||||
|
||||
// .., cache the intended camera matrix so that we can calculate the delta
|
||||
// transform when needed ...
|
||||
m_cameraMatrix = viewMatrix;
|
||||
|
||||
// ... and let the 3DMouse controller know, that something is amiss.
|
||||
return navlib::make_result_code( navlib::navlib_errc::error );
|
||||
}
|
||||
|
||||
m_camera->SetViewMatrix( viewMatrix );
|
||||
m_camera->Update();
|
||||
|
||||
// cache the view matrix so that we know when it has changed.
|
||||
m_cameraMatrix = m_camera->GetViewMatrix();
|
||||
|
||||
// The camera has a constraint on the z position so we need to check that ...
|
||||
|
||||
if( !equals( m_cameraMatrix[3].z, viewMatrix[3].z ) )
|
||||
{
|
||||
// ... and let the 3DMouse controller know, when something is amiss.
|
||||
return navlib::make_result_code( navlib::navlib_errc::error );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetViewExtents( const navlib::box_t& extents )
|
||||
{
|
||||
const CAMERA_FRUSTUM& f = m_camera->GetFrustum();
|
||||
|
||||
float factor = f.nw / ( extents.max_x - extents.min_x );
|
||||
float zoom = m_camera->GetZoom() / factor;
|
||||
|
||||
m_camera->Zoom( factor );
|
||||
|
||||
// The camera auto positions the camera to match the zoom values. We need to
|
||||
// update our cached camera matrix to match the new z value
|
||||
m_cameraMatrix[3].z = m_camera->GetViewMatrix()[3].z;
|
||||
|
||||
// The camera has a constraint on the zoom factor so we need to check that ...
|
||||
if( zoom != m_camera->GetZoom() )
|
||||
{
|
||||
// ... and let the 3DMouse controller know, when something is amiss.
|
||||
return navlib::make_result_code( navlib::navlib_errc::error );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetViewFOV( double fov )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::function_not_supported );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetViewFrustum( const navlib::frustum_t& frustum )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::permission_denied );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
SFVEC3F min = m_canvas->GetBoardAdapter().GetBBox().Min();
|
||||
SFVEC3F max = m_canvas->GetBoardAdapter().GetBBox().Max();
|
||||
|
||||
extents = { min.x, min.y, min.z, max.x, max.y, max.z };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetSelectionExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetSelectionTransform( navlib::matrix_t& transform ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetIsSelectionEmpty( navlib::bool_t& empty ) const
|
||||
{
|
||||
empty = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetSelectionTransform( const navlib::matrix_t& matrix )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetPivotPosition( navlib::point_t& position ) const
|
||||
{
|
||||
SFVEC3F lap = m_camera->GetLookAtPos();
|
||||
|
||||
position = { lap.x, lap.y, lap.z };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::IsUserPivot( navlib::bool_t& userPivot ) const
|
||||
{
|
||||
userPivot = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetPivotPosition( const navlib::point_t& position )
|
||||
{
|
||||
SFVEC3F pivotPos = SFVEC3F( position.x, position.y, position.z );
|
||||
|
||||
// Set the 3dmouse pivot position.
|
||||
m_canvas->Set3dmousePivotPos( pivotPos );
|
||||
|
||||
// Set the camera lookat pos.
|
||||
m_camera->SetLookAtPos_T1( pivotPos );
|
||||
|
||||
m_canvas->Request_refresh();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetPivotVisible( navlib::bool_t& visible ) const
|
||||
{
|
||||
visible = m_canvas->GetRender3dmousePivot();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetPivotVisible( bool visible )
|
||||
{
|
||||
m_canvas->SetRender3dmousePivot( visible );
|
||||
|
||||
m_canvas->Request_refresh();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetHitLookAt( navlib::point_t& position ) const
|
||||
{
|
||||
RAY mouseRay;
|
||||
mouseRay.Init( m_rayOrigin, m_rayDirection );
|
||||
|
||||
float hit;
|
||||
glm::vec3 vec;
|
||||
|
||||
// Test it with the board bounding box
|
||||
|
||||
if( m_canvas->GetBoardAdapter().GetBBox().Intersect( mouseRay, &hit ) )
|
||||
{
|
||||
vec = mouseRay.at( hit );
|
||||
position = { vec.x, vec.y, vec.z };
|
||||
return 0;
|
||||
}
|
||||
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetHitAperture( double aperture )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::function_not_supported );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetHitDirection( const navlib::vector_t& direction )
|
||||
{
|
||||
m_rayDirection = { direction.x, direction.y, direction.z };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetHitLookFrom( const navlib::point_t& eye )
|
||||
{
|
||||
m_rayOrigin = { eye.x, eye.y, eye.z };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetHitSelectionOnly( bool onlySelection )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::function_not_supported );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetActiveCommand( std::string commandId )
|
||||
{
|
||||
if( commandId.empty() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
TOOL_ACTION* context = nullptr;
|
||||
|
||||
for( std::list<TOOL_ACTION*>::const_iterator it = actions.begin(); it != actions.end(); it++ )
|
||||
{
|
||||
TOOL_ACTION* action = *it;
|
||||
std::string nm = action->GetName();
|
||||
|
||||
if( commandId == nm )
|
||||
{
|
||||
context = action;
|
||||
}
|
||||
}
|
||||
|
||||
if( context != nullptr )
|
||||
{
|
||||
wxWindow* parent = m_canvas->GetParent();
|
||||
|
||||
// Only allow command execution if the window is enabled. i.e. there is not a modal dialog
|
||||
// currently active.
|
||||
TOOLS_HOLDER* tools_holder = nullptr;
|
||||
|
||||
if( parent->IsEnabled() && ( tools_holder = dynamic_cast<TOOLS_HOLDER*>( parent ) ) )
|
||||
{
|
||||
TOOL_MANAGER* tool_manager = tools_holder->GetToolManager();
|
||||
|
||||
if( tool_manager == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
// Get the selection to use to test if the action is enabled
|
||||
SELECTION& sel = tool_manager->GetToolHolder()->GetCurrentSelection();
|
||||
|
||||
bool runAction = true;
|
||||
|
||||
if( const ACTION_CONDITIONS* aCond =
|
||||
tool_manager->GetActionManager()->GetCondition( *context ) )
|
||||
{
|
||||
runAction = aCond->enableCondition( sel );
|
||||
}
|
||||
|
||||
if( runAction )
|
||||
{
|
||||
tool_manager->RunAction( *context );
|
||||
m_canvas->Request_refresh();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetSettingsChanged( long change )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetMotionFlag( bool value )
|
||||
{
|
||||
m_capIsMoving = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetTransaction( long value )
|
||||
{
|
||||
if( value != 0L )
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
m_canvas->Request_refresh( true );
|
||||
wxLogTrace( m_logTrace, wxT( "End of transaction" ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::SetCameraTarget( const navlib::point_t& position )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::function_not_supported );
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetFrontView( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
matrix = { 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetCoordinateSystem( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
// Use the right-handed coordinate system X-right, Z-up, Y-in (row vectors)
|
||||
matrix = { 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1 };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_3D_VIEWER_PLUGIN_IMPL::GetIsViewRotatable( navlib::bool_t& isRotatable ) const
|
||||
{
|
||||
isRotatable = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_3d_viewer_plugin_impl.h
|
||||
* @brief Declaration of the NL_3D_VIEWER_PLUGIN_IMPL class
|
||||
*/
|
||||
|
||||
#ifndef NL_3D_VIEWER_PLUGIN_IMPL_H_
|
||||
#define NL_3D_VIEWER_PLUGIN_IMPL_H_
|
||||
|
||||
// TDxWare SDK.
|
||||
#include <SpaceMouse/CNavigation3D.hpp>
|
||||
|
||||
// KiCad
|
||||
#include <include/plugins/3dapi/xv3d_types.h>
|
||||
|
||||
// wx
|
||||
#include <wx/chartype.h>
|
||||
|
||||
// glm
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_3D_CANVAS;
|
||||
class TRACK_BALL;
|
||||
|
||||
// temporary store for the categories
|
||||
typedef std::map<std::string, TDx::CCommandTreeNode*> CATEGORY_STORE;
|
||||
|
||||
/**
|
||||
* Add a category to the store.
|
||||
*
|
||||
* The function adds category paths of the format "A.B" where B is a sub-category of A.
|
||||
*
|
||||
* @param aCategoryPath is the std::string representation of the category.
|
||||
* @param aCategoryStore is the CATEGORY_STORE instance to add to.
|
||||
* @return a CATEGORY_STORE::iterator where the category was added.
|
||||
*/
|
||||
CATEGORY_STORE::iterator add_category( std::string aCategoryPath, CATEGORY_STORE& aCategoryStore );
|
||||
|
||||
// Convenience typedef.
|
||||
typedef TDx::SpaceMouse::Navigation3D::CNavigation3D NAV_3D;
|
||||
|
||||
/**
|
||||
* The class that implements the accessors and mutators required for
|
||||
* 3D navigation in an EDA_3D_CANVAS using a SpaceMouse.
|
||||
*/
|
||||
class NL_3D_VIEWER_PLUGIN_IMPL : public NAV_3D
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_3DVIEWER_PLUGIN.
|
||||
*
|
||||
* @param aCanvas is the viewport to be navigated.
|
||||
* @param aProfileHint tells the 3DConnexion UI which profile to use.
|
||||
*/
|
||||
NL_3D_VIEWER_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas, const std::string& aProfileHint );
|
||||
|
||||
virtual ~NL_3D_VIEWER_PLUGIN_IMPL();
|
||||
|
||||
/**
|
||||
* Set the connection to the 3Dconnexion driver to the focus state so that
|
||||
* 3DMouse data is routed here.
|
||||
*
|
||||
* @param aFocus is true to set the connection active.
|
||||
*/
|
||||
void SetFocus( bool aFocus = true );
|
||||
|
||||
/**
|
||||
* Get the m_canvas pointer.
|
||||
*/
|
||||
EDA_3D_CANVAS* GetCanvas() const;
|
||||
|
||||
/**
|
||||
* Connect plugin implementation to the driver.
|
||||
*/
|
||||
void Connect();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Export the invocable actions and images to the 3Dconnexion UI.
|
||||
*/
|
||||
virtual void exportCommandsAndImages();
|
||||
|
||||
long GetCameraMatrix( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetPointerPosition( navlib::point_t& aPosition ) const override;
|
||||
long GetViewExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetViewFOV( double& aFov ) const override;
|
||||
long GetViewFrustum( navlib::frustum_t& aFrustum ) const override;
|
||||
long GetIsViewPerspective( navlib::bool_t& aPerspective ) const override;
|
||||
long SetCameraMatrix( const navlib::matrix_t& aMatrix ) override;
|
||||
long SetViewExtents( const navlib::box_t& aExtents ) override;
|
||||
long SetViewFOV( double aFov ) override;
|
||||
long SetViewFrustum( const navlib::frustum_t& aFrustum ) override;
|
||||
long GetModelExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetSelectionExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetSelectionTransform( navlib::matrix_t& aTransform ) const override;
|
||||
long GetIsSelectionEmpty( navlib::bool_t& aEmpty ) const override;
|
||||
long SetSelectionTransform( const navlib::matrix_t& aMatrix ) override;
|
||||
long GetPivotPosition( navlib::point_t& aPosition ) const override;
|
||||
long IsUserPivot( navlib::bool_t& aUserPivot ) const override;
|
||||
long SetPivotPosition( const navlib::point_t& aPosition ) override;
|
||||
long GetPivotVisible( navlib::bool_t& aVisible ) const override;
|
||||
long SetPivotVisible( bool aVisible ) override;
|
||||
long GetHitLookAt( navlib::point_t& aPosition ) const override;
|
||||
long SetHitAperture( double aAperture ) override;
|
||||
long SetHitDirection( const navlib::vector_t& aDirection ) override;
|
||||
long SetHitLookFrom( const navlib::point_t& aPosition ) override;
|
||||
long SetHitSelectionOnly( bool aSelectionOnly ) override;
|
||||
long SetActiveCommand( std::string aCommandId ) override;
|
||||
|
||||
long SetSettingsChanged( long aChangeNumber ) override;
|
||||
long SetMotionFlag( bool aValue ) override;
|
||||
long SetTransaction( long aValue ) override;
|
||||
long SetCameraTarget( const navlib::point_t& aPosition ) override;
|
||||
|
||||
long GetFrontView( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetCoordinateSystem( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetIsViewRotatable( navlib::bool_t& isRotatable ) const override;
|
||||
|
||||
|
||||
private:
|
||||
EDA_3D_CANVAS* m_canvas;
|
||||
TRACK_BALL* m_camera;
|
||||
bool m_capIsMoving;
|
||||
double m_newWidth;
|
||||
SFVEC3F m_rayOrigin;
|
||||
SFVEC3F m_rayDirection;
|
||||
|
||||
// The cached CAMERA affine matrix. This is used to determine if the camera has been
|
||||
// moved. The camera matrix is the world to camera affine.
|
||||
mutable glm::mat4 m_cameraMatrix;
|
||||
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_NL_3DVIEWER_PLUGIN". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
};
|
||||
|
||||
#endif // NL_3D_VIEWER_PLUGIN_IMPL_H_
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nl_footprint_properties_plugin.h"
|
||||
#include "nl_footprint_properties_plugin_impl.h"
|
||||
#include <advanced_config.h>
|
||||
#include <kiplatform/drivers.h>
|
||||
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN::NL_FOOTPRINT_PROPERTIES_PLUGIN( EDA_3D_CANVAS* aViewport )
|
||||
{
|
||||
if( ADVANCED_CFG::GetCfg().m_Use3DConnexionDriver
|
||||
&& KIPLATFORM::DRIVERS::Valid3DConnexionDriverVersion() )
|
||||
{
|
||||
m_impl = std::make_unique<NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL>( aViewport );
|
||||
m_impl->Connect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN::~NL_FOOTPRINT_PROPERTIES_PLUGIN() = default;
|
||||
|
||||
|
||||
void NL_FOOTPRINT_PROPERTIES_PLUGIN::SetFocus( bool focus )
|
||||
{
|
||||
if( m_impl )
|
||||
m_impl->SetFocus( focus );
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_footprint_properties_plugin.h
|
||||
* @brief declaration of the nl_footprint_properties_plugin class
|
||||
*/
|
||||
|
||||
#ifndef NL_FOOTPRINT_PROPERTIES_PLUGIN_H_
|
||||
#define NL_FOOTPRINT_PROPERTIES_PLUGIN_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_3D_CANVAS;
|
||||
class NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL;
|
||||
|
||||
/**
|
||||
* The class that implements the public interface to the SpaceMouse plug-in.
|
||||
*/
|
||||
class NL_FOOTPRINT_PROPERTIES_PLUGIN
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_FOOTPRINT_PROPERTIES_PLUGIN.
|
||||
*
|
||||
* @param aViewport is the viewport to be navigated.
|
||||
*/
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN( EDA_3D_CANVAS* aViewport );
|
||||
|
||||
virtual ~NL_FOOTPRINT_PROPERTIES_PLUGIN();
|
||||
|
||||
/**
|
||||
* Set the connection to the 3Dconnexion driver to the focus state so that
|
||||
* 3DMouse data is routed here.
|
||||
*
|
||||
* @param aFocus is true to set the connection active.
|
||||
*/
|
||||
void SetFocus( bool aFocus = true );
|
||||
|
||||
private:
|
||||
std::unique_ptr<NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL> m_impl;
|
||||
};
|
||||
|
||||
#endif // NL_FOOTPRINT_PROPERTIES_PLUGIN_H_
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nl_footprint_properties_plugin_impl.h"
|
||||
#include <3d-viewer/3d_canvas/eda_3d_canvas.h>
|
||||
|
||||
// KiCAD includes
|
||||
#include <tool/action_manager.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tool/tools_holder.h>
|
||||
|
||||
#include <wx/mstream.h>
|
||||
|
||||
#define BOUNDING_BOX_SCALE_FACTOR 1.3f
|
||||
|
||||
/**
|
||||
* Flag to enable the NL_FOOTPRINT_PROPERTIES_PLUGIN debug tracing.
|
||||
*
|
||||
* Use "KI_TRACE_NL_FOOTPRINT_PROPERTIES_PLUGIN" to enable.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL::m_logTrace =
|
||||
wxT( "KI_TRACE_NL_FOOTPRINT_PROPERTIES_PLUGIN" );
|
||||
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL::NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL(EDA_3D_CANVAS* aCanvas) :
|
||||
NL_3D_VIEWER_PLUGIN_IMPL(aCanvas, "KiCAD Footprint Properties")
|
||||
{}
|
||||
|
||||
|
||||
long NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
SFVEC3F min = NL_3D_VIEWER_PLUGIN_IMPL::GetCanvas()->GetBoardAdapter().GetBBox().Min();
|
||||
SFVEC3F max = NL_3D_VIEWER_PLUGIN_IMPL::GetCanvas()->GetBoardAdapter().GetBBox().Max();
|
||||
|
||||
SFVEC3F diff = ( BOUNDING_BOX_SCALE_FACTOR - 1.f ) / 2.f * ( max - min );
|
||||
|
||||
min -= diff;
|
||||
max += diff;
|
||||
|
||||
extents = { min.x, min.y, min.z, max.x, max.y, max.z };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL::exportCommandsAndImages()
|
||||
{
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
|
||||
if( actions.size() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using TDx::SpaceMouse::CCommand;
|
||||
using TDx::SpaceMouse::CCommandSet;
|
||||
|
||||
// The root action set node
|
||||
CCommandSet commandSet( "EDA_3D_CANVAS", "3D Viewer" );
|
||||
|
||||
// Activate the command set
|
||||
NAV_3D::PutActiveCommands( commandSet.GetId() );
|
||||
|
||||
// temporary store for the categories
|
||||
CATEGORY_STORE categoryStore;
|
||||
|
||||
std::vector<TDx::CImage> vImages;
|
||||
|
||||
// add the action set to the category_store
|
||||
categoryStore.insert( categoryStore.end(), CATEGORY_STORE::value_type( ".", &commandSet ) );
|
||||
|
||||
std::list<TOOL_ACTION*>::const_iterator it;
|
||||
|
||||
for( it = actions.begin(); it != actions.end(); ++it )
|
||||
{
|
||||
const TOOL_ACTION* action = *it;
|
||||
std::string label = action->GetMenuLabel().ToStdString();
|
||||
|
||||
if( label.empty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = action->GetName();
|
||||
|
||||
// Do no export commands for the pcbnew app.
|
||||
if( name.rfind( "pcbnew.", 0 ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Exclude commands which can't be used in the footprint properties.
|
||||
if( name.rfind( "3DViewer.Control.pivotCenter", 0 ) == 0
|
||||
|| name.rfind( "3DViewer.Control.material", 0 ) == 0
|
||||
|| name.rfind( "3DViewer.Control.attribute", 0 ) == 0
|
||||
|| name.rfind( "3DViewer.Control.show", 0 ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string strCategory = action->GetToolName();
|
||||
CATEGORY_STORE::iterator iter = categoryStore.find( strCategory );
|
||||
|
||||
if( iter == categoryStore.end() )
|
||||
{
|
||||
iter = add_category( std::move( strCategory ), categoryStore );
|
||||
}
|
||||
|
||||
std::string description = action->GetDescription().ToStdString();
|
||||
|
||||
// Arbitrary 8-bit data stream
|
||||
wxMemoryOutputStream imageStream;
|
||||
|
||||
if( action->GetIcon() != BITMAPS::INVALID_BITMAP )
|
||||
{
|
||||
wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage();
|
||||
image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG );
|
||||
image.Destroy();
|
||||
|
||||
if( imageStream.GetSize() )
|
||||
{
|
||||
wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer();
|
||||
TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() );
|
||||
tdxImage.AssignImage( std::string( reinterpret_cast<const char*>(
|
||||
streamBuffer->GetBufferStart() ),
|
||||
streamBuffer->GetBufferSize() ),
|
||||
0 );
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
|
||||
vImages.push_back( std::move( tdxImage ) );
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
|
||||
name, description, iter->first );
|
||||
|
||||
iter->second->push_back(
|
||||
CCommand( std::move( name ), std::move( label ), std::move( description ) ) );
|
||||
}
|
||||
|
||||
NAV_3D::AddCommandSet( commandSet );
|
||||
NAV_3D::AddImages( vImages );
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 3Dconnexion
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_footprint_properties_plugin_impl.h
|
||||
* @brief declaration of the nl_footprint_properties_plugin_impl class
|
||||
*/
|
||||
|
||||
#ifndef NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL_H_
|
||||
#define NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL_H_
|
||||
|
||||
#include "nl_3d_viewer_plugin_impl.h"
|
||||
// TDxWare SDK.
|
||||
#include <SpaceMouse/CNavigation3D.hpp>
|
||||
|
||||
/**
|
||||
* The class that adjusts NL_3D_VIEWER_PLUGIN_IMPL implementation for 3D Model preview in
|
||||
* footprint properties dialog.
|
||||
*/
|
||||
class NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL : public NL_3D_VIEWER_PLUGIN_IMPL
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initialize a new instance of the NL_FOOTPRINT_PROPERTIES_PLUGIN.
|
||||
*
|
||||
* @param aCanvas is the viewport to be navigated.
|
||||
*/
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL( EDA_3D_CANVAS* aCanvas );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Get Footprint 3D Model extents.
|
||||
*
|
||||
* @param extents is the box around the 3D model.
|
||||
*/
|
||||
long GetModelExtents( navlib::box_t& extents ) const override;
|
||||
|
||||
/**
|
||||
* Export the invocable actions and images to the 3Dconnexion UI.
|
||||
*/
|
||||
void exportCommandsAndImages() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_NL_FOOTPRINT_PROPERTIES_PLUGIN". See the wxWidgets documentation on
|
||||
* wxLogTrace for more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
};
|
||||
#endif // NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL_H_
|
||||
@@ -0,0 +1 @@
|
||||
#define PLUGINDIR "@CMAKE_INSTALL_FULL_LIBDIR@"
|
||||
@@ -0,0 +1,961 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_render_createscene_ogl_legacy.cpp
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#include "c3d_render_ogl_legacy.h"
|
||||
#include "ogl_legacy_utils.h"
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include "../../3d_math.h"
|
||||
#include "../../3d_fastmath.h"
|
||||
#include <trigo.h>
|
||||
#include <project.h>
|
||||
#include <profile.h> // To use GetRunningMicroSecs or another profiling utility
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CFILLEDCIRCLE2D * aFilledCircle,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F ¢er = aFilledCircle->GetCenter();
|
||||
const float radius = aFilledCircle->GetRadius() *
|
||||
2.0f; // Double because the render triangle
|
||||
|
||||
// This is a small adjustment to the circle texture
|
||||
const float texture_factor = (8.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
const float f = (sqrtf(2.0f) / 2.0f) * radius * texture_factor;
|
||||
|
||||
// Top and Bot segments ends are just triangle semi-circles, so need to add
|
||||
// it in duplicated
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZtop ),
|
||||
SFVEC3F( center.x - f, center.y, aZtop ),
|
||||
SFVEC3F( center.x,
|
||||
center.y - f, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZtop ),
|
||||
SFVEC3F( center.x + f, center.y, aZtop ),
|
||||
SFVEC3F( center.x,
|
||||
center.y + f, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZbot ),
|
||||
SFVEC3F( center.x + f, center.y, aZbot ),
|
||||
SFVEC3F( center.x,
|
||||
center.y - f, aZbot ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZbot ),
|
||||
SFVEC3F( center.x - f, center.y, aZbot ),
|
||||
SFVEC3F( center.x,
|
||||
center.y + f, aZbot ) );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CPOLYGON4PTS2D * aPoly,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F &v0 = aPoly->GetV0();
|
||||
const SFVEC2F &v1 = aPoly->GetV1();
|
||||
const SFVEC2F &v2 = aPoly->GetV2();
|
||||
const SFVEC2F &v3 = aPoly->GetV3();
|
||||
|
||||
add_triangle_top_bot( aDstLayer, v0, v2, v1, aZtop, aZbot );
|
||||
add_triangle_top_bot( aDstLayer, v2, v0, v3, aZtop, aZbot );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_ring_contour( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
std::vector< SFVEC2F > &aInnerContourResult,
|
||||
std::vector< SFVEC2F > &aOuterContourResult,
|
||||
bool aInvertOrder )
|
||||
{
|
||||
aInnerContourResult.clear();
|
||||
aInnerContourResult.reserve( aNr_sides_per_circle + 2 );
|
||||
|
||||
aOuterContourResult.clear();
|
||||
aOuterContourResult.reserve( aNr_sides_per_circle + 2 );
|
||||
|
||||
const int delta = 3600 / aNr_sides_per_circle;
|
||||
|
||||
for( int ii = 0; ii < 3600; ii += delta )
|
||||
{
|
||||
float angle = (float)( aInvertOrder ? ( 3600 - ii ) : ii )
|
||||
* 2.0f * glm::pi<float>() / 3600.0f;
|
||||
const SFVEC2F rotatedDir = SFVEC2F( cos( angle ), sin( angle ) );
|
||||
|
||||
aInnerContourResult.push_back( SFVEC2F( aCenter.x + rotatedDir.x * aInnerRadius,
|
||||
aCenter.y + rotatedDir.y * aInnerRadius ) );
|
||||
|
||||
aOuterContourResult.push_back( SFVEC2F( aCenter.x + rotatedDir.x * aOuterRadius,
|
||||
aCenter.y + rotatedDir.y * aOuterRadius ) );
|
||||
}
|
||||
|
||||
aInnerContourResult.push_back( aInnerContourResult[0] );
|
||||
aOuterContourResult.push_back( aOuterContourResult[0] );
|
||||
|
||||
wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CRING2D * aRing,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F ¢er = aRing->GetCenter();
|
||||
const float inner = aRing->GetInnerRadius();
|
||||
const float outer = aRing->GetOuterRadius();
|
||||
|
||||
std::vector< SFVEC2F > innerContour;
|
||||
std::vector< SFVEC2F > outerContour;
|
||||
|
||||
generate_ring_contour( center,
|
||||
inner,
|
||||
outer,
|
||||
m_settings.GetNrSegmentsCircle( outer * 2.0f ),
|
||||
innerContour,
|
||||
outerContour,
|
||||
false );
|
||||
|
||||
// This will add the top and bot quads that will form the approximated ring
|
||||
|
||||
for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &vi0 = innerContour[i + 0];
|
||||
const SFVEC2F &vi1 = innerContour[i + 1];
|
||||
const SFVEC2F &vo0 = outerContour[i + 0];
|
||||
const SFVEC2F &vo1 = outerContour[i + 1];
|
||||
|
||||
aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZtop ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZtop ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZbot ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZbot ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZbot ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CTRIANGLE2D * aTri,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F &v1 = aTri->GetP1();
|
||||
const SFVEC2F &v2 = aTri->GetP2();
|
||||
const SFVEC2F &v3 = aTri->GetP3();
|
||||
|
||||
add_triangle_top_bot( aDstLayer, v1, v2, v3, aZtop, aZbot );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_object_to_triangle_layer( const CROUNDSEGMENT2D * aSeg,
|
||||
CLAYER_TRIANGLES *aDstLayer,
|
||||
float aZtop,
|
||||
float aZbot )
|
||||
{
|
||||
const SFVEC2F leftStart = aSeg->GetLeftStar();
|
||||
const SFVEC2F leftEnd = aSeg->GetLeftEnd();
|
||||
const SFVEC2F leftDir = aSeg->GetLeftDir();
|
||||
|
||||
const SFVEC2F rightStart = aSeg->GetRightStar();
|
||||
const SFVEC2F rightEnd = aSeg->GetRightEnd();
|
||||
const SFVEC2F rightDir = aSeg->GetRightDir();
|
||||
const float radius = aSeg->GetRadius();
|
||||
|
||||
const SFVEC2F start = aSeg->GetStart();
|
||||
const SFVEC2F end = aSeg->GetEnd();
|
||||
|
||||
const float texture_factor = (12.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
const float texture_factorF= ( 6.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||
|
||||
const float radius_of_the_square = sqrtf( aSeg->GetRadiusSquared() * 2.0f );
|
||||
const float radius_triangle_factor = (radius_of_the_square - radius) / radius;
|
||||
|
||||
const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor,
|
||||
rightDir.x * radius * radius_triangle_factor );
|
||||
|
||||
const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor,
|
||||
leftDir.x * radius * radius_triangle_factor );
|
||||
|
||||
// Top end segment triangles (semi-circles)
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle(
|
||||
SFVEC3F( rightEnd.x + texture_factor * factorS.x,
|
||||
rightEnd.y + texture_factor * factorS.y,
|
||||
aZtop ),
|
||||
SFVEC3F( leftStart.x + texture_factor * factorE.x,
|
||||
leftStart.y + texture_factor * factorE.y,
|
||||
aZtop ),
|
||||
SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
|
||||
start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
|
||||
aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_top_segment_ends->AddTriangle(
|
||||
SFVEC3F( leftEnd.x + texture_factor * factorE.x,
|
||||
leftEnd.y + texture_factor * factorE.y, aZtop ),
|
||||
SFVEC3F( rightStart.x + texture_factor * factorS.x,
|
||||
rightStart.y + texture_factor * factorS.y, aZtop ),
|
||||
SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
|
||||
end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
|
||||
aZtop ) );
|
||||
|
||||
// Bot end segment triangles (semi-circles)
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle(
|
||||
SFVEC3F( leftStart.x + texture_factor * factorE.x,
|
||||
leftStart.y + texture_factor * factorE.y,
|
||||
aZbot ),
|
||||
SFVEC3F( rightEnd.x + texture_factor * factorS.x,
|
||||
rightEnd.y + texture_factor * factorS.y,
|
||||
aZbot ),
|
||||
SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
|
||||
start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
|
||||
aZbot ) );
|
||||
|
||||
aDstLayer->m_layer_bot_segment_ends->AddTriangle(
|
||||
SFVEC3F( rightStart.x + texture_factor * factorS.x,
|
||||
rightStart.y + texture_factor * factorS.y, aZbot ),
|
||||
SFVEC3F( leftEnd.x + texture_factor * factorE.x,
|
||||
leftEnd.y + texture_factor * factorE.y, aZbot ),
|
||||
SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
|
||||
end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
|
||||
aZbot ) );
|
||||
|
||||
// Segment top and bot planes
|
||||
aDstLayer->m_layer_top_triangles->AddQuad(
|
||||
SFVEC3F( rightEnd.x, rightEnd.y, aZtop ),
|
||||
SFVEC3F( rightStart.x, rightStart.y, aZtop ),
|
||||
SFVEC3F( leftEnd.x, leftEnd.y, aZtop ),
|
||||
SFVEC3F( leftStart.x, leftStart.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad(
|
||||
SFVEC3F( rightEnd.x, rightEnd.y, aZbot ),
|
||||
SFVEC3F( leftStart.x, leftStart.y, aZbot ),
|
||||
SFVEC3F( leftEnd.x, leftEnd.y, aZbot ),
|
||||
SFVEC3F( rightStart.x, rightStart.y, aZbot ) );
|
||||
}
|
||||
|
||||
|
||||
CLAYERS_OGL_DISP_LISTS *C3D_RENDER_OGL_LEGACY::generate_holes_display_list(
|
||||
const LIST_OBJECT2D &aListHolesObject2d,
|
||||
const SHAPE_POLY_SET &aPoly,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
bool aInvertFaces )
|
||||
{
|
||||
CLAYERS_OGL_DISP_LISTS *ret = NULL;
|
||||
|
||||
if( aListHolesObject2d.size() > 0 )
|
||||
{
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( aListHolesObject2d.size() * 2 );
|
||||
|
||||
// Convert the list of objects(filled circles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = aListHolesObject2d.begin();
|
||||
itemOnLayer != aListHolesObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( (object2d_A->GetObjectType() == OBJ2D_FILLED_CIRCLE) ||
|
||||
(object2d_A->GetObjectType() == OBJ2D_ROUNDSEG) );
|
||||
|
||||
switch( object2d_A->GetObjectType() )
|
||||
{
|
||||
case OBJ2D_FILLED_CIRCLE:
|
||||
add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A,
|
||||
layerTriangles,
|
||||
aZtop, aZbot );
|
||||
break;
|
||||
|
||||
case OBJ2D_ROUNDSEG:
|
||||
add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A,
|
||||
layerTriangles,
|
||||
aZtop, aZbot );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG("C3D_RENDER_OGL_LEGACY::generate_holes_display_list: Object type is not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: he can have a aListHolesObject2d whith holes but without countours
|
||||
// eg: when there are only NPTH on the list and the contours were not
|
||||
// added
|
||||
|
||||
if( aPoly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( aPoly,
|
||||
aZbot,
|
||||
aZtop,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
aInvertFaces );
|
||||
}
|
||||
|
||||
ret = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
aZbot,
|
||||
aZtop );
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::reload( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
m_reloadRequested = false;
|
||||
|
||||
ogl_free_all_display_lists();
|
||||
|
||||
COBJECT2D_STATS::Instance().ResetStats();
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
printf("InitSettings...\n");
|
||||
#endif
|
||||
|
||||
unsigned stats_startReloadTime = GetRunningMicroSecs();
|
||||
|
||||
m_settings.InitSettings( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_endReloadTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
SFVEC3F camera_pos = m_settings.GetBoardCenter3DU();
|
||||
m_settings.CameraGet().SetBoardLookAtPos( camera_pos );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_start_OpenGL_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: board" ) );
|
||||
|
||||
// Create Board
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CCONTAINER2D boardContainer;
|
||||
SHAPE_POLY_SET tmpBoard = m_settings.GetBoardPoly();
|
||||
Convert_shape_line_polygon_to_triangles( tmpBoard,
|
||||
boardContainer,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
(const BOARD_ITEM &)*m_settings.GetBoard() );
|
||||
|
||||
const LIST_OBJECT2D &listBoardObject2d = boardContainer.GetList();
|
||||
|
||||
if( listBoardObject2d.size() > 0 )
|
||||
{
|
||||
// We will set a unitary Z so it will in future used with transformations
|
||||
// since the board poly will be used not only to draw itself but also the
|
||||
// solder mask layers.
|
||||
const float layer_z_top = 1.0f;
|
||||
const float layer_z_bot = 0.0f;
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listBoardObject2d.size() );
|
||||
|
||||
// Convert the list of objects(triangles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listBoardObject2d.begin();
|
||||
itemOnLayer != listBoardObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( object2d_A->GetObjectType() == OBJ2D_TRIANGLE );
|
||||
|
||||
const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
|
||||
|
||||
const SFVEC2F &v1 = tri->GetP1();
|
||||
const SFVEC2F &v2 = tri->GetP2();
|
||||
const SFVEC2F &v3 = tri->GetP3();
|
||||
|
||||
add_triangle_top_bot( layerTriangles,
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
layer_z_top,
|
||||
layer_z_bot );
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET &boardPoly = m_settings.GetBoardPoly();
|
||||
|
||||
wxASSERT( boardPoly.OutlineCount() > 0 );
|
||||
|
||||
if( boardPoly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( boardPoly,
|
||||
layer_z_bot,
|
||||
layer_z_top,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_board = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
layer_z_top,
|
||||
layer_z_top );
|
||||
}
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
|
||||
// Create Through Holes and vias
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: holes and vias" ) );
|
||||
|
||||
m_ogl_disp_list_through_holes_outer = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Outer().GetList(),
|
||||
m_settings.GetThroughHole_Outer_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
SHAPE_POLY_SET bodyHoles = m_settings.GetThroughHole_Outer_poly();
|
||||
|
||||
bodyHoles.BooleanAdd( m_settings.GetThroughHole_Outer_poly_NPTH(),
|
||||
SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
m_ogl_disp_list_through_holes_outer_with_npth = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Outer().GetList(),
|
||||
bodyHoles,
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_through_holes_inner = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Inner().GetList(),
|
||||
m_settings.GetThroughHole_Inner_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
true );
|
||||
|
||||
|
||||
m_ogl_disp_list_through_holes_vias_outer = generate_holes_display_list(
|
||||
m_settings.GetThroughHole_Vias_Outer().GetList(),
|
||||
m_settings.GetThroughHole_Vias_Outer_poly(),
|
||||
1.0f,
|
||||
0.0f,
|
||||
false );
|
||||
|
||||
// Not in use
|
||||
//m_ogl_disp_list_through_holes_vias_inner = generate_holes_display_list(
|
||||
// m_settings.GetThroughHole_Vias_Inner().GetList(),
|
||||
// m_settings.GetThroughHole_Vias_Inner_poly(),
|
||||
// 1.0f, 0.0f,
|
||||
// false );
|
||||
|
||||
const MAP_POLY & innerMapHoles = m_settings.GetPolyMapHoles_Inner();
|
||||
const MAP_POLY & outerMapHoles = m_settings.GetPolyMapHoles_Outer();
|
||||
|
||||
wxASSERT( innerMapHoles.size() == outerMapHoles.size() );
|
||||
|
||||
const MAP_CONTAINER_2D &map_holes = m_settings.GetMapLayersHoles();
|
||||
|
||||
if( outerMapHoles.size() > 0 )
|
||||
{
|
||||
float layer_z_bot = 0.0f;
|
||||
float layer_z_top = 0.0f;
|
||||
|
||||
for( MAP_POLY::const_iterator ii = outerMapHoles.begin();
|
||||
ii != outerMapHoles.end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
const SHAPE_POLY_SET *poly = static_cast<const SHAPE_POLY_SET *>(ii->second);
|
||||
const CBVHCONTAINER2D *container = map_holes.at( layer_id );
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
m_ogl_disp_lists_layers_holes_outer[layer_id] = generate_holes_display_list(
|
||||
container->GetList(), *poly, layer_z_top, layer_z_bot, false );
|
||||
}
|
||||
|
||||
for( MAP_POLY::const_iterator ii = innerMapHoles.begin();
|
||||
ii != innerMapHoles.end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
const SHAPE_POLY_SET *poly = static_cast<const SHAPE_POLY_SET *>(ii->second);
|
||||
const CBVHCONTAINER2D *container = map_holes.at( layer_id );
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
m_ogl_disp_lists_layers_holes_inner[layer_id] = generate_holes_display_list(
|
||||
container->GetList(), *poly, layer_z_top, layer_z_bot, false );
|
||||
}
|
||||
}
|
||||
|
||||
// Generate vertical cylinders of vias and pads (copper)
|
||||
generate_3D_Vias_and_Pads();
|
||||
|
||||
// Add layers maps
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Load OpenGL: layers" ) );
|
||||
|
||||
for( MAP_CONTAINER_2D::const_iterator ii = m_settings.GetMapLayers().begin();
|
||||
ii != m_settings.GetMapLayers().end();
|
||||
++ii )
|
||||
{
|
||||
PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
|
||||
|
||||
if( !m_settings.Is3DLayerEnabled( layer_id ) )
|
||||
continue;
|
||||
|
||||
const CBVHCONTAINER2D *container2d = static_cast<const CBVHCONTAINER2D *>(ii->second);
|
||||
const LIST_OBJECT2D &listObject2d = container2d->GetList();
|
||||
|
||||
if( listObject2d.size() == 0 )
|
||||
continue;
|
||||
|
||||
float layer_z_bot = 0.0f;
|
||||
float layer_z_top = 0.0f;
|
||||
|
||||
get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
|
||||
|
||||
// Calculate an estimation for the nr of triangles based on the nr of objects
|
||||
unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( nrTrianglesEstimation );
|
||||
|
||||
m_triangles[layer_id] = layerTriangles;
|
||||
|
||||
// Load the 2D (X,Y axis) component of shapes
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin();
|
||||
itemOnLayer != listObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
switch( object2d_A->GetObjectType() )
|
||||
{
|
||||
case OBJ2D_FILLED_CIRCLE:
|
||||
add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_POLYGON4PT:
|
||||
add_object_to_triangle_layer( (const CPOLYGON4PTS2D *)object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_RING:
|
||||
add_object_to_triangle_layer( (const CRING2D *)object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_TRIANGLE:
|
||||
add_object_to_triangle_layer( (const CTRIANGLE2D *)object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
case OBJ2D_ROUNDSEG:
|
||||
add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A,
|
||||
layerTriangles, layer_z_top, layer_z_bot );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG("C3D_RENDER_OGL_LEGACY: Object type is not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const MAP_POLY &map_poly = m_settings.GetPolyMap();
|
||||
|
||||
// Load the vertical (Z axis) component of shapes
|
||||
if( map_poly.find( layer_id ) != map_poly.end() )
|
||||
{
|
||||
const SHAPE_POLY_SET *polyList = map_poly.at( layer_id );
|
||||
|
||||
if( polyList->OutlineCount() > 0 )
|
||||
layerTriangles->AddToMiddleContourns( *polyList, layer_z_bot, layer_z_top,
|
||||
m_settings.BiuTo3Dunits(), false );
|
||||
}
|
||||
|
||||
// Create display list
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
m_ogl_disp_lists_layers[layer_id] = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||
m_ogl_circle_texture,
|
||||
layer_z_bot,
|
||||
layer_z_top );
|
||||
}// for each layer on map
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_end_OpenGL_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
// Load 3D models
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_start_models_Load_Time = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Loading 3D models" ) );
|
||||
|
||||
load_3D_models( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_end_models_Load_Time = GetRunningMicroSecs();
|
||||
|
||||
|
||||
printf( "C3D_RENDER_OGL_LEGACY::reload times:\n" );
|
||||
printf( " Reload board: %.3f ms\n",
|
||||
(float)( stats_endReloadTime - stats_startReloadTime ) / 1000.0f );
|
||||
printf( " Loading to openGL: %.3f ms\n",
|
||||
(float)( stats_end_OpenGL_Load_Time - stats_start_OpenGL_Load_Time ) / 1000.0f );
|
||||
printf( " Loading 3D models: %.3f ms\n",
|
||||
(float)( stats_end_models_Load_Time - stats_start_models_Load_Time ) / 1000.0f );
|
||||
COBJECT2D_STATS::Instance().PrintStats();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
{
|
||||
// Calculation time in seconds
|
||||
const double calculation_time = (double)( GetRunningMicroSecs() -
|
||||
stats_startReloadTime) / 1e6;
|
||||
|
||||
aStatusTextReporter->Report( wxString::Format( _( "Reload time %.3f s" ),
|
||||
calculation_time ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::add_triangle_top_bot( CLAYER_TRIANGLES *aDst,
|
||||
const SFVEC2F &v0,
|
||||
const SFVEC2F &v1,
|
||||
const SFVEC2F &v2,
|
||||
float top,
|
||||
float bot )
|
||||
{
|
||||
aDst->m_layer_bot_triangles->AddTriangle( SFVEC3F( v0.x, v0.y, bot ),
|
||||
SFVEC3F( v1.x, v1.y, bot ),
|
||||
SFVEC3F( v2.x, v2.y, bot ) );
|
||||
|
||||
aDst->m_layer_top_triangles->AddTriangle( SFVEC3F( v2.x, v2.y, top ),
|
||||
SFVEC3F( v1.x, v1.y, top ),
|
||||
SFVEC3F( v0.x, v0.y, top ) );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::get_layer_z_pos ( PCB_LAYER_ID aLayerID,
|
||||
float &aOutZtop,
|
||||
float &aOutZbot ) const
|
||||
{
|
||||
aOutZbot = m_settings.GetLayerBottomZpos3DU( aLayerID );
|
||||
aOutZtop = m_settings.GetLayerTopZpos3DU( aLayerID );
|
||||
|
||||
if( aOutZtop < aOutZbot )
|
||||
{
|
||||
float tmpFloat = aOutZbot;
|
||||
aOutZbot = aOutZtop;
|
||||
aOutZtop = tmpFloat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_cylinder( const SFVEC2F &aCenter,
|
||||
float aInnerRadius,
|
||||
float aOuterRadius,
|
||||
float aZtop,
|
||||
float aZbot,
|
||||
unsigned int aNr_sides_per_circle,
|
||||
CLAYER_TRIANGLES *aDstLayer )
|
||||
{
|
||||
std::vector< SFVEC2F > innerContour;
|
||||
std::vector< SFVEC2F > outerContour;
|
||||
|
||||
generate_ring_contour( aCenter,
|
||||
aInnerRadius,
|
||||
aOuterRadius,
|
||||
aNr_sides_per_circle,
|
||||
innerContour,
|
||||
outerContour,
|
||||
false );
|
||||
|
||||
for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
|
||||
{
|
||||
const SFVEC2F &vi0 = innerContour[i + 0];
|
||||
const SFVEC2F &vi1 = innerContour[i + 1];
|
||||
const SFVEC2F &vo0 = outerContour[i + 0];
|
||||
const SFVEC2F &vo1 = outerContour[i + 1];
|
||||
|
||||
aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZtop ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZtop ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZtop ) );
|
||||
|
||||
aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
|
||||
SFVEC3F( vo1.x, vo1.y, aZbot ),
|
||||
SFVEC3F( vo0.x, vo0.y, aZbot ),
|
||||
SFVEC3F( vi0.x, vi0.y, aZbot ) );
|
||||
}
|
||||
|
||||
aDstLayer->AddToMiddleContourns( outerContour, aZbot, aZtop, true );
|
||||
aDstLayer->AddToMiddleContourns( innerContour, aZbot, aZtop, false );
|
||||
}
|
||||
|
||||
|
||||
void C3D_RENDER_OGL_LEGACY::generate_3D_Vias_and_Pads()
|
||||
{
|
||||
if( m_settings.GetStats_Nr_Vias() )
|
||||
{
|
||||
const unsigned int reserve_nr_triangles_estimation =
|
||||
m_settings.GetNrSegmentsCircle( m_settings.GetStats_Med_Via_Hole_Diameter3DU() ) *
|
||||
8 *
|
||||
m_settings.GetStats_Nr_Vias();
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangleVIA = new CLAYER_TRIANGLES( reserve_nr_triangles_estimation );
|
||||
|
||||
// Insert plated vertical holes inside the board
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Insert vias holes (vertical cylinders)
|
||||
for( const TRACK* track = m_settings.GetBoard()->m_Track;
|
||||
track;
|
||||
track = track->Next() )
|
||||
{
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
{
|
||||
const VIA *via = static_cast<const VIA*>(track);
|
||||
|
||||
const float holediameter = via->GetDrillValue() * m_settings.BiuTo3Dunits();
|
||||
const float thickness = m_settings.GetCopperThickness3DU();
|
||||
const int nrSegments = m_settings.GetNrSegmentsCircle( via->GetDrillValue() );
|
||||
const double correctionFactor = m_settings.GetCircleCorrectionFactor( nrSegments );
|
||||
const float hole_inner_radius = ( holediameter / 2.0f ) * correctionFactor;
|
||||
|
||||
const SFVEC2F via_center( via->GetStart().x * m_settings.BiuTo3Dunits(),
|
||||
-via->GetStart().y * m_settings.BiuTo3Dunits() );
|
||||
|
||||
PCB_LAYER_ID top_layer, bottom_layer;
|
||||
via->LayerPair( &top_layer, &bottom_layer );
|
||||
|
||||
float ztop, zbot, dummy;
|
||||
|
||||
get_layer_z_pos( top_layer, ztop, dummy );
|
||||
get_layer_z_pos( bottom_layer, dummy, zbot );
|
||||
|
||||
wxASSERT( zbot < ztop );
|
||||
|
||||
generate_cylinder( via_center,
|
||||
hole_inner_radius,
|
||||
hole_inner_radius + thickness,
|
||||
ztop,
|
||||
zbot,
|
||||
nrSegments,
|
||||
layerTriangleVIA );
|
||||
}
|
||||
}
|
||||
|
||||
m_ogl_disp_list_via = new CLAYERS_OGL_DISP_LISTS( *layerTriangleVIA,
|
||||
0,
|
||||
0.0f,
|
||||
0.0f );
|
||||
|
||||
delete layerTriangleVIA;
|
||||
}
|
||||
|
||||
|
||||
if( m_settings.GetStats_Nr_Holes() > 0 )
|
||||
{
|
||||
SHAPE_POLY_SET tht_outer_holes_poly; // Stores the outer poly of the copper holes (the pad)
|
||||
SHAPE_POLY_SET tht_inner_holes_poly; // Stores the inner poly of the copper holes (the hole)
|
||||
|
||||
tht_outer_holes_poly.RemoveAllContours();
|
||||
tht_inner_holes_poly.RemoveAllContours();
|
||||
|
||||
// Insert pads holes (vertical cylinders)
|
||||
for( const MODULE* module = m_settings.GetBoard()->m_Modules;
|
||||
module;
|
||||
module = module->Next() )
|
||||
{
|
||||
for( const D_PAD* pad = module->PadsList(); pad; pad = pad->Next() )
|
||||
{
|
||||
if( pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
|
||||
{
|
||||
const wxSize drillsize = pad->GetDrillSize();
|
||||
const bool hasHole = drillsize.x && drillsize.y;
|
||||
|
||||
if( !hasHole )
|
||||
continue;
|
||||
|
||||
// we use the hole diameter to calculate the seg count.
|
||||
// for round holes, drillsize.x == drillsize.y
|
||||
// for slots, the diameter is the smaller of (drillsize.x, drillsize.y)
|
||||
int copperThickness = m_settings.GetCopperThicknessBIU();
|
||||
int radius = std::min( drillsize.x, drillsize.y ) / 2 + copperThickness;
|
||||
int nrSegments = m_settings.GetNrSegmentsCircle( radius * 2 );
|
||||
double correctionFactor = m_settings.GetCircleCorrectionFactor( nrSegments );
|
||||
int correction = radius * ( correctionFactor - 1 );
|
||||
|
||||
pad->BuildPadDrillShapePolygon( tht_outer_holes_poly,
|
||||
copperThickness + correction,
|
||||
nrSegments );
|
||||
|
||||
pad->BuildPadDrillShapePolygon( tht_inner_holes_poly,
|
||||
correction,
|
||||
nrSegments );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Subtract the holes
|
||||
tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly, SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
|
||||
CCONTAINER2D holesContainer;
|
||||
|
||||
Convert_shape_line_polygon_to_triangles( tht_outer_holes_poly,
|
||||
holesContainer,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
(const BOARD_ITEM &)*m_settings.GetBoard() );
|
||||
|
||||
const LIST_OBJECT2D &listHolesObject2d = holesContainer.GetList();
|
||||
|
||||
if( listHolesObject2d.size() > 0 )
|
||||
{
|
||||
float layer_z_top, layer_z_bot, dummy;
|
||||
|
||||
get_layer_z_pos( F_Cu, layer_z_top, dummy );
|
||||
get_layer_z_pos( B_Cu, dummy, layer_z_bot );
|
||||
|
||||
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listHolesObject2d.size() );
|
||||
|
||||
// Convert the list of objects(triangles) to triangle layer structure
|
||||
for( LIST_OBJECT2D::const_iterator itemOnLayer = listHolesObject2d.begin();
|
||||
itemOnLayer != listHolesObject2d.end();
|
||||
++itemOnLayer )
|
||||
{
|
||||
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||
|
||||
wxASSERT( object2d_A->GetObjectType() == OBJ2D_TRIANGLE );
|
||||
|
||||
const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
|
||||
|
||||
const SFVEC2F &v1 = tri->GetP1();
|
||||
const SFVEC2F &v2 = tri->GetP2();
|
||||
const SFVEC2F &v3 = tri->GetP3();
|
||||
|
||||
add_triangle_top_bot( layerTriangles, v1, v2, v3,
|
||||
layer_z_top, layer_z_bot );
|
||||
}
|
||||
|
||||
wxASSERT( tht_outer_holes_poly.OutlineCount() > 0 );
|
||||
|
||||
if( tht_outer_holes_poly.OutlineCount() > 0 )
|
||||
{
|
||||
layerTriangles->AddToMiddleContourns( tht_outer_holes_poly,
|
||||
layer_z_bot, layer_z_top,
|
||||
m_settings.BiuTo3Dunits(),
|
||||
false );
|
||||
|
||||
m_ogl_disp_list_pads_holes = new CLAYERS_OGL_DISP_LISTS(
|
||||
*layerTriangles,
|
||||
m_ogl_circle_texture, // not need
|
||||
layer_z_top, layer_z_top );
|
||||
}
|
||||
|
||||
delete layerTriangles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function will get models from the cache and load it to openGL lists
|
||||
* in the form of C_OGL_3DMODEL. So this map of models will work as a local
|
||||
* cache for this render. (cache based on C_OGL_3DMODEL with associated
|
||||
* openGL lists in GPU memory)
|
||||
*/
|
||||
void C3D_RENDER_OGL_LEGACY::load_3D_models( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
if( (!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL )) &&
|
||||
(!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT )) &&
|
||||
(!m_settings.GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL )) )
|
||||
return;
|
||||
|
||||
// Go for all modules
|
||||
for( const MODULE* module = m_settings.GetBoard()->m_Modules;
|
||||
module; module = module->Next() )
|
||||
{
|
||||
if( !module->Models().empty() )
|
||||
{
|
||||
// Get the list of model files for this model
|
||||
auto sM = module->Models().begin();
|
||||
auto eM = module->Models().end();
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
if( !sM->m_Filename.empty() )
|
||||
{
|
||||
if( aStatusTextReporter )
|
||||
{
|
||||
// Display the short filename of the 3D model loaded:
|
||||
// (the full name is usually too long to be displayed)
|
||||
wxFileName fn( sM->m_Filename );
|
||||
wxString msg;
|
||||
msg.Printf( _( "Loading %s" ), fn.GetFullName() );
|
||||
aStatusTextReporter->Report( msg );
|
||||
}
|
||||
|
||||
// Check if the model is not present in our cache map
|
||||
// (Not already loaded in memory)
|
||||
if( m_3dmodel_map.find( sM->m_Filename ) == m_3dmodel_map.end() )
|
||||
{
|
||||
// It is not present, try get it from cache
|
||||
const S3DMODEL *modelPtr =
|
||||
m_settings.Get3DCacheManager()->GetModel( sM->m_Filename );
|
||||
|
||||
// only add it if the return is not NULL
|
||||
if( modelPtr )
|
||||
{
|
||||
C_OGL_3DMODEL* ogl_model =
|
||||
new C_OGL_3DMODEL( *modelPtr,
|
||||
m_settings.MaterialModeGet() );
|
||||
|
||||
if( ogl_model )
|
||||
m_3dmodel_map[ sM->m_Filename ] = ogl_model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++sM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user